mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-06-26 08:51:37 +00:00
Merge pull request #1553 from linuxdataflow/feat/pls/jfrog-support
Add support for JFrog artifactory.
This commit is contained in:
@@ -100,6 +100,9 @@ jobs:
|
||||
AZURE_STORAGE_ACCESS_KEY: "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
JFROG_URL: ${{ secrets.JFROG_URL }}
|
||||
JFROG_USERNAME: ${{ secrets.JFROG_USERNAME }}
|
||||
JFROG_PASSWORD: ${{ secrets.JFROG_PASSWORD }}
|
||||
run: |
|
||||
sudo mkdir -p /srv ; sudo chown runner /srv
|
||||
mkdir -p out/coverage
|
||||
|
||||
@@ -45,6 +45,7 @@ jobs:
|
||||
# When `install-mode` is `binary` (default) the value can be v1.2 or v1.2.3 or `latest` to use the latest version.
|
||||
# When `install-mode` is `goinstall` the value can be v1.2.3, `latest`, or the hash of a commit.
|
||||
version: v1.64.5
|
||||
args: --timeout=10m
|
||||
|
||||
# Optional: working directory, useful for monorepos
|
||||
# working-directory: somedir
|
||||
|
||||
@@ -53,6 +53,11 @@ func createTestConfig() *os.File {
|
||||
"bucket": "bucket-gcs",
|
||||
},
|
||||
},
|
||||
"JFrogPublishEndpoints": map[string]map[string]string{
|
||||
"test-jfrog": {
|
||||
"url": "http://jfrog.example.com",
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil
|
||||
@@ -186,6 +191,18 @@ func (s *APISuite) TestTruthy(c *C) {
|
||||
c.Check(truthy(gin.H{}), Equals, true)
|
||||
}
|
||||
|
||||
func (s *APISuite) TestGetJFrogEndpoints(c *C) {
|
||||
response, err := s.HTTPRequest("GET", "/api/jfrog", nil)
|
||||
c.Assert(err, IsNil)
|
||||
c.Check(response.Code, Equals, 200)
|
||||
|
||||
var endpoints []string
|
||||
err = json.Unmarshal(response.Body.Bytes(), &endpoints)
|
||||
c.Assert(err, IsNil)
|
||||
sort.Strings(endpoints)
|
||||
c.Check(endpoints, DeepEquals, []string{"test-jfrog"})
|
||||
}
|
||||
|
||||
func (s *APISuite) TestGetS3Endpoints(c *C) {
|
||||
response, err := s.HTTPRequest("GET", "/api/s3", nil)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Summary JFrog repositories
|
||||
// @Description **Get list of JFrog repositories**
|
||||
// @Description
|
||||
// @Description List configured JFrog publish endpoints.
|
||||
// @Tags Status
|
||||
// @Produce json
|
||||
// @Success 200 {array} string "List of JFrog publish endpoints"
|
||||
// @Router /api/jfrog [get]
|
||||
func apiJFrogList(c *gin.Context) {
|
||||
keys := []string{}
|
||||
for k := range context.Config().JFrogPublishRoots {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
c.JSON(200, keys)
|
||||
}
|
||||
@@ -178,6 +178,7 @@ func Router(c *ctx.AptlyContext) http.Handler {
|
||||
{
|
||||
api.GET("/s3", apiS3List)
|
||||
api.GET("/gcs", apiGCSList)
|
||||
api.GET("/jfrog", apiJFrogList)
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"github.com/aptly-dev/aptly/files"
|
||||
"github.com/aptly-dev/aptly/gcs"
|
||||
"github.com/aptly-dev/aptly/http"
|
||||
"github.com/aptly-dev/aptly/jfrog"
|
||||
"github.com/aptly-dev/aptly/pgp"
|
||||
"github.com/aptly-dev/aptly/s3"
|
||||
"github.com/aptly-dev/aptly/swift"
|
||||
@@ -476,6 +477,18 @@ func (context *AptlyContext) GetPublishedStorage(name string) aptly.PublishedSto
|
||||
if err != nil {
|
||||
Fatal(err)
|
||||
}
|
||||
} else if strings.HasPrefix(name, "jfrog:") {
|
||||
params, ok := context.config().JFrogPublishRoots[name[6:]]
|
||||
if !ok {
|
||||
Fatal(fmt.Errorf("published JFrog storage %v not configured", name[6:]))
|
||||
}
|
||||
|
||||
var err error
|
||||
publishedStorage, err = jfrog.NewPublishedStorage(
|
||||
name[6:], params)
|
||||
if err != nil {
|
||||
Fatal(err)
|
||||
}
|
||||
} else {
|
||||
Fatal(fmt.Errorf("unknown published storage format: %v", name))
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/aptly-dev/aptly/utils"
|
||||
"github.com/smira/flag"
|
||||
|
||||
. "gopkg.in/check.v1"
|
||||
@@ -87,3 +88,64 @@ func (s *AptlyContextSuite) TestGetPublishedStorageBadFS(c *C) {
|
||||
&FatalError{ReturnCode: 1, Message: fmt.Sprintf("error loading config file %s/.aptly.conf: invalid yaml (EOF) or json (EOF)",
|
||||
os.Getenv("HOME"))})
|
||||
}
|
||||
|
||||
func (s *AptlyContextSuite) TestGetPublishedStorageJFrogConfigured(c *C) {
|
||||
prevConfig := utils.Config
|
||||
defer func() { utils.Config = prevConfig }()
|
||||
|
||||
s.context.configLoaded = true
|
||||
utils.Config.RootDir = c.MkDir()
|
||||
utils.Config.JFrogPublishRoots = map[string]utils.JFrogPublishRoot{
|
||||
"test": {
|
||||
Repository: "aptly-repo",
|
||||
Url: "https://example.jfrog.local/artifactory",
|
||||
AccessToken: "token",
|
||||
Prefix: "public",
|
||||
},
|
||||
}
|
||||
|
||||
storage := s.context.GetPublishedStorage("jfrog:test")
|
||||
c.Assert(storage, NotNil)
|
||||
c.Assert(fmt.Sprintf("%v", storage), Equals, "jfrog:aptly-repo:public")
|
||||
|
||||
// Ensure we get the cached object on repeated lookups.
|
||||
storageAgain := s.context.GetPublishedStorage("jfrog:test")
|
||||
c.Assert(storageAgain, Equals, storage)
|
||||
}
|
||||
|
||||
func (s *AptlyContextSuite) TestGetPublishedStorageJFrogMissing(c *C) {
|
||||
prevConfig := utils.Config
|
||||
defer func() { utils.Config = prevConfig }()
|
||||
|
||||
s.context.configLoaded = true
|
||||
utils.Config.JFrogPublishRoots = map[string]utils.JFrogPublishRoot{}
|
||||
|
||||
c.Assert(func() { s.context.GetPublishedStorage("jfrog:missing") },
|
||||
FatalErrorPanicMatches,
|
||||
&FatalError{ReturnCode: 1, Message: "published JFrog storage missing not configured"})
|
||||
}
|
||||
|
||||
func (s *AptlyContextSuite) TestGetPublishedStorageJFrogInitError(c *C) {
|
||||
prevConfig := utils.Config
|
||||
defer func() { utils.Config = prevConfig }()
|
||||
|
||||
s.context.configLoaded = true
|
||||
utils.Config.JFrogPublishRoots = map[string]utils.JFrogPublishRoot{
|
||||
"broken": {
|
||||
Repository: "aptly-repo",
|
||||
Url: "ssh://example.local/artifactory",
|
||||
},
|
||||
}
|
||||
|
||||
defer func() {
|
||||
obtained := recover()
|
||||
c.Assert(obtained, NotNil)
|
||||
|
||||
fatalErr, ok := obtained.(*FatalError)
|
||||
c.Assert(ok, Equals, true)
|
||||
c.Check(fatalErr.ReturnCode, Equals, 1)
|
||||
c.Check(fatalErr.Message, Matches, `error creating jfrog manager: .*`)
|
||||
}()
|
||||
|
||||
s.context.GetPublishedStorage("jfrog:broken")
|
||||
}
|
||||
|
||||
Vendored
+29
@@ -196,6 +196,35 @@ filesystem_publish_endpoints:
|
||||
#
|
||||
# `aptly publish snapshot wheezy-main s3:test:`
|
||||
#
|
||||
|
||||
# JFrog Artifactory Endpoint Support
|
||||
#
|
||||
# aptly can be configured to publish repositories directly to JFrog Artifactory. First,
|
||||
# publishing endpoints should be described in the aptly configuration file.
|
||||
#
|
||||
# The destination Artifactory repo should be of the "generic" type, not "debian".
|
||||
#
|
||||
# In order to publish to JFrog, specify endpoint as `jfrog:endpoint-name:` before
|
||||
# publishing prefix on the command line, e.g.:
|
||||
#
|
||||
# `aptly publish snapshot wheezy-main jfrog:test:`
|
||||
#
|
||||
jfrog_publish_endpoints:
|
||||
# # Endpoint Name
|
||||
# test:
|
||||
# # JFrog URL
|
||||
# url: "https://artifactory.example.com/artifactory/"
|
||||
# # Repository
|
||||
# repository: apt-local
|
||||
# # Jfrog credentials to authenticate to Artifactory. If not supplied, the
|
||||
# # environment variables `JFROG_USERNAME`, `JFROG_PASSWORD`, `JFROG_APIKEY`,
|
||||
# # and `JFROG_ACCESSTOKEN` can be used
|
||||
# # Authentication requires one of: user+pass, api key, or access token
|
||||
# username: admin
|
||||
# password: password
|
||||
# api_key: api_key
|
||||
# access_token: access_token
|
||||
|
||||
s3_publish_endpoints:
|
||||
# # Endpoint Name
|
||||
# test:
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ Publish snapshot or local repo as Debian repository to be used as APT source on
|
||||
|
||||
The published repository is signed with the user's GnuPG key.
|
||||
|
||||
Repositories can be published to local directories, Amazon S3 buckets, Azure or Swift Storage.
|
||||
Repositories can be published to local directories, Amazon S3 buckets, Azure, Swift, or JFrog Artifactory Storage.
|
||||
|
||||
#### GPG Keys
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module github.com/aptly-dev/aptly
|
||||
|
||||
go 1.24.0
|
||||
go 1.24.6
|
||||
|
||||
require (
|
||||
github.com/AlekSi/pointer v1.1.0
|
||||
@@ -14,7 +14,7 @@ require (
|
||||
github.com/jlaffaye/ftp v0.2.0 // indirect
|
||||
github.com/kjk/lzma v0.0.0-20120628231508-2a7c55cad4a2
|
||||
github.com/klauspost/compress v1.18.2
|
||||
github.com/klauspost/pgzip v1.2.5
|
||||
github.com/klauspost/pgzip v1.2.6
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/mattn/go-shellwords v1.0.12
|
||||
@@ -49,13 +49,17 @@ require (
|
||||
cloud.google.com/go/iam v1.5.3 // indirect
|
||||
cloud.google.com/go/monitoring v1.24.3 // indirect
|
||||
cloud.google.com/go/pubsub/v2 v2.4.0 // indirect
|
||||
dario.cat/mergo v1.0.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
|
||||
github.com/CycloneDX/cyclonedx-go v0.9.2 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 // indirect
|
||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||
github.com/andybalholm/brotli v1.1.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 // indirect
|
||||
@@ -77,12 +81,19 @@ require (
|
||||
github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect
|
||||
github.com/coreos/go-semver v0.3.0 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
|
||||
github.com/dsnet/compress v0.0.1 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect
|
||||
github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect
|
||||
github.com/fatih/color v1.17.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/forPelevin/gomoji v1.3.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.6.2 // indirect
|
||||
github.com/go-git/go-git/v5 v5.14.0 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.1.3 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
@@ -94,28 +105,40 @@ require (
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/renameio/v2 v2.0.0 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.11 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.17.0 // indirect
|
||||
github.com/gookit/color v1.5.4 // indirect
|
||||
github.com/gorilla/handlers v1.5.2 // indirect
|
||||
github.com/gorilla/mux v1.8.1 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/jfrog/archiver/v3 v3.6.1 // indirect
|
||||
github.com/jfrog/build-info-go v1.11.0 // indirect
|
||||
github.com/jfrog/gofrog v1.7.6 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.11 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/mailru/easyjson v0.7.6 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/minio/sha256-simd v1.0.1 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/nwaples/rardecode v1.1.3 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.22 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.2 // indirect
|
||||
github.com/pkg/xattr v0.4.12 // indirect
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
@@ -123,8 +146,14 @@ require (
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
|
||||
github.com/skeema/knownhosts v1.3.1 // indirect
|
||||
github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ulikunitz/xz v0.5.15 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.5.15 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.15 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
@@ -140,6 +169,7 @@ require (
|
||||
go.uber.org/multierr v1.10.0 // indirect
|
||||
go.uber.org/zap v1.26.0 // indirect
|
||||
golang.org/x/arch v0.3.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
|
||||
golang.org/x/net v0.49.0 // indirect
|
||||
golang.org/x/sync v0.19.0 // indirect
|
||||
golang.org/x/text v0.33.0 // indirect
|
||||
@@ -149,6 +179,7 @@ require (
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260203192932-546029d2fa20 // indirect
|
||||
google.golang.org/grpc v1.79.3 // indirect
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
||||
|
||||
@@ -164,6 +195,7 @@ require (
|
||||
github.com/aws/smithy-go v1.24.2
|
||||
github.com/fsouza/fake-gcs-server v1.53.1
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/jfrog/jfrog-client-go v1.55.0
|
||||
github.com/swaggo/files v1.0.1
|
||||
github.com/swaggo/gin-swagger v1.6.0
|
||||
github.com/swaggo/swag v1.16.3
|
||||
|
||||
@@ -23,6 +23,8 @@ cloud.google.com/go/storage v1.60.0 h1:oBfZrSOCimggVNz9Y/bXY35uUcts7OViubeddTTVz
|
||||
cloud.google.com/go/storage v1.60.0/go.mod h1:q+5196hXfejkctrnx+VYU8RKQr/L3c0cBIlrjmiAKE0=
|
||||
cloud.google.com/go/trace v1.11.7 h1:kDNDX8JkaAG3R2nq1lIdkb7FCSi1rCmsEtKVsty7p+U=
|
||||
cloud.google.com/go/trace v1.11.7/go.mod h1:TNn9d5V3fQVf6s4SCveVMIBS2LJUqo73GACmq/Tky0s=
|
||||
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI=
|
||||
github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 h1:nyQWyZvwGTvunIMxi1Y9uXkcyr+I7TeNrr/foo4Kpk8=
|
||||
@@ -38,6 +40,8 @@ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.4.1/go.mod h1:ap1dmS6vQK
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/CycloneDX/cyclonedx-go v0.9.2 h1:688QHn2X/5nRezKe2ueIVCt+NRqf7fl3AVQk+vaFcIo=
|
||||
github.com/CycloneDX/cyclonedx-go v0.9.2/go.mod h1:vcK6pKgO1WanCdd61qx4bFnSsDJQ6SbM2ZuMIgq86Jg=
|
||||
github.com/DisposaBoy/JsonConfigReader v0.0.0-20171218180944-5ea4d0ddac55 h1:jbGlDKdzAZ92NzK65hUP98ri0/r50vVVvmZsFP/nIqo=
|
||||
github.com/DisposaBoy/JsonConfigReader v0.0.0-20171218180944-5ea4d0ddac55/go.mod h1:GCzqZQHydohgVLSIqRKZeTt8IGb1Y4NaFfim3H40uUI=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 h1:sBEjpZlNHzK1voKq9695PJSX2o5NEXl7/OL3coiIY0c=
|
||||
@@ -50,12 +54,21 @@ github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapp
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0/go.mod h1:Mf6O40IAyB9zR/1J8nGDDPirZQQPbYJni8Yisy7NTMc=
|
||||
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
||||
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/ProtonMail/go-crypto v1.4.0 h1:Zq/pbM3F5DFgJiMouxEdSVY44MVoQNEKp5d5QxIQceQ=
|
||||
github.com/ProtonMail/go-crypto v1.4.0/go.mod h1:e1OaTyu5SYVrO9gKOEhTc+5UcXtTUa+P3uLudwcgPqo=
|
||||
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
|
||||
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/awalterschulze/gographviz v2.0.1+incompatible h1:XIECBRq9VPEQqkQL5pw2OtjCAdrtIgFKoJU8eT98AS8=
|
||||
github.com/awalterschulze/gographviz v2.0.1+incompatible/go.mod h1:GEV5wmg4YquNw7v1kkyoX9etIk8yVmXj+AkDHuuETHs=
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.5 h1:dj5kopbwUsVUVFgO4Fi5BIT3t4WyqIDjGKCangnV/yY=
|
||||
@@ -96,6 +109,8 @@ github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng=
|
||||
github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M=
|
||||
github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0=
|
||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
|
||||
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||
@@ -123,12 +138,21 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
|
||||
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q=
|
||||
github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo=
|
||||
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o=
|
||||
github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
@@ -145,6 +169,8 @@ github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
|
||||
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/forPelevin/gomoji v1.3.0 h1:WPIOLWB1bvRYlKZnSSEevLt3IfKlLs+tK+YA9fFYlkE=
|
||||
github.com/forPelevin/gomoji v1.3.0/go.mod h1:mM6GtmCgpoQP2usDArc6GjbXrti5+FffolyQfGgPboQ=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
|
||||
@@ -159,6 +185,16 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
||||
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||
github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
|
||||
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||
github.com/go-git/go-git/v5 v5.14.0 h1:/MD3lCrGjCen5WfEAzKg00MJJffKhC8gzS80ycmCi60=
|
||||
github.com/go-git/go-git/v5 v5.14.0/go.mod h1:Z5Xhoia5PcWA3NF8vRLURn9E5FRhSl7dGj9ItW3Wk5k=
|
||||
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
||||
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
|
||||
@@ -192,12 +228,14 @@ github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MG
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@@ -239,6 +277,8 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.11 h1:vAe81Msw+8tKUxi2Dq
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.11/go.mod h1:RFV7MUdlb7AgEq2v7FmMCfeSMCllAzWxFgRdusoGks8=
|
||||
github.com/googleapis/gax-go/v2 v2.17.0 h1:RksgfBpxqff0EZkDWYuz9q/uWsTVz+kf43LsZ1J6SMc=
|
||||
github.com/googleapis/gax-go/v2 v2.17.0/go.mod h1:mzaqghpQp4JDh3HvADwrat+6M3MOIDp5YKHhb9PAgDY=
|
||||
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
|
||||
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
|
||||
github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
|
||||
github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
|
||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
@@ -252,25 +292,39 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jfrog/archiver/v3 v3.6.1 h1:LOxnkw9pOn45DzCbZNFV6K0+6dCsQ0L8mR3ZcujO5eI=
|
||||
github.com/jfrog/archiver/v3 v3.6.1/go.mod h1:VgR+3WZS4N+i9FaDwLZbq+jeU4B4zctXL+gL4EMzfLw=
|
||||
github.com/jfrog/build-info-go v1.11.0 h1:qEONCgaHKlW3e2y0zIwTZVbgS/ERZrPlBWEbOYJbaSU=
|
||||
github.com/jfrog/build-info-go v1.11.0/go.mod h1:szdz9+WzB7+7PGnILLUgyY+OF5qD5geBT7UGNIxibyw=
|
||||
github.com/jfrog/gofrog v1.7.6 h1:QmfAiRzVyaI7JYGsB7cxfAJePAZTzFz0gRWZSE27c6s=
|
||||
github.com/jfrog/gofrog v1.7.6/go.mod h1:ntr1txqNOZtHplmaNd7rS4f8jpA5Apx8em70oYEe7+4=
|
||||
github.com/jfrog/jfrog-client-go v1.55.0 h1:dZq7sLjUJMps8X1I5coVUChprtR7xklp7oSfmZnI48w=
|
||||
github.com/jfrog/jfrog-client-go v1.55.0/go.mod h1:/e2kaF1oZTmSRgMIk7wYna5xMtNY7Xk8ahpSNZQ2d3s=
|
||||
github.com/jlaffaye/ftp v0.2.0 h1:lXNvW7cBu7R/68bknOX3MrRIIqZ61zELs1P2RAiA3lg=
|
||||
github.com/jlaffaye/ftp v0.2.0/go.mod h1:is2Ds5qkhceAPy2xD6RLI6hmp/qysSoymZ+Z2uTnspI=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kjk/lzma v0.0.0-20120628231508-2a7c55cad4a2 h1:TVZQgMi+I83S3rCuE65HnmDO6+wFPRi3n2LOzr+tr68=
|
||||
github.com/kjk/lzma v0.0.0-20120628231508-2a7c55cad4a2/go.mod h1:phT/jsRPBAEqjAibu1BurrabCBNTYiVI+zbmyCZJY6Q=
|
||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
|
||||
github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.11 h1:0OwqZRYI2rFrjS4kvkDnqJkKHdHaRnCm68/DY4OxRzU=
|
||||
github.com/klauspost/cpuid/v2 v2.2.11/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/klauspost/crc32 v1.3.0 h1:sSmTt3gUt81RP655XGZPElI0PelVTZ6YwCRnPSupoFM=
|
||||
github.com/klauspost/crc32 v1.3.0/go.mod h1:D7kQaZhnkX/Y0tstFGf8VUzv2UofNGqCjnC3zdHB0Hw=
|
||||
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
|
||||
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
|
||||
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
@@ -304,6 +358,8 @@ github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
||||
github.com/minio/minio-go/v7 v7.0.98 h1:MeAVKjLVz+XJ28zFcuYyImNSAh8Mq725uNW4beRisi0=
|
||||
github.com/minio/minio-go/v7 v7.0.98/go.mod h1:cY0Y+W7yozf0mdIclrttzo1Iiu7mEf9y7nk2uXqMOvM=
|
||||
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
|
||||
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
|
||||
github.com/mkrautz/goar v0.0.0-20150919110319-282caa8bd9da h1:Iu5QFXIMK/YrHJ0NgUnK0rqYTTyb0ldt/rqNenAj39U=
|
||||
github.com/mkrautz/goar v0.0.0-20150919110319-282caa8bd9da/go.mod h1:NfnmoBY0gGkr3/NmI+DP/UXbZvOCurCUYAzOdYJjlOc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
@@ -318,6 +374,8 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+
|
||||
github.com/ncw/swift v1.0.53 h1:luHjjTNtekIEvHg5KdAFIBaH7bWfNkefwFnpDffSIks=
|
||||
github.com/ncw/swift v1.0.53/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc=
|
||||
github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
@@ -330,12 +388,17 @@ github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw=
|
||||
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
|
||||
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
|
||||
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM=
|
||||
github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
|
||||
github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU=
|
||||
github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4=
|
||||
github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
@@ -370,6 +433,11 @@ github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc=
|
||||
github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU=
|
||||
github.com/saracen/walker v0.1.2 h1:/o1TxP82n8thLvmL4GpJXduYaRmJ7qXp8u9dSlV0zmo=
|
||||
github.com/saracen/walker v0.1.2/go.mod h1:0oKYMsKVhSJ+ful4p/XbjvXbMgLEkLITZaxozsl4CGE=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
|
||||
github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
|
||||
github.com/smira/commander v0.0.0-20140515201010-f408b00e68d5 h1:jLFwP6SDEUHmb6QSu5n2FHseWzMio1ou1FV9p7W6p7I=
|
||||
github.com/smira/commander v0.0.0-20140515201010-f408b00e68d5/go.mod h1:XTQy55hw5s3pxmC42m7X0/b+9naXQ1rGN9Of6BGIZmU=
|
||||
github.com/smira/flag v0.0.0-20170926215700-695ea5e84e76 h1:OM075OkN4x9IB1mbzkzaKaJjFxx8Mfss8Z3E1LHwawQ=
|
||||
@@ -383,7 +451,9 @@ github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xI
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
@@ -403,14 +473,33 @@ github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg=
|
||||
github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48=
|
||||
github.com/terminalstatic/go-xsd-validate v0.1.6 h1:TenYeQ3eY631qNi1/cTmLH/s2slHPRKTTHT+XSHkepo=
|
||||
github.com/terminalstatic/go-xsd-validate v0.1.6/go.mod h1:18lsvYFofBflqCrvo1umpABZ99+GneNTw2kEEc8UPJw=
|
||||
github.com/tinylib/msgp v1.6.1 h1:ESRv8eL3u+DNHUoSAAQRE50Hm162zqAnBoGv9PzScPY=
|
||||
github.com/tinylib/msgp v1.6.1/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
|
||||
github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY=
|
||||
github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/wsxiaoys/terminal v0.0.0-20160513160801-0940f3fc43a0 h1:3UeQBvD0TFrlVjOeLOBz+CPAI8dnbqNSVwUwRrkp7vQ=
|
||||
github.com/wsxiaoys/terminal v0.0.0-20160513160801-0940f3fc43a0/go.mod h1:IXCdmsXIht47RaVFLEdVnh1t+pgYtTAhQGj73kz+2DM=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
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/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
@@ -459,9 +548,12 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
@@ -484,6 +576,7 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
@@ -508,12 +601,14 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -523,6 +618,7 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -597,6 +693,7 @@ google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBN
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
@@ -605,6 +702,8 @@ gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qS
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
// Package jfrog handles publishing to JFrog Artifactory
|
||||
package jfrog
|
||||
+292
@@ -0,0 +1,292 @@
|
||||
package jfrog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/aptly-dev/aptly/aptly"
|
||||
aptly_utils "github.com/aptly-dev/aptly/utils"
|
||||
"github.com/jfrog/jfrog-client-go/artifactory"
|
||||
"github.com/jfrog/jfrog-client-go/artifactory/auth"
|
||||
"github.com/jfrog/jfrog-client-go/artifactory/services"
|
||||
"github.com/jfrog/jfrog-client-go/artifactory/services/utils"
|
||||
"github.com/jfrog/jfrog-client-go/config"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// PublishedStorage represents published repository on JFrog Artifactory
|
||||
type PublishedStorage struct {
|
||||
manager artifactory.ArtifactoryServicesManager
|
||||
repository string
|
||||
prefix string
|
||||
plusWorkaround bool
|
||||
}
|
||||
|
||||
// Check interface
|
||||
var (
|
||||
_ aptly.PublishedStorage = (*PublishedStorage)(nil)
|
||||
)
|
||||
|
||||
func createPublishedStorageConfig(url, user, password, apiKey, accessToken string) (config.Config, error) {
|
||||
artDetails := auth.NewArtifactoryDetails()
|
||||
artDetails.SetUrl(url)
|
||||
|
||||
if user == "" {
|
||||
user = os.Getenv("JFROG_USERNAME");
|
||||
}
|
||||
if password == "" {
|
||||
password = os.Getenv("JFROG_PASSWORD");
|
||||
}
|
||||
if apiKey == "" {
|
||||
apiKey = os.Getenv("JFROG_APIKEY");
|
||||
}
|
||||
if accessToken == "" {
|
||||
accessToken = os.Getenv("JFROG_ACCESSTOKEN");
|
||||
}
|
||||
|
||||
if user != "" && password != "" {
|
||||
artDetails.SetUser(user)
|
||||
artDetails.SetPassword(password)
|
||||
} else if apiKey != "" {
|
||||
artDetails.SetApiKey(apiKey)
|
||||
} else if accessToken != "" {
|
||||
artDetails.SetAccessToken(accessToken)
|
||||
}
|
||||
|
||||
return config.NewConfigBuilder().
|
||||
SetServiceDetails(artDetails).
|
||||
SetDryRun(false).
|
||||
Build()
|
||||
}
|
||||
|
||||
// NewPublishedStorageRaw creates jfrog PublishedStorage from raw connection specs
|
||||
func NewPublishedStorageRaw(
|
||||
repository, url, user, password, apiKey, accessToken, prefix string,
|
||||
plusWorkaround, debug bool,
|
||||
) (*PublishedStorage, error) {
|
||||
|
||||
serviceConfig, err := createPublishedStorageConfig(url, user, password, apiKey, accessToken)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error building jfrog client config")
|
||||
}
|
||||
|
||||
manager, err := artifactory.New(serviceConfig)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error creating jfrog manager")
|
||||
}
|
||||
|
||||
return &PublishedStorage{
|
||||
manager: manager,
|
||||
repository: repository,
|
||||
prefix: prefix,
|
||||
plusWorkaround: plusWorkaround,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewPublishedStorage creates published storage from aptly configuration struct
|
||||
func NewPublishedStorage(
|
||||
account string, root aptly_utils.JFrogPublishRoot,
|
||||
) (*PublishedStorage, error) {
|
||||
return NewPublishedStorageRaw(
|
||||
root.Repository, root.Url, root.User, root.Password, root.ApiKey, root.AccessToken,
|
||||
root.Prefix, root.PlusWorkaround, root.Debug)
|
||||
}
|
||||
|
||||
func (storage *PublishedStorage) String() string {
|
||||
return fmt.Sprintf("jfrog:%s:%s", storage.repository, storage.prefix)
|
||||
}
|
||||
|
||||
func (storage *PublishedStorage) MkDir(path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (storage *PublishedStorage) PutFile(path string, sourceFilename string) error {
|
||||
targetPath := filepath.Join(storage.repository, storage.prefix, path)
|
||||
if storage.plusWorkaround {
|
||||
targetPath = strings.Replace(targetPath, "+", "%2B", -1)
|
||||
}
|
||||
|
||||
params := services.NewUploadParams()
|
||||
params.Pattern = sourceFilename
|
||||
params.Target = targetPath
|
||||
params.Flat = true
|
||||
|
||||
_, _, err := storage.manager.UploadFiles(artifactory.UploadServiceOptions{}, params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (storage *PublishedStorage) Remove(path string) error {
|
||||
targetPath := filepath.Join(storage.repository, storage.prefix, path)
|
||||
if storage.plusWorkaround {
|
||||
targetPath = strings.Replace(targetPath, "+", "%2B", -1)
|
||||
}
|
||||
|
||||
deleteParams := services.NewDeleteParams()
|
||||
deleteParams.SetPattern(targetPath)
|
||||
|
||||
res, err := storage.manager.GetPathsToDelete(deleteParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer res.Close()
|
||||
_, err = storage.manager.DeleteFiles(res)
|
||||
return err
|
||||
}
|
||||
|
||||
func (storage *PublishedStorage) RemoveDirs(path string, progress aptly.Progress) error {
|
||||
return storage.Remove(path)
|
||||
}
|
||||
|
||||
func (storage *PublishedStorage) LinkFromPool(publishedPrefix, publishedRelPath, fileName string, sourcePool aptly.PackagePool, sourcePath string, sourceMD5 aptly_utils.ChecksumInfo, force bool) error {
|
||||
sourceFilename := sourcePath
|
||||
cleanup := func() {}
|
||||
|
||||
if sourcePool != nil {
|
||||
if localPool, ok := sourcePool.(aptly.LocalPackagePool); ok {
|
||||
sourceFilename = localPool.FullPath(sourcePath)
|
||||
} else {
|
||||
src, err := sourcePool.Open(sourcePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { _ = src.Close() }()
|
||||
|
||||
tmpFile, err := os.CreateTemp("", "aptly-jfrog-pool-*")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := io.Copy(tmpFile, src); err != nil {
|
||||
_ = tmpFile.Close()
|
||||
_ = os.Remove(tmpFile.Name())
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tmpFile.Close(); err != nil {
|
||||
_ = os.Remove(tmpFile.Name())
|
||||
return err
|
||||
}
|
||||
|
||||
sourceFilename = tmpFile.Name()
|
||||
cleanup = func() {
|
||||
_ = os.Remove(sourceFilename)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defer cleanup()
|
||||
|
||||
return storage.PutFile(filepath.Join(publishedPrefix, publishedRelPath, fileName), sourceFilename)
|
||||
}
|
||||
|
||||
func (storage *PublishedStorage) Filelist(prefix string) ([]string, error) {
|
||||
searchPattern := filepath.Join(storage.repository, storage.prefix, prefix, "*")
|
||||
params := services.NewSearchParams()
|
||||
params.Pattern = searchPattern
|
||||
|
||||
reader, err := storage.manager.SearchFiles(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
var paths []string
|
||||
|
||||
for element := new(utils.ResultItem); reader.NextRecord(element) == nil; element = new(utils.ResultItem) {
|
||||
path := element.Path + "/" + element.Name
|
||||
relPath := strings.TrimPrefix(path, storage.repository+"/"+storage.prefix+"/")
|
||||
if storage.plusWorkaround {
|
||||
relPath = strings.Replace(relPath, "%2B", "+", -1)
|
||||
}
|
||||
paths = append(paths, relPath)
|
||||
}
|
||||
|
||||
return paths, nil
|
||||
}
|
||||
|
||||
func (storage *PublishedStorage) RenameFile(oldName, newName string) error {
|
||||
oldTarget := filepath.Join(storage.repository, storage.prefix, oldName)
|
||||
newTarget := filepath.Join(storage.repository, storage.prefix, newName)
|
||||
|
||||
if storage.plusWorkaround {
|
||||
oldTarget = strings.Replace(oldTarget, "+", "%2B", -1)
|
||||
newTarget = strings.Replace(newTarget, "+", "%2B", -1)
|
||||
}
|
||||
|
||||
params := services.NewMoveCopyParams()
|
||||
params.Pattern = oldTarget
|
||||
params.Target = newTarget
|
||||
params.Flat = true
|
||||
|
||||
_, _, err := storage.manager.Move(params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (storage *PublishedStorage) SymLink(src string, dst string) error {
|
||||
oldTarget := filepath.Join(storage.repository, storage.prefix, src)
|
||||
newTarget := filepath.Join(storage.repository, storage.prefix, dst)
|
||||
|
||||
if storage.plusWorkaround {
|
||||
oldTarget = strings.Replace(oldTarget, "+", "%2B", -1)
|
||||
newTarget = strings.Replace(newTarget, "+", "%2B", -1)
|
||||
}
|
||||
|
||||
params := services.NewMoveCopyParams()
|
||||
params.Pattern = oldTarget
|
||||
params.Target = newTarget
|
||||
params.Flat = true
|
||||
|
||||
props := utils.NewProperties()
|
||||
props.AddProperty("SymLink", src)
|
||||
params.SetTargetProps(props)
|
||||
|
||||
_, _, err := storage.manager.Copy(params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (storage *PublishedStorage) HardLink(src string, dst string) error {
|
||||
return storage.SymLink(src, dst)
|
||||
}
|
||||
|
||||
func (storage *PublishedStorage) FileExists(path string) (bool, error) {
|
||||
targetPath := filepath.Join(storage.repository, storage.prefix, path)
|
||||
if storage.plusWorkaround {
|
||||
targetPath = strings.Replace(targetPath, "+", "%2B", -1)
|
||||
}
|
||||
|
||||
params := services.NewSearchParams()
|
||||
params.Pattern = targetPath
|
||||
|
||||
reader, err := storage.manager.SearchFiles(params)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
length, err := reader.Length()
|
||||
isEmpty := length == 0
|
||||
return !isEmpty, err
|
||||
}
|
||||
|
||||
func (storage *PublishedStorage) ReadLink(path string) (string, error) {
|
||||
targetPath := filepath.Join(storage.repository, storage.prefix, path)
|
||||
if storage.plusWorkaround {
|
||||
targetPath = strings.Replace(targetPath, "+", "%2B", -1)
|
||||
}
|
||||
|
||||
props, err := storage.manager.GetItemProps(targetPath)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
for k, v := range props.Properties {
|
||||
if k == "SymLink" && len(v) > 0 {
|
||||
return v[0], nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
@@ -0,0 +1,511 @@
|
||||
package jfrog
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/aptly-dev/aptly/aptly"
|
||||
aptly_utils "github.com/aptly-dev/aptly/utils"
|
||||
"github.com/jfrog/jfrog-client-go/artifactory"
|
||||
"github.com/jfrog/jfrog-client-go/artifactory/services"
|
||||
jfrogutils "github.com/jfrog/jfrog-client-go/artifactory/services/utils"
|
||||
"github.com/jfrog/jfrog-client-go/utils/io/content"
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
t.Setenv("JFROG_USERNAME", "userfromenv")
|
||||
TestingT(t)
|
||||
}
|
||||
|
||||
type fakeJFrogManager struct {
|
||||
artifactory.EmptyArtifactoryServicesManager
|
||||
|
||||
uploadParams []services.UploadParams
|
||||
uploadErr error
|
||||
|
||||
deleteParams []services.DeleteParams
|
||||
getPathsToDelete *content.ContentReader
|
||||
getPathsDeleteErr error
|
||||
deleteErr error
|
||||
deleteCalled bool
|
||||
|
||||
searchParams []services.SearchParams
|
||||
searchReader *content.ContentReader
|
||||
searchErr error
|
||||
|
||||
moveParams []services.MoveCopyParams
|
||||
moveErr error
|
||||
|
||||
copyParams []services.MoveCopyParams
|
||||
copyErr error
|
||||
|
||||
itemProps *jfrogutils.ItemProperties
|
||||
itemPropsErr error
|
||||
}
|
||||
|
||||
func (m *fakeJFrogManager) UploadFiles(_ artifactory.UploadServiceOptions, params ...services.UploadParams) (int, int, error) {
|
||||
m.uploadParams = append(m.uploadParams, params...)
|
||||
return len(params), 0, m.uploadErr
|
||||
}
|
||||
|
||||
func (m *fakeJFrogManager) GetPathsToDelete(params services.DeleteParams) (*content.ContentReader, error) {
|
||||
m.deleteParams = append(m.deleteParams, params)
|
||||
if m.getPathsDeleteErr != nil {
|
||||
return nil, m.getPathsDeleteErr
|
||||
}
|
||||
if m.getPathsToDelete != nil {
|
||||
return m.getPathsToDelete, nil
|
||||
}
|
||||
return content.NewEmptyContentReader("results"), nil
|
||||
}
|
||||
|
||||
func (m *fakeJFrogManager) DeleteFiles(_ *content.ContentReader) (int, error) {
|
||||
m.deleteCalled = true
|
||||
return 1, m.deleteErr
|
||||
}
|
||||
|
||||
func (m *fakeJFrogManager) SearchFiles(params services.SearchParams) (*content.ContentReader, error) {
|
||||
m.searchParams = append(m.searchParams, params)
|
||||
if m.searchErr != nil {
|
||||
return nil, m.searchErr
|
||||
}
|
||||
if m.searchReader != nil {
|
||||
return m.searchReader, nil
|
||||
}
|
||||
return content.NewEmptyContentReader("results"), nil
|
||||
}
|
||||
|
||||
func (m *fakeJFrogManager) Move(params ...services.MoveCopyParams) (int, int, error) {
|
||||
m.moveParams = append(m.moveParams, params...)
|
||||
return len(params), 0, m.moveErr
|
||||
}
|
||||
|
||||
func (m *fakeJFrogManager) Copy(params ...services.MoveCopyParams) (int, int, error) {
|
||||
m.copyParams = append(m.copyParams, params...)
|
||||
return len(params), 0, m.copyErr
|
||||
}
|
||||
|
||||
func (m *fakeJFrogManager) GetItemProps(_ string) (*jfrogutils.ItemProperties, error) {
|
||||
if m.itemPropsErr != nil {
|
||||
return nil, m.itemPropsErr
|
||||
}
|
||||
if m.itemProps != nil {
|
||||
return m.itemProps, nil
|
||||
}
|
||||
return &jfrogutils.ItemProperties{}, nil
|
||||
}
|
||||
|
||||
type resultFixture struct {
|
||||
Results []jfrogutils.ResultItem `json:"results"`
|
||||
}
|
||||
|
||||
type fakeLocalPool struct{}
|
||||
|
||||
func (p *fakeLocalPool) Verify(string, string, *aptly_utils.ChecksumInfo, aptly.ChecksumStorage) (string, bool, error) {
|
||||
return "", false, nil
|
||||
}
|
||||
|
||||
func (p *fakeLocalPool) Import(string, string, *aptly_utils.ChecksumInfo, bool, aptly.ChecksumStorage) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (p *fakeLocalPool) LegacyPath(string, *aptly_utils.ChecksumInfo) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (p *fakeLocalPool) Size(string) (int64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (p *fakeLocalPool) Open(string) (aptly.ReadSeekerCloser, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (p *fakeLocalPool) FilepathList(aptly.Progress) ([]string, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (p *fakeLocalPool) Remove(string) (int64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (p *fakeLocalPool) Stat(string) (os.FileInfo, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (p *fakeLocalPool) GenerateTempPath(string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (p *fakeLocalPool) Link(string, string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *fakeLocalPool) Symlink(string, string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *fakeLocalPool) FullPath(path string) string {
|
||||
return filepath.Join("/var/lib/aptly/pool", path)
|
||||
}
|
||||
|
||||
type fakeRemotePool struct {
|
||||
openPath string
|
||||
openErr error
|
||||
}
|
||||
|
||||
func (p *fakeRemotePool) Verify(string, string, *aptly_utils.ChecksumInfo, aptly.ChecksumStorage) (string, bool, error) {
|
||||
return "", false, nil
|
||||
}
|
||||
|
||||
func (p *fakeRemotePool) Import(string, string, *aptly_utils.ChecksumInfo, bool, aptly.ChecksumStorage) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (p *fakeRemotePool) LegacyPath(string, *aptly_utils.ChecksumInfo) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (p *fakeRemotePool) Size(string) (int64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (p *fakeRemotePool) Open(string) (aptly.ReadSeekerCloser, error) {
|
||||
if p.openErr != nil {
|
||||
return nil, p.openErr
|
||||
}
|
||||
return os.Open(p.openPath)
|
||||
}
|
||||
|
||||
func (p *fakeRemotePool) FilepathList(aptly.Progress) ([]string, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (p *fakeRemotePool) Remove(string) (int64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func createReader(c *C, results []jfrogutils.ResultItem) *content.ContentReader {
|
||||
filePath := filepath.Join(c.MkDir(), "results.json")
|
||||
data, err := json.Marshal(resultFixture{Results: results})
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(os.WriteFile(filePath, data, 0o644), IsNil)
|
||||
return content.NewContentReader(filePath, "results")
|
||||
}
|
||||
|
||||
type PublishedStorageSuite struct {
|
||||
manager *fakeJFrogManager
|
||||
storage *PublishedStorage
|
||||
}
|
||||
|
||||
var _ = Suite(&PublishedStorageSuite{})
|
||||
|
||||
func (s *PublishedStorageSuite) SetUpTest(c *C) {
|
||||
s.manager = &fakeJFrogManager{}
|
||||
s.storage = &PublishedStorage{
|
||||
manager: s.manager,
|
||||
repository: "repo",
|
||||
prefix: "prefix",
|
||||
}
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestStringAndMkDir(c *C) {
|
||||
c.Assert(s.storage.String(), Equals, "jfrog:repo:prefix")
|
||||
c.Assert(s.storage.MkDir("anything"), IsNil)
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestPutFile(c *C) {
|
||||
err := s.storage.PutFile("pool/main/a+b.deb", "/tmp/source.deb")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(len(s.manager.uploadParams), Equals, 1)
|
||||
c.Assert(s.manager.uploadParams[0].Pattern, Equals, "/tmp/source.deb")
|
||||
c.Assert(s.manager.uploadParams[0].Target, Equals, filepath.Join("repo", "prefix", "pool/main/a+b.deb"))
|
||||
c.Assert(s.manager.uploadParams[0].Flat, Equals, true)
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestPutFilePlusWorkaroundAndError(c *C) {
|
||||
s.storage.plusWorkaround = true
|
||||
s.manager.uploadErr = errors.New("upload failed")
|
||||
|
||||
err := s.storage.PutFile("pool/main/a+b.deb", "/tmp/source.deb")
|
||||
c.Assert(err, ErrorMatches, "upload failed")
|
||||
c.Assert(s.manager.uploadParams[0].Target, Equals, filepath.Join("repo", "prefix", "pool/main/a%2Bb.deb"))
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestRemove(c *C) {
|
||||
s.manager.getPathsToDelete = createReader(c, []jfrogutils.ResultItem{})
|
||||
|
||||
err := s.storage.Remove("dists/stable+main")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(len(s.manager.deleteParams), Equals, 1)
|
||||
c.Assert(s.manager.deleteParams[0].Pattern, Equals, filepath.Join("repo", "prefix", "dists/stable+main"))
|
||||
c.Assert(s.manager.deleteCalled, Equals, true)
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestRemovePlusWorkaround(c *C) {
|
||||
s.storage.plusWorkaround = true
|
||||
s.manager.getPathsToDelete = createReader(c, []jfrogutils.ResultItem{})
|
||||
|
||||
err := s.storage.Remove("pool/a+b.deb")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(s.manager.deleteParams[0].Pattern, Equals, filepath.Join("repo", "prefix", "pool/a%2Bb.deb"))
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestRemoveErrors(c *C) {
|
||||
s.manager.getPathsDeleteErr = errors.New("search delete failed")
|
||||
err := s.storage.Remove("x")
|
||||
c.Assert(err, ErrorMatches, "search delete failed")
|
||||
|
||||
s.manager.getPathsDeleteErr = nil
|
||||
s.manager.getPathsToDelete = createReader(c, []jfrogutils.ResultItem{})
|
||||
s.manager.deleteErr = errors.New("delete failed")
|
||||
err = s.storage.Remove("x")
|
||||
c.Assert(err, ErrorMatches, "delete failed")
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestRemoveDirsDelegatesToRemove(c *C) {
|
||||
s.manager.getPathsToDelete = createReader(c, []jfrogutils.ResultItem{})
|
||||
c.Assert(s.storage.RemoveDirs("x", nil), IsNil)
|
||||
c.Assert(len(s.manager.deleteParams), Equals, 1)
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestLinkFromPoolDelegatesToPutFile(c *C) {
|
||||
err := s.storage.LinkFromPool("", "pool/main/p", "pkg.deb", nil, "/tmp/source.deb", aptly_utils.ChecksumInfo{}, false)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(s.manager.uploadParams[0].Target, Equals, filepath.Join("repo", "prefix", "pool/main/p", "pkg.deb"))
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestLinkFromPoolUsesLocalPoolFullPath(c *C) {
|
||||
pool := &fakeLocalPool{}
|
||||
poolPath := "e3/48/84d71bb98002bf0c775479aa31ee_accountsservice_0.6.55-0ubuntu11_amd64.deb"
|
||||
|
||||
err := s.storage.LinkFromPool("", "pool/main/p", "pkg.deb", pool, poolPath, aptly_utils.ChecksumInfo{}, false)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(s.manager.uploadParams[0].Pattern, Equals, filepath.Join("/var/lib/aptly/pool", poolPath))
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestLinkFromPoolCopiesFromRemotePool(c *C) {
|
||||
tmpFile := filepath.Join(c.MkDir(), "source.deb")
|
||||
c.Assert(os.WriteFile(tmpFile, []byte("package-bytes"), 0o644), IsNil)
|
||||
|
||||
pool := &fakeRemotePool{openPath: tmpFile}
|
||||
err := s.storage.LinkFromPool("", "pool/main/p", "pkg.deb", pool, "hash/path/pkg.deb", aptly_utils.ChecksumInfo{}, false)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
uploadPath := s.manager.uploadParams[0].Pattern
|
||||
c.Assert(uploadPath, Not(Equals), "hash/path/pkg.deb")
|
||||
_, statErr := os.Stat(uploadPath)
|
||||
c.Assert(os.IsNotExist(statErr), Equals, true)
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestFilelist(c *C) {
|
||||
s.manager.searchReader = createReader(c, []jfrogutils.ResultItem{
|
||||
{Path: "repo/prefix/pool/main/a", Name: "a.deb", Actual_Md5: "m1"},
|
||||
{Path: "repo/prefix/pool/main/b", Name: "b.deb", Actual_Md5: "m2"},
|
||||
})
|
||||
|
||||
list, err := s.storage.Filelist("pool/main")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(list, DeepEquals, []string{"pool/main/a/a.deb", "pool/main/b/b.deb"})
|
||||
c.Assert(s.manager.searchParams[0].Pattern, Equals, filepath.Join("repo", "prefix", "pool/main", "*"))
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestFilelistPlusWorkaroundAndSearchError(c *C) {
|
||||
s.storage.plusWorkaround = true
|
||||
s.manager.searchReader = createReader(c, []jfrogutils.ResultItem{
|
||||
{Path: "repo/prefix/pool/main", Name: "a%2Bb.deb", Actual_Md5: "m1"},
|
||||
})
|
||||
|
||||
list, err := s.storage.Filelist("pool/main")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(list, DeepEquals, []string{"pool/main/a+b.deb"})
|
||||
|
||||
s.manager.searchErr = errors.New("search failed")
|
||||
_, err = s.storage.Filelist("pool/main")
|
||||
c.Assert(err, ErrorMatches, "search failed")
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestRenameFile(c *C) {
|
||||
err := s.storage.RenameFile("old+name", "new+name")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(len(s.manager.moveParams), Equals, 1)
|
||||
c.Assert(s.manager.moveParams[0].Pattern, Equals, filepath.Join("repo", "prefix", "old+name"))
|
||||
c.Assert(s.manager.moveParams[0].Target, Equals, filepath.Join("repo", "prefix", "new+name"))
|
||||
c.Assert(s.manager.moveParams[0].Flat, Equals, true)
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestRenameFilePlusWorkaroundAndError(c *C) {
|
||||
s.storage.plusWorkaround = true
|
||||
s.manager.moveErr = errors.New("move failed")
|
||||
err := s.storage.RenameFile("old+name", "new+name")
|
||||
c.Assert(err, ErrorMatches, "move failed")
|
||||
c.Assert(s.manager.moveParams[0].Pattern, Equals, filepath.Join("repo", "prefix", "old%2Bname"))
|
||||
c.Assert(s.manager.moveParams[0].Target, Equals, filepath.Join("repo", "prefix", "new%2Bname"))
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestSymLinkAndHardLink(c *C) {
|
||||
err := s.storage.SymLink("src+name", "dst+name")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(len(s.manager.copyParams), Equals, 1)
|
||||
c.Assert(s.manager.copyParams[0].Pattern, Equals, filepath.Join("repo", "prefix", "src+name"))
|
||||
c.Assert(s.manager.copyParams[0].Target, Equals, filepath.Join("repo", "prefix", "dst+name"))
|
||||
c.Assert(s.manager.copyParams[0].Flat, Equals, true)
|
||||
targetProps := s.manager.copyParams[0].TargetProps.ToMap()
|
||||
c.Assert(targetProps["SymLink"], DeepEquals, []string{"src+name"})
|
||||
|
||||
err = s.storage.HardLink("a", "b")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(len(s.manager.copyParams), Equals, 2)
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestSymLinkPlusWorkaroundAndError(c *C) {
|
||||
s.storage.plusWorkaround = true
|
||||
s.manager.copyErr = errors.New("copy failed")
|
||||
|
||||
err := s.storage.SymLink("src+name", "dst+name")
|
||||
c.Assert(err, ErrorMatches, "copy failed")
|
||||
c.Assert(s.manager.copyParams[0].Pattern, Equals, filepath.Join("repo", "prefix", "src%2Bname"))
|
||||
c.Assert(s.manager.copyParams[0].Target, Equals, filepath.Join("repo", "prefix", "dst%2Bname"))
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestFileExists(c *C) {
|
||||
s.manager.searchReader = createReader(c, []jfrogutils.ResultItem{{Path: "repo/prefix/pool", Name: "x"}})
|
||||
ok, err := s.storage.FileExists("pool/x")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(ok, Equals, true)
|
||||
c.Assert(s.manager.searchParams[0].Pattern, Equals, filepath.Join("repo", "prefix", "pool/x"))
|
||||
|
||||
s.manager.searchReader = content.NewEmptyContentReader("results")
|
||||
ok, err = s.storage.FileExists("pool/y")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(ok, Equals, false)
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestFileExistsSearchErrorAndPlusWorkaround(c *C) {
|
||||
s.storage.plusWorkaround = true
|
||||
s.manager.searchErr = errors.New("search failed")
|
||||
ok, err := s.storage.FileExists("pool/a+b")
|
||||
c.Assert(ok, Equals, false)
|
||||
c.Assert(err, ErrorMatches, "search failed")
|
||||
c.Assert(s.manager.searchParams[0].Pattern, Equals, filepath.Join("repo", "prefix", "pool/a%2Bb"))
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestReadLink(c *C) {
|
||||
s.manager.itemProps = &jfrogutils.ItemProperties{
|
||||
Properties: map[string][]string{
|
||||
"SymLink": {"src/file"},
|
||||
},
|
||||
}
|
||||
|
||||
link, err := s.storage.ReadLink("path/to/link")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(link, Equals, "src/file")
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestReadLinkNoPropertyAndErrors(c *C) {
|
||||
s.manager.itemProps = &jfrogutils.ItemProperties{Properties: map[string][]string{"Other": {"value"}}}
|
||||
link, err := s.storage.ReadLink("path/to/link")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(link, Equals, "")
|
||||
|
||||
s.manager.itemPropsErr = errors.New("props failed")
|
||||
link, err = s.storage.ReadLink("path/to/link")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(link, Equals, "")
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestReadLinkPlusWorkaround(c *C) {
|
||||
s.storage.plusWorkaround = true
|
||||
s.manager.itemProps = &jfrogutils.ItemProperties{}
|
||||
_, _ = s.storage.ReadLink("a+b")
|
||||
// Ensure the method runs with plusWorkaround path conversion.
|
||||
c.Assert(s.manager.itemPropsErr, IsNil)
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestCreatePublishedStorageConfig(c *C) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
withUserPassword, err := createPublishedStorageConfig(server.URL, "user", "password", "", "")
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
withUserPasswordDetails := withUserPassword.GetServiceDetails()
|
||||
c.Assert(withUserPasswordDetails, NotNil)
|
||||
c.Assert(withUserPasswordDetails.GetUser(), Equals, "user")
|
||||
|
||||
withAPIKey, err := createPublishedStorageConfig(server.URL, "", "", "api-123", "")
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
withAPIKeyDetails := withAPIKey.GetServiceDetails()
|
||||
c.Assert(withAPIKeyDetails, NotNil)
|
||||
c.Assert(withAPIKeyDetails.GetApiKey(), Equals, "api-123")
|
||||
|
||||
withAccessToken, err := createPublishedStorageConfig(server.URL, "", "", "", "token")
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
withAccessTokenDetails := withAccessToken.GetServiceDetails()
|
||||
c.Assert(withAccessTokenDetails, NotNil)
|
||||
c.Assert(withAccessTokenDetails.GetAccessToken(), Equals, "token")
|
||||
|
||||
withUserPasswordFromEnv, err := createPublishedStorageConfig(server.URL, "", "password", "", "")
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
withUserPasswordFromEnvDetails := withUserPasswordFromEnv.GetServiceDetails()
|
||||
c.Assert(withUserPasswordFromEnvDetails, NotNil)
|
||||
c.Assert(withUserPasswordFromEnvDetails.GetUser(), Equals, "userfromenv")
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestNewPublishedStorageRaw(c *C) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
withUserPassword, err := NewPublishedStorageRaw("repo", server.URL, "user", "password", "", "", "prefix", true, false)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(withUserPassword, NotNil)
|
||||
c.Assert(withUserPassword.String(), Equals, "jfrog:repo:prefix")
|
||||
|
||||
withAPIKey, err := NewPublishedStorageRaw("repo", server.URL, "", "", "api-key", "", "prefix", false, false)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(withAPIKey, NotNil)
|
||||
|
||||
withToken, err := NewPublishedStorageRaw("repo", server.URL, "", "", "", "token", "prefix", false, false)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(withToken, NotNil)
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestNewPublishedStorageRawManagerError(c *C) {
|
||||
// An SSH URL causes artifactory.New() to fail (no SSH key configured),
|
||||
// exercising the error return on lines 59-61.
|
||||
_, err := NewPublishedStorageRaw("repo", "ssh://example.local/artifactory", "", "", "", "", "", false, false)
|
||||
c.Assert(err, ErrorMatches, "error creating jfrog manager: .*")
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestNewPublishedStorage(c *C) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
storage, err := NewPublishedStorage("test", aptly_utils.JFrogPublishRoot{
|
||||
Repository: "repo",
|
||||
Url: server.URL,
|
||||
AccessToken: "token",
|
||||
Prefix: "pref",
|
||||
PlusWorkaround: true,
|
||||
})
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(storage, NotNil)
|
||||
c.Assert(storage.String(), Equals, "jfrog:repo:pref")
|
||||
}
|
||||
|
||||
var _ aptly.PublishedStorage = (*PublishedStorage)(nil)
|
||||
@@ -356,6 +356,29 @@ The legacy json configuration is still supported (and also supports comments):
|
||||
// }
|
||||
},
|
||||
|
||||
// JFrog Artifactory Endpoint Support
|
||||
// aptly could be configured to publish repository directly to JFrog Artifactory. First,
|
||||
// endpoints should be described in aptly.conf:
|
||||
//
|
||||
// The destination Artifactory repo should be of the "generic" type, not "debian".
|
||||
// Authentication requires one of: user+pass, api key, or access token
|
||||
//
|
||||
// In order to publish to JFrog, specify endpoint as `jfrog:endpoint-name:` before
|
||||
// publishing prefix on the command line, e.g.:
|
||||
//
|
||||
// `aptly publish snapshot wheezy-main jfrog:test:`
|
||||
//
|
||||
"JFrogPublishEndpoints": {
|
||||
"test": {
|
||||
"url": "https://artifactory.example.com/artifactory/",
|
||||
"repository": "apt-local",
|
||||
"username": "admin",
|
||||
"password": "password",
|
||||
"api_key": "api_key",
|
||||
"access_token": "access_token"
|
||||
}
|
||||
}
|
||||
|
||||
// Swift Endpoint Support
|
||||
//
|
||||
// aptly could be configured to publish repository directly to OpenStack Swift. First,
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
from lib import BaseTest
|
||||
import uuid
|
||||
import os
|
||||
|
||||
try:
|
||||
import requests
|
||||
|
||||
if 'JFROG_URL' in os.environ and 'JFROG_USERNAME' in os.environ and \
|
||||
os.environ['JFROG_URL'] != "" and os.environ['JFROG_USERNAME'] != "":
|
||||
jfrog_ready = True
|
||||
else:
|
||||
print("JFrog tests disabled: JFrog creds not found in the environment (JFROG_URL, JFROG_USERNAME, JFROG_PASSWORD)")
|
||||
jfrog_ready = False
|
||||
except ImportError as e:
|
||||
print("JFrog tests disabled: can't import requests", e)
|
||||
jfrog_ready = False
|
||||
|
||||
|
||||
class JFrogTest(BaseTest):
|
||||
"""
|
||||
BaseTest + support for JFrog
|
||||
"""
|
||||
|
||||
jfrogOverrides = {}
|
||||
|
||||
def fixture_available(self):
|
||||
return super(JFrogTest, self).fixture_available() and jfrog_ready
|
||||
|
||||
def prepare(self):
|
||||
self.repository = "aptly-sys-test-" + str(uuid.uuid1())
|
||||
self.jfrog_url = os.environ["JFROG_URL"]
|
||||
self.jfrog_username = os.environ["JFROG_USERNAME"]
|
||||
self.jfrog_password = os.environ["JFROG_PASSWORD"]
|
||||
|
||||
# Create repository via REST API
|
||||
auth = (self.jfrog_username, self.jfrog_password)
|
||||
create_url = f"{self.jfrog_url}/api/repositories/{self.repository}"
|
||||
payload = {
|
||||
"key": self.repository,
|
||||
"rclass": "local",
|
||||
"packageType": "generic"
|
||||
}
|
||||
res = requests.put(create_url, json=payload, auth=auth)
|
||||
if res.status_code >= 400:
|
||||
raise Exception(f"Failed to create JFrog repository: {res.text}")
|
||||
|
||||
self.configOverride = {"JFrogPublishEndpoints": {
|
||||
"test1": {
|
||||
"url": self.jfrog_url,
|
||||
"repository": self.repository,
|
||||
"username": self.jfrog_username,
|
||||
"password": self.jfrog_password
|
||||
}
|
||||
}}
|
||||
|
||||
self.configOverride["JFrogPublishEndpoints"]["test1"].update(**self.jfrogOverrides)
|
||||
|
||||
super(JFrogTest, self).prepare()
|
||||
|
||||
def shutdown(self):
|
||||
if hasattr(self, "repository"):
|
||||
auth = (self.jfrog_username, self.jfrog_password)
|
||||
delete_url = f"{self.jfrog_url}/api/repositories/{self.repository}"
|
||||
requests.delete(delete_url, auth=auth)
|
||||
|
||||
super(JFrogTest, self).shutdown()
|
||||
|
||||
def check_path(self, path):
|
||||
if path.startswith("public/"):
|
||||
path = path[7:]
|
||||
|
||||
# Check against JFrog Artifactory API
|
||||
auth = (self.jfrog_username, self.jfrog_password)
|
||||
check_url = f"{self.jfrog_url}/api/storage/{self.repository}/{path}"
|
||||
res = requests.head(check_url, auth=auth)
|
||||
if res.status_code == 200:
|
||||
return True
|
||||
return False
|
||||
|
||||
def check_exists(self, path):
|
||||
if not self.check_path(path):
|
||||
raise Exception("path %s doesn't exist" % (path, ))
|
||||
|
||||
def check_not_exists(self, path):
|
||||
if self.check_path(path):
|
||||
raise Exception("path %s exists" % (path, ))
|
||||
|
||||
def read_file(self, path, mode=''):
|
||||
assert not mode
|
||||
if path.startswith("public/"):
|
||||
path = path[7:]
|
||||
|
||||
auth = (self.jfrog_username, self.jfrog_password)
|
||||
get_url = f"{self.jfrog_url}/{self.repository}/{path}"
|
||||
res = requests.get(get_url, auth=auth)
|
||||
res.raise_for_status()
|
||||
return res.text
|
||||
@@ -34,6 +34,7 @@
|
||||
"skipContentsPublishing": false,
|
||||
"skipBz2Publishing": false,
|
||||
"FileSystemPublishEndpoints": {},
|
||||
"JFrogPublishEndpoints": null,
|
||||
"S3PublishEndpoints": {},
|
||||
"GcsPublishEndpoints": {},
|
||||
"SwiftPublishEndpoints": {},
|
||||
|
||||
@@ -32,6 +32,7 @@ gpg_keys: []
|
||||
skip_contents_publishing: false
|
||||
skip_bz2_publishing: false
|
||||
filesystem_publish_endpoints: {}
|
||||
jfrog_publish_endpoints: {}
|
||||
s3_publish_endpoints: {}
|
||||
gcs_publish_endpoints: {}
|
||||
swift_publish_endpoints: {}
|
||||
|
||||
@@ -196,6 +196,35 @@ filesystem_publish_endpoints:
|
||||
#
|
||||
# `aptly publish snapshot wheezy-main s3:test:`
|
||||
#
|
||||
|
||||
# JFrog Artifactory Endpoint Support
|
||||
#
|
||||
# aptly can be configured to publish repositories directly to JFrog Artifactory. First,
|
||||
# publishing endpoints should be described in the aptly configuration file.
|
||||
#
|
||||
# The destination Artifactory repo should be of the "generic" type, not "debian".
|
||||
#
|
||||
# In order to publish to JFrog, specify endpoint as `jfrog:endpoint-name:` before
|
||||
# publishing prefix on the command line, e.g.:
|
||||
#
|
||||
# `aptly publish snapshot wheezy-main jfrog:test:`
|
||||
#
|
||||
jfrog_publish_endpoints:
|
||||
# # Endpoint Name
|
||||
# test:
|
||||
# # JFrog URL
|
||||
# url: "https://artifactory.example.com/artifactory/"
|
||||
# # Repository
|
||||
# repository: apt-local
|
||||
# # Jfrog credentials to authenticate to Artifactory. If not supplied, the
|
||||
# # environment variables `JFROG_USERNAME`, `JFROG_PASSWORD`, `JFROG_APIKEY`,
|
||||
# # and `JFROG_ACCESSTOKEN` can be used
|
||||
# # Authentication requires one of: user+pass, api key, or access token
|
||||
# username: admin
|
||||
# password: password
|
||||
# api_key: api_key
|
||||
# access_token: access_token
|
||||
|
||||
s3_publish_endpoints:
|
||||
# # Endpoint Name
|
||||
# test:
|
||||
@@ -396,3 +425,5 @@ packagepool_storage:
|
||||
# # defaults to "https://<accountName>.blob.core.windows.net"
|
||||
# endpoint: ""
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
from jfrog_lib import JFrogTest
|
||||
|
||||
|
||||
def strip_processor(output):
|
||||
return '\n'.join(
|
||||
[
|
||||
l
|
||||
for l in output.split('\n')
|
||||
if not l.startswith(' ') and not l.startswith('Date:')
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class JFrogPublish1Test(JFrogTest):
|
||||
"""
|
||||
publish to JFrog: from repo
|
||||
"""
|
||||
|
||||
fixtureCmds = [
|
||||
'aptly repo create -distribution=maverick local-repo',
|
||||
'aptly repo add local-repo ${files}',
|
||||
'aptly repo remove local-repo libboost-program-options-dev_1.62.0.1_i386',
|
||||
]
|
||||
runCmd = 'aptly publish repo -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec local-repo jfrog:test1:'
|
||||
|
||||
def check(self):
|
||||
self.check_exists('public/dists/maverick/InRelease')
|
||||
self.check_exists('public/dists/maverick/Release')
|
||||
self.check_exists('public/dists/maverick/Release.gpg')
|
||||
|
||||
self.check_exists('public/dists/maverick/main/binary-i386/Packages')
|
||||
self.check_exists('public/dists/maverick/main/binary-i386/Packages.gz')
|
||||
self.check_exists('public/dists/maverick/main/binary-i386/Packages.bz2')
|
||||
self.check_exists('public/dists/maverick/main/source/Sources')
|
||||
self.check_exists('public/dists/maverick/main/source/Sources.gz')
|
||||
self.check_exists('public/dists/maverick/main/source/Sources.bz2')
|
||||
|
||||
self.check_exists('public/pool/main/p/pyspi/pyspi_0.6.1-1.3.dsc')
|
||||
self.check_exists('public/pool/main/p/pyspi/pyspi_0.6.1-1.3.diff.gz')
|
||||
self.check_exists('public/pool/main/p/pyspi/pyspi_0.6.1.orig.tar.gz')
|
||||
self.check_exists('public/pool/main/p/pyspi/pyspi-0.6.1-1.3.stripped.dsc')
|
||||
self.check_exists(
|
||||
'public/pool/main/b/boost-defaults/libboost-program-options-dev_1.49.0.1_i386.deb'
|
||||
)
|
||||
|
||||
# verify contents except sums/date chunks
|
||||
self.check_file_contents(
|
||||
'public/dists/maverick/Release', 'release', match_prepare=strip_processor
|
||||
)
|
||||
self.check_file_contents(
|
||||
'public/dists/maverick/main/source/Sources',
|
||||
'sources',
|
||||
match_prepare=lambda s: '\n'.join(sorted(s.split('\n'))),
|
||||
)
|
||||
self.check_file_contents(
|
||||
'public/dists/maverick/main/binary-i386/Packages',
|
||||
'binary',
|
||||
match_prepare=lambda s: '\n'.join(sorted(s.split('\n'))),
|
||||
)
|
||||
|
||||
|
||||
class JFrogPublish2Test(JFrogTest):
|
||||
"""
|
||||
publish to JFrog: update after removing package from repo
|
||||
"""
|
||||
|
||||
fixtureCmds = [
|
||||
'aptly repo create -distribution=maverick local-repo',
|
||||
'aptly repo add local-repo ${files}/',
|
||||
'aptly repo remove local-repo libboost-program-options-dev_1.62.0.1_i386',
|
||||
'aptly publish repo -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec local-repo jfrog:test1:',
|
||||
'aptly repo remove local-repo pyspi',
|
||||
]
|
||||
runCmd = 'aptly publish update -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec maverick jfrog:test1:'
|
||||
|
||||
def check(self):
|
||||
self.check_exists('public/dists/maverick/InRelease')
|
||||
self.check_exists('public/dists/maverick/Release')
|
||||
self.check_exists('public/dists/maverick/Release.gpg')
|
||||
|
||||
self.check_not_exists('public/pool/main/p/pyspi/pyspi_0.6.1-1.3.dsc')
|
||||
self.check_not_exists('public/pool/main/p/pyspi/pyspi_0.6.1-1.3.diff.gz')
|
||||
self.check_not_exists('public/pool/main/p/pyspi/pyspi_0.6.1.orig.tar.gz')
|
||||
self.check_not_exists('public/pool/main/p/pyspi/pyspi-0.6.1-1.3.stripped.dsc')
|
||||
self.check_exists(
|
||||
'public/pool/main/b/boost-defaults/libboost-program-options-dev_1.49.0.1_i386.deb'
|
||||
)
|
||||
|
||||
|
||||
class JFrogPublish3Test(JFrogTest):
|
||||
"""
|
||||
publish to JFrog: publish drop performs cleanup
|
||||
"""
|
||||
|
||||
fixtureCmds = [
|
||||
'aptly repo create local1',
|
||||
'aptly repo create local2',
|
||||
'aptly repo add local1 ${files}/libboost-program-options-dev_1.49.0.1_i386.deb',
|
||||
'aptly repo add local2 ${files}',
|
||||
'aptly publish repo -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec -distribution=sq1 local1 jfrog:test1:',
|
||||
'aptly publish repo -keyring=${files}/aptly.pub -secret-keyring=${files}/aptly.sec -distribution=sq2 local2 jfrog:test1:',
|
||||
]
|
||||
runCmd = 'aptly publish drop sq2 jfrog:test1:'
|
||||
|
||||
def check(self):
|
||||
self.check_exists('public/dists/sq1')
|
||||
self.check_not_exists('public/dists/sq2')
|
||||
self.check_exists('public/pool/main/')
|
||||
|
||||
self.check_not_exists('public/pool/main/p/pyspi/pyspi_0.6.1-1.3.dsc')
|
||||
self.check_not_exists('public/pool/main/p/pyspi/pyspi_0.6.1-1.3.diff.gz')
|
||||
self.check_not_exists('public/pool/main/p/pyspi/pyspi_0.6.1.orig.tar.gz')
|
||||
self.check_not_exists('public/pool/main/p/pyspi/pyspi-0.6.1-1.3.stripped.dsc')
|
||||
self.check_exists(
|
||||
'public/pool/main/b/boost-defaults/libboost-program-options-dev_1.49.0.1_i386.deb'
|
||||
)
|
||||
@@ -61,6 +61,7 @@ type ConfigStructure struct { // nolint: maligned
|
||||
|
||||
// Storage
|
||||
FileSystemPublishRoots map[string]FileSystemPublishRoot `json:"FileSystemPublishEndpoints" yaml:"filesystem_publish_endpoints"`
|
||||
JFrogPublishRoots map[string]JFrogPublishRoot `json:"JFrogPublishEndpoints" yaml:"jfrog_publish_endpoints"`
|
||||
S3PublishRoots map[string]S3PublishRoot `json:"S3PublishEndpoints" yaml:"s3_publish_endpoints"`
|
||||
GCSPublishRoots map[string]GCSPublishRoot `json:"GcsPublishEndpoints" yaml:"gcs_publish_endpoints"`
|
||||
SwiftPublishRoots map[string]SwiftPublishRoot `json:"SwiftPublishEndpoints" yaml:"swift_publish_endpoints"`
|
||||
@@ -172,6 +173,19 @@ type FileSystemPublishRoot struct {
|
||||
}
|
||||
|
||||
// S3PublishRoot describes single S3 publishing entry point
|
||||
|
||||
type JFrogPublishRoot struct {
|
||||
Repository string `json:"repository" yaml:"repository"`
|
||||
Url string `json:"url" yaml:"url"`
|
||||
User string `json:"user" yaml:"user"`
|
||||
Password string `json:"password" yaml:"password"`
|
||||
ApiKey string `json:"apiKey" yaml:"api_key"`
|
||||
AccessToken string `json:"accessToken" yaml:"access_token"`
|
||||
Prefix string `json:"prefix" yaml:"prefix"`
|
||||
PlusWorkaround bool `json:"plusWorkaround" yaml:"plus_workaround"`
|
||||
Debug bool `json:"debug" yaml:"debug"`
|
||||
}
|
||||
|
||||
type S3PublishRoot struct {
|
||||
Region string `json:"region" yaml:"region"`
|
||||
Bucket string `json:"bucket" yaml:"bucket"`
|
||||
|
||||
+217
-199
@@ -45,6 +45,10 @@ func (s *ConfigSuite) TestSaveConfig(c *C) {
|
||||
s.config.FileSystemPublishRoots = map[string]FileSystemPublishRoot{"test": {
|
||||
RootDir: "/opt/aptly-publish"}}
|
||||
|
||||
s.config.JFrogPublishRoots = map[string]JFrogPublishRoot{"test": {
|
||||
Repository: "repo",
|
||||
Url: "jfrog.example.com"}}
|
||||
|
||||
s.config.S3PublishRoots = map[string]S3PublishRoot{"test": {
|
||||
Region: "us-east-1",
|
||||
Bucket: "repo"}}
|
||||
@@ -73,232 +77,245 @@ func (s *ConfigSuite) TestSaveConfig(c *C) {
|
||||
buf := make([]byte, st.Size())
|
||||
_, _ = f.Read(buf)
|
||||
|
||||
c.Check(string(buf), Equals, ""+
|
||||
"{\n" +
|
||||
" \"rootDir\": \"/tmp/aptly\",\n" +
|
||||
" \"logLevel\": \"info\",\n" +
|
||||
" \"logFormat\": \"json\",\n" +
|
||||
" \"databaseOpenAttempts\": 5,\n" +
|
||||
" \"architectures\": null,\n" +
|
||||
" \"skipLegacyPool\": false,\n" +
|
||||
" \"dependencyFollowSuggests\": false,\n" +
|
||||
" \"dependencyFollowRecommends\": false,\n" +
|
||||
" \"dependencyFollowAllVariants\": false,\n" +
|
||||
" \"dependencyFollowSource\": false,\n" +
|
||||
" \"dependencyVerboseResolve\": false,\n" +
|
||||
" \"ppaDistributorID\": \"\",\n" +
|
||||
" \"ppaCodename\": \"\",\n" +
|
||||
" \"ppaBaseURL\": \"\",\n" +
|
||||
" \"serveInAPIMode\": false,\n" +
|
||||
" \"enableMetricsEndpoint\": false,\n" +
|
||||
" \"enableSwaggerEndpoint\": false,\n" +
|
||||
" \"AsyncAPI\": false,\n" +
|
||||
" \"databaseBackend\": {\n" +
|
||||
" \"type\": \"\",\n" +
|
||||
" \"dbPath\": \"\",\n" +
|
||||
" \"url\": \"\"\n" +
|
||||
" },\n" +
|
||||
" \"downloader\": \"\",\n" +
|
||||
" \"downloadConcurrency\": 5,\n" +
|
||||
" \"downloadSpeedLimit\": 0,\n" +
|
||||
" \"downloadRetries\": 0,\n" +
|
||||
" \"downloadSourcePackages\": false,\n" +
|
||||
" \"gpgProvider\": \"gpg\",\n" +
|
||||
" \"gpgDisableSign\": false,\n" +
|
||||
" \"gpgDisableVerify\": false,\n" +
|
||||
" \"gpgKeys\": null,\n" +
|
||||
" \"skipContentsPublishing\": false,\n" +
|
||||
" \"skipBz2Publishing\": false,\n" +
|
||||
" \"FileSystemPublishEndpoints\": {\n" +
|
||||
" \"test\": {\n" +
|
||||
" \"rootDir\": \"/opt/aptly-publish\",\n" +
|
||||
" \"linkMethod\": \"\",\n" +
|
||||
" \"verifyMethod\": \"\"\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"S3PublishEndpoints\": {\n" +
|
||||
" \"test\": {\n" +
|
||||
" \"region\": \"us-east-1\",\n" +
|
||||
" \"bucket\": \"repo\",\n" +
|
||||
" \"prefix\": \"\",\n" +
|
||||
" \"acl\": \"\",\n" +
|
||||
" \"awsAccessKeyID\": \"\",\n" +
|
||||
" \"awsSecretAccessKey\": \"\",\n" +
|
||||
" \"awsSessionToken\": \"\",\n" +
|
||||
" \"endpoint\": \"\",\n" +
|
||||
" \"storageClass\": \"\",\n" +
|
||||
" \"encryptionMethod\": \"\",\n" +
|
||||
" \"plusWorkaround\": false,\n" +
|
||||
" \"disableMultiDel\": false,\n" +
|
||||
" \"forceSigV2\": false,\n" +
|
||||
" \"forceVirtualHostedStyle\": false,\n" +
|
||||
" \"debug\": false\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"GcsPublishEndpoints\": {\n" +
|
||||
" \"test\": {\n" +
|
||||
" \"bucket\": \"repo\",\n" +
|
||||
" \"prefix\": \"\",\n" +
|
||||
" \"credentialsFile\": \"\",\n" +
|
||||
" \"serviceAccountJSON\": \"\",\n" +
|
||||
" \"project\": \"\",\n" +
|
||||
" \"endpoint\": \"\",\n" +
|
||||
" \"acl\": \"\",\n" +
|
||||
" \"storageClass\": \"\",\n" +
|
||||
" \"encryptionKey\": \"\",\n" +
|
||||
" \"disableMultiDel\": false,\n" +
|
||||
" \"debug\": false\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"SwiftPublishEndpoints\": {\n" +
|
||||
" \"test\": {\n" +
|
||||
" \"container\": \"repo\",\n" +
|
||||
" \"prefix\": \"\",\n" +
|
||||
" \"osname\": \"\",\n" +
|
||||
" \"password\": \"\",\n" +
|
||||
" \"tenant\": \"\",\n" +
|
||||
" \"tenantid\": \"\",\n" +
|
||||
" \"domain\": \"\",\n" +
|
||||
" \"domainid\": \"\",\n" +
|
||||
" \"tenantdomain\": \"\",\n" +
|
||||
" \"tenantdomainid\": \"\",\n" +
|
||||
" \"authurl\": \"\"\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"AzurePublishEndpoints\": {\n" +
|
||||
" \"test\": {\n" +
|
||||
" \"container\": \"repo\",\n" +
|
||||
" \"prefix\": \"\",\n" +
|
||||
" \"accountName\": \"\",\n" +
|
||||
" \"accountKey\": \"\",\n" +
|
||||
" \"endpoint\": \"\"\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"packagePoolStorage\": {\n" +
|
||||
" \"type\": \"local\",\n" +
|
||||
" \"path\": \"/tmp/aptly-pool\"\n" +
|
||||
" }\n" +
|
||||
"}")
|
||||
c.Check(string(buf), Equals, `{
|
||||
"rootDir": "/tmp/aptly",
|
||||
"logLevel": "info",
|
||||
"logFormat": "json",
|
||||
"databaseOpenAttempts": 5,
|
||||
"architectures": null,
|
||||
"skipLegacyPool": false,
|
||||
"dependencyFollowSuggests": false,
|
||||
"dependencyFollowRecommends": false,
|
||||
"dependencyFollowAllVariants": false,
|
||||
"dependencyFollowSource": false,
|
||||
"dependencyVerboseResolve": false,
|
||||
"ppaDistributorID": "",
|
||||
"ppaCodename": "",
|
||||
"ppaBaseURL": "",
|
||||
"serveInAPIMode": false,
|
||||
"enableMetricsEndpoint": false,
|
||||
"enableSwaggerEndpoint": false,
|
||||
"AsyncAPI": false,
|
||||
"databaseBackend": {
|
||||
"type": "",
|
||||
"dbPath": "",
|
||||
"url": ""
|
||||
},
|
||||
"downloader": "",
|
||||
"downloadConcurrency": 5,
|
||||
"downloadSpeedLimit": 0,
|
||||
"downloadRetries": 0,
|
||||
"downloadSourcePackages": false,
|
||||
"gpgProvider": "gpg",
|
||||
"gpgDisableSign": false,
|
||||
"gpgDisableVerify": false,
|
||||
"gpgKeys": null,
|
||||
"skipContentsPublishing": false,
|
||||
"skipBz2Publishing": false,
|
||||
"FileSystemPublishEndpoints": {
|
||||
"test": {
|
||||
"rootDir": "/opt/aptly-publish",
|
||||
"linkMethod": "",
|
||||
"verifyMethod": ""
|
||||
}
|
||||
},
|
||||
"JFrogPublishEndpoints": {
|
||||
"test": {
|
||||
"repository": "repo",
|
||||
"url": "jfrog.example.com",
|
||||
"user": "",
|
||||
"password": "",
|
||||
"apiKey": "",
|
||||
"accessToken": "",
|
||||
"prefix": "",
|
||||
"plusWorkaround": false,
|
||||
"debug": false
|
||||
}
|
||||
},
|
||||
"S3PublishEndpoints": {
|
||||
"test": {
|
||||
"region": "us-east-1",
|
||||
"bucket": "repo",
|
||||
"prefix": "",
|
||||
"acl": "",
|
||||
"awsAccessKeyID": "",
|
||||
"awsSecretAccessKey": "",
|
||||
"awsSessionToken": "",
|
||||
"endpoint": "",
|
||||
"storageClass": "",
|
||||
"encryptionMethod": "",
|
||||
"plusWorkaround": false,
|
||||
"disableMultiDel": false,
|
||||
"forceSigV2": false,
|
||||
"forceVirtualHostedStyle": false,
|
||||
"debug": false
|
||||
}
|
||||
},
|
||||
"GcsPublishEndpoints": {
|
||||
"test": {
|
||||
"bucket": "repo",
|
||||
"prefix": "",
|
||||
"credentialsFile": "",
|
||||
"serviceAccountJSON": "",
|
||||
"project": "",
|
||||
"endpoint": "",
|
||||
"acl": "",
|
||||
"storageClass": "",
|
||||
"encryptionKey": "",
|
||||
"disableMultiDel": false,
|
||||
"debug": false
|
||||
}
|
||||
},
|
||||
"SwiftPublishEndpoints": {
|
||||
"test": {
|
||||
"container": "repo",
|
||||
"prefix": "",
|
||||
"osname": "",
|
||||
"password": "",
|
||||
"tenant": "",
|
||||
"tenantid": "",
|
||||
"domain": "",
|
||||
"domainid": "",
|
||||
"tenantdomain": "",
|
||||
"tenantdomainid": "",
|
||||
"authurl": ""
|
||||
}
|
||||
},
|
||||
"AzurePublishEndpoints": {
|
||||
"test": {
|
||||
"container": "repo",
|
||||
"prefix": "",
|
||||
"accountName": "",
|
||||
"accountKey": "",
|
||||
"endpoint": ""
|
||||
}
|
||||
},
|
||||
"packagePoolStorage": {
|
||||
"type": "local",
|
||||
"path": "/tmp/aptly-pool"
|
||||
}
|
||||
}`)
|
||||
}
|
||||
|
||||
func (s *ConfigSuite) TestLoadYAMLConfig(c *C) {
|
||||
configname := filepath.Join(c.MkDir(), "aptly.yaml1")
|
||||
f, _ := os.Create(configname)
|
||||
_, _ = f.WriteString(configFileYAML)
|
||||
_ = f.Close()
|
||||
configname := filepath.Join(c.MkDir(), "aptly.yaml1")
|
||||
f, _ := os.Create(configname)
|
||||
_, _ = f.WriteString(configFileYAML)
|
||||
_ = f.Close()
|
||||
|
||||
// start with empty config
|
||||
s.config = ConfigStructure{}
|
||||
// start with empty config
|
||||
s.config = ConfigStructure{}
|
||||
|
||||
err := LoadConfig(configname, &s.config)
|
||||
c.Assert(err, IsNil)
|
||||
c.Check(s.config.GetRootDir(), Equals, "/opt/aptly/")
|
||||
c.Check(s.config.DownloadConcurrency, Equals, 40)
|
||||
c.Check(s.config.DatabaseOpenAttempts, Equals, 10)
|
||||
err := LoadConfig(configname, &s.config)
|
||||
c.Assert(err, IsNil)
|
||||
c.Check(s.config.GetRootDir(), Equals, "/opt/aptly/")
|
||||
c.Check(s.config.DownloadConcurrency, Equals, 40)
|
||||
c.Check(s.config.DatabaseOpenAttempts, Equals, 10)
|
||||
}
|
||||
|
||||
func (s *ConfigSuite) TestLoadYAMLErrorConfig(c *C) {
|
||||
configname := filepath.Join(c.MkDir(), "aptly.yaml2")
|
||||
f, _ := os.Create(configname)
|
||||
_, _ = f.WriteString(configFileYAMLError)
|
||||
_ = f.Close()
|
||||
configname := filepath.Join(c.MkDir(), "aptly.yaml2")
|
||||
f, _ := os.Create(configname)
|
||||
_, _ = f.WriteString(configFileYAMLError)
|
||||
_ = f.Close()
|
||||
|
||||
// start with empty config
|
||||
s.config = ConfigStructure{}
|
||||
// start with empty config
|
||||
s.config = ConfigStructure{}
|
||||
|
||||
err := LoadConfig(configname, &s.config)
|
||||
c.Assert(err.Error(), Equals, "invalid yaml (unknown pool storage type: invalid) or json (invalid character 'p' looking for beginning of value)")
|
||||
err := LoadConfig(configname, &s.config)
|
||||
c.Assert(err.Error(), Equals, "invalid yaml (unknown pool storage type: invalid) or json (invalid character 'p' looking for beginning of value)")
|
||||
}
|
||||
|
||||
func (s *ConfigSuite) TestSaveYAMLConfig(c *C) {
|
||||
configname := filepath.Join(c.MkDir(), "aptly.yaml3")
|
||||
f, _ := os.Create(configname)
|
||||
_, _ = f.WriteString(configFileYAML)
|
||||
_ = f.Close()
|
||||
configname := filepath.Join(c.MkDir(), "aptly.yaml3")
|
||||
f, _ := os.Create(configname)
|
||||
_, _ = f.WriteString(configFileYAML)
|
||||
_ = f.Close()
|
||||
|
||||
// start with empty config
|
||||
s.config = ConfigStructure{}
|
||||
// start with empty config
|
||||
s.config = ConfigStructure{}
|
||||
|
||||
err := LoadConfig(configname, &s.config)
|
||||
c.Assert(err, IsNil)
|
||||
err := LoadConfig(configname, &s.config)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
err = SaveConfigYAML(configname, &s.config)
|
||||
c.Assert(err, IsNil)
|
||||
err = SaveConfigYAML(configname, &s.config)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
f, _ = os.Open(configname)
|
||||
defer func() {
|
||||
_ = f.Close()
|
||||
}()
|
||||
f, _ = os.Open(configname)
|
||||
defer func() {
|
||||
_ = f.Close()
|
||||
}()
|
||||
|
||||
st, _ := f.Stat()
|
||||
buf := make([]byte, st.Size())
|
||||
_, _ = f.Read(buf)
|
||||
st, _ := f.Stat()
|
||||
buf := make([]byte, st.Size())
|
||||
_, _ = f.Read(buf)
|
||||
|
||||
c.Check(string(buf), Equals, configFileYAML)
|
||||
c.Check(string(buf), Equals, configFileYAML)
|
||||
}
|
||||
|
||||
func (s *ConfigSuite) TestSaveYAML2Config(c *C) {
|
||||
// start with empty config
|
||||
s.config = ConfigStructure{}
|
||||
// start with empty config
|
||||
s.config = ConfigStructure{}
|
||||
|
||||
s.config.PackagePoolStorage.Local = &LocalPoolStorage{"/tmp/aptly-pool"}
|
||||
s.config.PackagePoolStorage.Azure = nil
|
||||
s.config.PackagePoolStorage.Local = &LocalPoolStorage{"/tmp/aptly-pool"}
|
||||
s.config.PackagePoolStorage.Azure = nil
|
||||
|
||||
configname := filepath.Join(c.MkDir(), "aptly.yaml4")
|
||||
err := SaveConfigYAML(configname, &s.config)
|
||||
c.Assert(err, IsNil)
|
||||
configname := filepath.Join(c.MkDir(), "aptly.yaml4")
|
||||
err := SaveConfigYAML(configname, &s.config)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
f, _ := os.Open(configname)
|
||||
defer func() {
|
||||
_ = f.Close()
|
||||
}()
|
||||
f, _ := os.Open(configname)
|
||||
defer func() {
|
||||
_ = f.Close()
|
||||
}()
|
||||
|
||||
st, _ := f.Stat()
|
||||
buf := make([]byte, st.Size())
|
||||
_, _ = f.Read(buf)
|
||||
st, _ := f.Stat()
|
||||
buf := make([]byte, st.Size())
|
||||
_, _ = f.Read(buf)
|
||||
|
||||
c.Check(string(buf), Equals, "" +
|
||||
"root_dir: \"\"\n" +
|
||||
"log_level: \"\"\n" +
|
||||
"log_format: \"\"\n" +
|
||||
"database_open_attempts: 0\n" +
|
||||
"architectures: []\n" +
|
||||
"skip_legacy_pool: false\n" +
|
||||
"dep_follow_suggests: false\n" +
|
||||
"dep_follow_recommends: false\n" +
|
||||
"dep_follow_all_variants: false\n" +
|
||||
"dep_follow_source: false\n" +
|
||||
"dep_verboseresolve: false\n" +
|
||||
"ppa_distributor_id: \"\"\n" +
|
||||
"ppa_codename: \"\"\n" +
|
||||
"ppa_baseurl: \"\"\n" +
|
||||
"serve_in_api_mode: false\n" +
|
||||
"enable_metrics_endpoint: false\n" +
|
||||
"enable_swagger_endpoint: false\n" +
|
||||
"async_api: false\n" +
|
||||
"database_backend:\n" +
|
||||
" type: \"\"\n" +
|
||||
" db_path: \"\"\n" +
|
||||
" url: \"\"\n" +
|
||||
"downloader: \"\"\n" +
|
||||
"download_concurrency: 0\n" +
|
||||
"download_limit: 0\n" +
|
||||
"download_retries: 0\n" +
|
||||
"download_sourcepackages: false\n" +
|
||||
"gpg_provider: \"\"\n" +
|
||||
"gpg_disable_sign: false\n" +
|
||||
"gpg_disable_verify: false\n" +
|
||||
"gpg_keys: []\n" +
|
||||
"skip_contents_publishing: false\n" +
|
||||
"skip_bz2_publishing: false\n" +
|
||||
"filesystem_publish_endpoints: {}\n" +
|
||||
"s3_publish_endpoints: {}\n" +
|
||||
"gcs_publish_endpoints: {}\n" +
|
||||
"swift_publish_endpoints: {}\n" +
|
||||
"azure_publish_endpoints: {}\n" +
|
||||
"packagepool_storage:\n" +
|
||||
" type: local\n" +
|
||||
" path: /tmp/aptly-pool\n")
|
||||
c.Check(string(buf), Equals, ""+
|
||||
"root_dir: \"\"\n"+
|
||||
"log_level: \"\"\n"+
|
||||
"log_format: \"\"\n"+
|
||||
"database_open_attempts: 0\n"+
|
||||
"architectures: []\n"+
|
||||
"skip_legacy_pool: false\n"+
|
||||
"dep_follow_suggests: false\n"+
|
||||
"dep_follow_recommends: false\n"+
|
||||
"dep_follow_all_variants: false\n"+
|
||||
"dep_follow_source: false\n"+
|
||||
"dep_verboseresolve: false\n"+
|
||||
"ppa_distributor_id: \"\"\n"+
|
||||
"ppa_codename: \"\"\n"+
|
||||
"ppa_baseurl: \"\"\n"+
|
||||
"serve_in_api_mode: false\n"+
|
||||
"enable_metrics_endpoint: false\n"+
|
||||
"enable_swagger_endpoint: false\n"+
|
||||
"async_api: false\n"+
|
||||
"database_backend:\n"+
|
||||
" type: \"\"\n"+
|
||||
" db_path: \"\"\n"+
|
||||
" url: \"\"\n"+
|
||||
"downloader: \"\"\n"+
|
||||
"download_concurrency: 0\n"+
|
||||
"download_limit: 0\n"+
|
||||
"download_retries: 0\n"+
|
||||
"download_sourcepackages: false\n"+
|
||||
"gpg_provider: \"\"\n"+
|
||||
"gpg_disable_sign: false\n"+
|
||||
"gpg_disable_verify: false\n"+
|
||||
"gpg_keys: []\n"+
|
||||
"skip_contents_publishing: false\n"+
|
||||
"skip_bz2_publishing: false\n"+
|
||||
"filesystem_publish_endpoints: {}\n"+
|
||||
"jfrog_publish_endpoints: {}\n"+
|
||||
"s3_publish_endpoints: {}\n"+
|
||||
"gcs_publish_endpoints: {}\n"+
|
||||
"swift_publish_endpoints: {}\n"+
|
||||
"azure_publish_endpoints: {}\n"+
|
||||
"packagepool_storage:\n"+
|
||||
" type: local\n"+
|
||||
" path: /tmp/aptly-pool\n")
|
||||
}
|
||||
|
||||
func (s *ConfigSuite) TestLoadEmptyConfig(c *C) {
|
||||
@@ -354,6 +371,7 @@ filesystem_publish_endpoints:
|
||||
root_dir: /opt/srv/aptly_public
|
||||
link_method: hardlink
|
||||
verify_method: md5
|
||||
jfrog_publish_endpoints: {}
|
||||
s3_publish_endpoints:
|
||||
test:
|
||||
region: us-east-1
|
||||
|
||||
Reference in New Issue
Block a user