mirror of
https://github.com/drone-plugins/drone-download.git
synced 2026-06-04 18:24:21 +08:00
Use the drone plugin lib
This commit is contained in:
+145
@@ -0,0 +1,145 @@
|
||||
// Copyright (c) 2020, the Drone Plugins project authors.
|
||||
// Please see the AUTHORS file for details. All rights reserved.
|
||||
// Use of this source code is governed by an Apache 2.0 license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Settings for the plugin.
|
||||
type Settings struct {
|
||||
Source string
|
||||
Destination string
|
||||
Authorization string
|
||||
Username string
|
||||
Password string
|
||||
MD5 string
|
||||
SHA256 string
|
||||
|
||||
destination string
|
||||
}
|
||||
|
||||
// Validate handles the settings validation of the plugin.
|
||||
func (p *Plugin) Validate() error {
|
||||
// Verify the source url
|
||||
source := p.settings.Source
|
||||
if source == "" {
|
||||
return fmt.Errorf("no source provided")
|
||||
}
|
||||
|
||||
u, err := url.Parse(source)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse url %s: %w", source, err)
|
||||
}
|
||||
|
||||
// Verify the destination
|
||||
destination := filepath.ToSlash(p.settings.Destination)
|
||||
if destination == "" {
|
||||
destination = path.Base(u.Path)
|
||||
} else if strings.HasSuffix(destination, "/") {
|
||||
destination = path.Join(destination, path.Base(u.Path))
|
||||
}
|
||||
|
||||
destination = filepath.FromSlash(path.Clean(destination))
|
||||
err = os.MkdirAll(filepath.Dir(destination), os.ModePerm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating directory failed: %w", err)
|
||||
}
|
||||
p.settings.destination = destination
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Execute provides the implementation of the plugin.
|
||||
func (p *Plugin) Execute() error {
|
||||
req, err := http.NewRequestWithContext(
|
||||
p.network.Context,
|
||||
"GET",
|
||||
p.settings.Source,
|
||||
nil,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("initializing request failed: %w", err)
|
||||
}
|
||||
|
||||
p.addAuth(req)
|
||||
|
||||
client := p.network.Client
|
||||
client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
||||
p.addAuth(req)
|
||||
return nil
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("executing request failed: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("request failed, status %s", http.StatusText(resp.StatusCode))
|
||||
}
|
||||
|
||||
target, err := os.Create(p.settings.destination)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating destination failed: %w", err)
|
||||
}
|
||||
defer target.Close()
|
||||
|
||||
_, err = io.Copy(target, resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("copying destination failed: %w", err)
|
||||
}
|
||||
|
||||
var h hash.Hash
|
||||
exp := ""
|
||||
|
||||
if p.settings.SHA256 != "" {
|
||||
exp = p.settings.SHA256
|
||||
h = sha256.New()
|
||||
} else if p.settings.MD5 != "" {
|
||||
exp = p.settings.MD5
|
||||
h = md5.New()
|
||||
}
|
||||
|
||||
if exp != "" {
|
||||
target.Seek(0, 0)
|
||||
|
||||
if _, err := io.Copy(h, target); err != nil {
|
||||
defer os.Remove(target.Name())
|
||||
return fmt.Errorf("failed to compare checksum: %w", err)
|
||||
}
|
||||
|
||||
check := fmt.Sprintf("%x", h.Sum(nil))
|
||||
|
||||
if exp != check {
|
||||
defer os.Remove(target.Name())
|
||||
return fmt.Errorf("checksum doesn't match, got %s and expected %s", check, exp)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Plugin) addAuth(req *http.Request) {
|
||||
if p.settings.Username != "" && p.settings.Password != "" {
|
||||
req.SetBasicAuth(p.settings.Username, p.settings.Password)
|
||||
}
|
||||
if p.settings.Authorization != "" {
|
||||
req.Header.Add("Authorization", p.settings.Authorization)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2020, the Drone Plugins project authors.
|
||||
// Please see the AUTHORS file for details. All rights reserved.
|
||||
// Use of this source code is governed by an Apache 2.0 license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestValidate(t *testing.T) {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
func TestExecute(t *testing.T) {
|
||||
t.Skip()
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) 2020, the Drone Plugins project authors.
|
||||
// Please see the AUTHORS file for details. All rights reserved.
|
||||
// Use of this source code is governed by an Apache 2.0 license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"github.com/drone-plugins/drone-plugin-lib/drone"
|
||||
)
|
||||
|
||||
// Plugin implements drone.Plugin to provide the plugin implementation.
|
||||
type Plugin struct {
|
||||
settings Settings
|
||||
pipeline drone.Pipeline
|
||||
network drone.Network
|
||||
}
|
||||
|
||||
// New initializes a plugin from the given Settings, Pipeline, and Network.
|
||||
func New(settings Settings, pipeline drone.Pipeline, network drone.Network) drone.Plugin {
|
||||
return &Plugin{
|
||||
settings: settings,
|
||||
pipeline: pipeline,
|
||||
network: network,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2020, the Drone Plugins project authors.
|
||||
// Please see the AUTHORS file for details. All rights reserved.
|
||||
// Use of this source code is governed by an Apache 2.0 license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPlugin(t *testing.T) {
|
||||
t.Skip()
|
||||
}
|
||||
Reference in New Issue
Block a user