diff --git a/.gitignore b/.gitignore index cf90ddaa..b9dcbee9 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,6 @@ maven-metadata* download n3dr* -maven-releases \ No newline at end of file +maven-releases +vendor +.snapcraft diff --git a/.travis.yml b/.travis.yml index 9ced535a..714e1c65 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ # windows. language: go go: - - 1.14.2 + - 1.14.4 env: global: - ARTIFACT_PUBLICATION=true diff --git a/CHANGELOG.md b/CHANGELOG.md index b92944d3..0a40af3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] -## Changed +None + +## [3.6.2] - 2020-07-08 +### Added +- Asciicast +- Configuration instructions minimal permissions n3dr user + +### Changed - Installation instructions +### Fixed +- Couple of code smells reported by sonar cloud + +### Removed +- Superfluous go modules + ## [3.6.1] - 2020-06-26 ### Fixed - Solved broken Darwin and Windows publication diff --git a/README.md b/README.md index 7f1f2f22..dd2c1d4b 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,28 @@ brew install n3dr choco install n3dr ```` -## Check the help menu +## Configuration + +### N3DR download user + +Create a user, e.g. n3dr-download in Nexus3, create a role, e.g. n3dr-download +and assign the following roles: + +* nx-repository-view-*-*-browse +* nx-repository-view-*-*-read + +### N3DR upload user + +In order to upload artifacts, additional privileges are required: + +* nx-repository-view-*-*-add +* nx-repository-view-*-*-edit + +## Usage + +<a href="https://asciinema.org/a/346048?autoplay=1"><img src="https://asciinema.org/a/346048.png" width="836"/></a> + +### Check the help menu ``` user@computer:~/dev$ ./n3dr-linux -h @@ -112,7 +133,7 @@ and set the permissions to 400 by issuing: chmod 400 ~/.n3dr.yaml ``` -## Backup artifacts from a certain repository +### Backup artifacts from a certain repository All artifacts from a repository will be stored in a download folder when the following command is run: @@ -121,7 +142,7 @@ the following command is run: ./n3dr-linux backup -u admin -n http://localhost:8081 -r maven-releases ``` -## Backup all repositories +### Backup all repositories All artifacts from various repositories will be stored in a download folder when the following command is issued: @@ -135,7 +156,7 @@ Note: a new folder will be created for every repository: * download/maven-public * download/maven-releases -## Backup only certain artifacts +### Backup only certain artifacts It is possible to only download artifacts that match a regular expression. If one would like to download all artifacts from 'some/group42' then one could do @@ -156,7 +177,7 @@ the `-x` option as well: In order to add all archives to a zip archive, one has to use the --zip or -z flag. -## Upload all artifacts to a certain repository +### Upload all artifacts to a certain repository It is possible to upload all JARs that reside in a folder by running the following command: @@ -165,7 +186,7 @@ running the following command: ./n3dr-linux upload -u admin -n http://localhost:8081 -r maven-public ``` -## "Clone" a Nexus3 repository +### "Clone" a Nexus3 repository Suppose that one has created a new Nexus3 repository, e.g. NexusNEW and that one would like to copy the content of the old repository, e.g. NexusOLD, then @@ -180,7 +201,7 @@ n3dr upload -u <new-target-nexus3-user> -n <new-target-nexus3-server-url> \ -r <new-repo-target-name> ``` -## Backup to OCI Object Storage +### Backup to OCI Object Storage `n3dr` supports backing up to [OCI Object Storage](https://www.oracle.com/cloud/storage/object-storage.html). To enable this option you need to - Configure OCI environment and secrets locally: https://docs.cloud.oracle.com/en-us/iaas/Content/API/Concepts/sdkconfig.htm diff --git a/cli/backup_test.go b/cli/backup_test.go index 9474ddaf..290012ab 100644 --- a/cli/backup_test.go +++ b/cli/backup_test.go @@ -9,8 +9,9 @@ import ( ) const ( - errMsg = "Not equal. Expected: %d. Actual: %d." - errMsgTxt = "Error incorrect. Expected: %v. Actual: %v" + errMsg = "Not equal. Expected: %d. Actual: %d." + errMsgTxt = "Incorrect. Expected: %v. Actual: %v" + testFileJar100 = "download/maven-releases/file1/file1/1.0.0/file1-1.0.0.jar" ) func TestContinuationTokenHash(t *testing.T) { @@ -63,7 +64,7 @@ func TestStoreArtifactsOnDisk(t *testing.T) { expectedDownloads := []string{ "download/.gitkeep", - "download/maven-releases/file1/file1/1.0.0/file1-1.0.0.jar", + testFileJar100, "download/maven-releases/file1/file1/1.0.0/file1-1.0.0.pom", "download/maven-releases/file1/file1/maven-metadata.xml", "download/maven-releases/file2/file2/1.0.0/file2-1.0.0.jar", @@ -142,7 +143,7 @@ func TestDownloadArtifact(t *testing.T) { expectedError := "URL: 'http://releasesoftwaremoreoften.com' does not seem to contain an artifactName" if actualError.Error() != expectedError { - t.Errorf("Error incorrect. Expected: %v. Actual: %v", expectedError, actualError) + t.Errorf(errMsgTxt, expectedError, actualError) } } @@ -152,15 +153,15 @@ func TestHashFileMD5(t *testing.T) { expectedError := "open file1/file1/1.0.0/file1-1.0.0.jar: no such file or directory" if actualError.Error() != expectedError { - t.Errorf("Error incorrect. Expected: %v. Actual: %v", expectedError, actualError) + t.Errorf(errMsgTxt, expectedError, actualError) } - file = "download/maven-releases/file1/file1/1.0.0/file1-1.0.0.jar" + file = testFileJar100 expectedResult := "ad60407c083b4ecc372614b8fcd9f305" result, _ := HashFileMD5(file) if result != expectedResult { - t.Errorf("Output incorrect. Expected: %v. Actual: %v", expectedResult, result) + t.Errorf(errMsgTxt, expectedResult, result) } } @@ -170,15 +171,15 @@ func TestFileExists(t *testing.T) { expectedResult := false if result != expectedResult { - t.Errorf("Output incorrect. Expected: %v. Actual: %v", expectedResult, result) + t.Errorf(errMsgTxt, expectedResult, result) } - file = "download/maven-releases/file1/file1/1.0.0/file1-1.0.0.jar" + file = testFileJar100 result = fileExists(file) expectedResult = true if result != expectedResult { - t.Errorf("Output incorrect. Expected: %v. Actual: %v", expectedResult, result) + t.Errorf(errMsgTxt, expectedResult, result) } } diff --git a/cli/oci.go b/cli/oci.go index 94420eed..54d937b5 100644 --- a/cli/oci.go +++ b/cli/oci.go @@ -5,20 +5,20 @@ import ( "encoding/base64" "encoding/hex" "fmt" - "github.com/oracle/oci-go-sdk/common" - "github.com/oracle/oci-go-sdk/objectstorage" - log "github.com/sirupsen/logrus" - "github.com/spf13/viper" "io" "os" "path/filepath" "strings" + + "github.com/oracle/oci-go-sdk/common" + "github.com/oracle/oci-go-sdk/objectstorage" + log "github.com/sirupsen/logrus" + "github.com/spf13/viper" ) func ociBackup(Bucketname string, Filename string) error { o, err := objectstorage.NewObjectStorageClientWithConfigurationProvider(common.DefaultConfigProvider()) if err != nil { - log.Error("Error:", err) return err } @@ -26,7 +26,6 @@ func ociBackup(Bucketname string, Filename string) error { namespace, err := getNamespace(ctx, o) if err != nil { - log.Error("Error:", err) return err } @@ -37,25 +36,21 @@ func ociBackup(Bucketname string, Filename string) error { } if err != nil { - log.Error("Error:", err) return err } for _, f := range filename { file, err := os.Open(f) if err != nil { - log.Error("Error:", err) return err } defer file.Close() fi, err := file.Stat() if err != nil { - log.Error("Error:", err) return err } err = putObject(ctx, o, namespace, Bucketname, f, fi.Size(), file, nil) if err != nil { - log.Error("Error:", err) return err } @@ -65,7 +60,6 @@ func ociBackup(Bucketname string, Filename string) error { } if err != nil { - log.Error(err) return err } } @@ -76,7 +70,6 @@ func getNamespace(ctx context.Context, c objectstorage.ObjectStorageClient) (str request := objectstorage.GetNamespaceRequest{} r, err := c.GetNamespace(ctx, request) if err != nil { - log.Error("Error:", err) return "Error", err } return *r.Value, nil @@ -93,7 +86,6 @@ func putObject(ctx context.Context, c objectstorage.ObjectStorageClient, namespa } _, err := c.PutObject(ctx, request) if err != nil { - log.Error("Error:", err) return err } log.Debug("You have uploaded file " + objectname + " in bucket " + bucketname + "\n") @@ -103,7 +95,6 @@ func putObject(ctx context.Context, c objectstorage.ObjectStorageClient, namespa func findObject(bucketname, objectname string, md5sum string) (bool, error) { o, err := objectstorage.NewObjectStorageClientWithConfigurationProvider(common.DefaultConfigProvider()) if err != nil { - log.Error("Error:", err) return false, err } @@ -111,7 +102,6 @@ func findObject(bucketname, objectname string, md5sum string) (bool, error) { namespace, err := getNamespace(ctx, o) if err != nil { - log.Error("Error:", err) return false, err } @@ -126,7 +116,6 @@ func findObject(bucketname, objectname string, md5sum string) (bool, error) { if strings.Contains(err.Error(), "ObjectNotFound") { return false, nil } - log.Error("Error:", err) return false, err } diff --git a/cmd/root.go b/cmd/root.go index 6892a552..62cfa0cb 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -15,10 +15,10 @@ package cmd import ( + "crypto/tls" "fmt" - "os" "net/http" - "crypto/tls" + "os" homedir "github.com/mitchellh/go-homedir" log "github.com/sirupsen/logrus" @@ -82,6 +82,7 @@ func initConfig() { fmt.Println(err) os.Exit(1) } + log.Infof("HomeDir: '%v'", home) viper.AddConfigPath(home) // Search config in home directory with name ".n3dr" (without extension). viper.SetConfigName(".n3dr") diff --git a/go.mod b/go.mod index f3168704..a57743a7 100644 --- a/go.mod +++ b/go.mod @@ -22,19 +22,10 @@ require ( github.com/sirupsen/logrus v1.4.2 github.com/spf13/cobra v0.0.3 github.com/spf13/viper v1.3.2 - github.com/stretchr/testify v1.2.2 github.com/svenfuchs/jq v0.0.0-20180603193138-b038733a5990 github.com/thedevsaddam/gojsonq v2.2.0+incompatible - github.com/vektra/mockery v1.1.2 // indirect github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect - github.com/yuin/goldmark v1.1.30 // indirect - golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 // indirect - golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect - golang.org/x/mod v0.3.0 // indirect - golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2 // indirect - golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a // indirect golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 // indirect golang.org/x/text v0.3.2 // indirect - golang.org/x/tools v0.0.0-20200521211927-2b542361a4fc // indirect gopkg.in/cheggaaa/pb.v1 v1.0.28 ) diff --git a/go.sum b/go.sum index 50cfa5a2..816690c8 100644 --- a/go.sum +++ b/go.sum @@ -87,39 +87,16 @@ github.com/thedevsaddam/gojsonq v2.2.0+incompatible/go.mod h1:RBcQaITThgJAAYKH7F github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ulikunitz/xz v0.5.6 h1:jGHAfXawEGZQ3blwU5wnWKQJvAraT7Ftq9EXjnXYgt8= github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= -github.com/vektra/mockery v1.1.2 h1:uc0Yn67rJpjt8U/mAZimdCKn9AeA97BOkjpmtBSlfP4= -github.com/vektra/mockery v1.1.2/go.mod h1:VcfZjKaFOPO+MpN4ZvwPjs4c48lkq1o3Ym8yHZJu0jU= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a h1:1n5lsVfiQW3yfsRGu98756EH1YthsFqr/5mxHduZW2A= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= @@ -127,14 +104,6 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200323144430-8dcfad9e016e/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200521211927-2b542361a4fc h1:6m2YO+AmBApbUOmhsghW+IfRyZOY4My4UYvQQrEpHfY= -golang.org/x/tools v0.0.0-20200521211927-2b542361a4fc/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk= diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index ee65db4a..6fcc5bba 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -27,3 +27,8 @@ parts: plugin: go source: . go-importpath: github.com/030/n3dr + override-build: | + GO111MODULE=on CGO_ENABLED=0 go build -ldflags "-X n3dr/cmd.Version=3.6.2" -o $SNAPCRAFT_PART_INSTALL/n3dr + $SNAPCRAFT_PART_INSTALL/n3dr --version + stage: + - "n3dr"