mirror of
https://github.com/harness/drone.git
synced 2025-05-04 00:59:43 +08:00
feat: [AH-1060]: RPM flows skeleton, RPM package upload (#3599)
* resolve PR comments * fix lint * resolve PR comments * fix lint issue * resolve PR comments * resolve PR comments * fix lint issue * feat: [AH-1060]: RPM flows skeleton, RPM package upload/install
This commit is contained in:
parent
6b50985f20
commit
a3d828f0a2
@ -129,6 +129,7 @@ import (
|
|||||||
npm2 "github.com/harness/gitness/registry/app/api/controller/pkg/npm"
|
npm2 "github.com/harness/gitness/registry/app/api/controller/pkg/npm"
|
||||||
nuget2 "github.com/harness/gitness/registry/app/api/controller/pkg/nuget"
|
nuget2 "github.com/harness/gitness/registry/app/api/controller/pkg/nuget"
|
||||||
python2 "github.com/harness/gitness/registry/app/api/controller/pkg/python"
|
python2 "github.com/harness/gitness/registry/app/api/controller/pkg/python"
|
||||||
|
rpm2 "github.com/harness/gitness/registry/app/api/controller/pkg/rpm"
|
||||||
"github.com/harness/gitness/registry/app/api/router"
|
"github.com/harness/gitness/registry/app/api/router"
|
||||||
events12 "github.com/harness/gitness/registry/app/events"
|
events12 "github.com/harness/gitness/registry/app/events"
|
||||||
"github.com/harness/gitness/registry/app/pkg"
|
"github.com/harness/gitness/registry/app/pkg"
|
||||||
@ -140,6 +141,7 @@ import (
|
|||||||
"github.com/harness/gitness/registry/app/pkg/npm"
|
"github.com/harness/gitness/registry/app/pkg/npm"
|
||||||
"github.com/harness/gitness/registry/app/pkg/nuget"
|
"github.com/harness/gitness/registry/app/pkg/nuget"
|
||||||
"github.com/harness/gitness/registry/app/pkg/python"
|
"github.com/harness/gitness/registry/app/pkg/python"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/rpm"
|
||||||
database2 "github.com/harness/gitness/registry/app/store/database"
|
database2 "github.com/harness/gitness/registry/app/store/database"
|
||||||
"github.com/harness/gitness/registry/gc"
|
"github.com/harness/gitness/registry/gc"
|
||||||
webhook3 "github.com/harness/gitness/registry/services/webhook"
|
webhook3 "github.com/harness/gitness/registry/services/webhook"
|
||||||
@ -548,7 +550,12 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
|
|||||||
npmProxy := npm.ProxyProvider(upstreamProxyConfigRepository, registryRepository, imageRepository, artifactRepository, fileManager, transactor, provider, spaceFinder, secretService, npmLocalRegistryHelper)
|
npmProxy := npm.ProxyProvider(upstreamProxyConfigRepository, registryRepository, imageRepository, artifactRepository, fileManager, transactor, provider, spaceFinder, secretService, npmLocalRegistryHelper)
|
||||||
npmController := npm2.ControllerProvider(upstreamProxyConfigRepository, registryRepository, imageRepository, artifactRepository, fileManager, transactor, downloadStatRepository, provider, npmLocalRegistry, npmProxy)
|
npmController := npm2.ControllerProvider(upstreamProxyConfigRepository, registryRepository, imageRepository, artifactRepository, fileManager, transactor, downloadStatRepository, provider, npmLocalRegistry, npmProxy)
|
||||||
npmHandler := api2.NewNPMHandlerProvider(npmController, packagesHandler)
|
npmHandler := api2.NewNPMHandlerProvider(npmController, packagesHandler)
|
||||||
handler4 := router.PackageHandlerProvider(packagesHandler, mavenHandler, genericHandler, pythonHandler, nugetHandler, npmHandler)
|
rpmLocalRegistryHelper := rpm.LocalRegistryHelperProvider(fileManager, artifactRepository)
|
||||||
|
rpmLocalRegistry := rpm.LocalRegistryProvider(localBase, fileManager, upstreamProxyConfigRepository, transactor, registryRepository, imageRepository, artifactRepository, provider, rpmLocalRegistryHelper)
|
||||||
|
rpmProxy := rpm.ProxyProvider(upstreamProxyConfigRepository, registryRepository, imageRepository, artifactRepository, fileManager, transactor, provider)
|
||||||
|
rpmController := rpm2.ControllerProvider(upstreamProxyConfigRepository, registryRepository, imageRepository, artifactRepository, fileManager, transactor, provider, rpmLocalRegistry, rpmProxy)
|
||||||
|
rpmHandler := api2.NewRpmHandlerProvider(rpmController, packagesHandler)
|
||||||
|
handler4 := router.PackageHandlerProvider(packagesHandler, mavenHandler, genericHandler, pythonHandler, nugetHandler, npmHandler, rpmHandler)
|
||||||
appRouter := router.AppRouterProvider(registryOCIHandler, apiHandler, handler2, handler3, handler4)
|
appRouter := router.AppRouterProvider(registryOCIHandler, apiHandler, handler2, handler3, handler4)
|
||||||
sender := usage.ProvideMediator(ctx, config, spaceFinder, usageMetricStore)
|
sender := usage.ProvideMediator(ctx, config, spaceFinder, usageMetricStore)
|
||||||
routerRouter := router2.ProvideRouter(ctx, config, authenticator, repoController, reposettingsController, executionController, logsController, spaceController, pipelineController, secretController, triggerController, connectorController, templateController, pluginController, pullreqController, webhookController, githookController, gitInterface, serviceaccountController, controller, principalController, usergroupController, checkController, systemController, uploadController, keywordsearchController, infraproviderController, gitspaceController, migrateController, provider, openapiService, appRouter, sender, lfsController)
|
routerRouter := router2.ProvideRouter(ctx, config, authenticator, repoController, reposettingsController, executionController, logsController, spaceController, pipelineController, secretController, triggerController, connectorController, templateController, pluginController, pullreqController, webhookController, githookController, gitInterface, serviceaccountController, controller, principalController, usergroupController, checkController, systemController, uploadController, keywordsearchController, infraproviderController, gitspaceController, migrateController, provider, openapiService, appRouter, sender, lfsController)
|
||||||
|
13
go.mod
13
go.mod
@ -62,11 +62,12 @@ require (
|
|||||||
github.com/opencontainers/go-digest v1.0.0
|
github.com/opencontainers/go-digest v1.0.0
|
||||||
github.com/opencontainers/image-spec v1.1.0
|
github.com/opencontainers/image-spec v1.1.0
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
|
github.com/posthog/posthog-go v1.3.3
|
||||||
github.com/rs/xid v1.5.0
|
github.com/rs/xid v1.5.0
|
||||||
github.com/rs/zerolog v1.33.0
|
github.com/rs/zerolog v1.33.0
|
||||||
|
github.com/sassoftware/go-rpmutils v0.4.0
|
||||||
github.com/sercand/kuberesolver/v5 v5.1.1
|
github.com/sercand/kuberesolver/v5 v5.1.1
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
github.com/slack-go/slack v0.14.0
|
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
github.com/swaggest/openapi-go v0.2.23
|
github.com/swaggest/openapi-go v0.2.23
|
||||||
github.com/swaggest/swgui v1.8.1
|
github.com/swaggest/swgui v1.8.1
|
||||||
@ -98,7 +99,9 @@ require (
|
|||||||
dario.cat/mergo v1.0.1 // indirect
|
dario.cat/mergo v1.0.1 // indirect
|
||||||
github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e // indirect
|
github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e // indirect
|
||||||
github.com/BobuSumisu/aho-corasick v1.0.3 // indirect
|
github.com/BobuSumisu/aho-corasick v1.0.3 // indirect
|
||||||
|
github.com/DataDog/zstd v1.5.5 // indirect
|
||||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||||
|
github.com/ProtonMail/go-crypto v1.0.0 // indirect
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
|
||||||
github.com/antonmedv/expr v1.15.5 // indirect
|
github.com/antonmedv/expr v1.15.5 // indirect
|
||||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
|
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
|
||||||
@ -108,6 +111,7 @@ require (
|
|||||||
github.com/buildkite/yaml v2.1.0+incompatible // indirect
|
github.com/buildkite/yaml v2.1.0+incompatible // indirect
|
||||||
github.com/charmbracelet/lipgloss v0.12.1 // indirect
|
github.com/charmbracelet/lipgloss v0.12.1 // indirect
|
||||||
github.com/charmbracelet/x/ansi v0.1.4 // indirect
|
github.com/charmbracelet/x/ansi v0.1.4 // indirect
|
||||||
|
github.com/cloudflare/circl v1.3.8 // indirect
|
||||||
github.com/docker/distribution v2.8.2+incompatible // indirect
|
github.com/docker/distribution v2.8.2+incompatible // indirect
|
||||||
github.com/drone/envsubst v1.0.3 // indirect
|
github.com/drone/envsubst v1.0.3 // indirect
|
||||||
github.com/fatih/semgroup v1.2.0 // indirect
|
github.com/fatih/semgroup v1.2.0 // indirect
|
||||||
@ -125,7 +129,6 @@ require (
|
|||||||
github.com/google/s2a-go v0.1.8 // indirect
|
github.com/google/s2a-go v0.1.8 // indirect
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||||
github.com/googleapis/gax-go/v2 v2.13.0 // indirect
|
github.com/googleapis/gax-go/v2 v2.13.0 // indirect
|
||||||
github.com/gorilla/websocket v1.4.2 // indirect
|
|
||||||
github.com/h2non/filetype v1.1.3 // indirect
|
github.com/h2non/filetype v1.1.3 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/invopop/yaml v0.2.0 // indirect
|
github.com/invopop/yaml v0.2.0 // indirect
|
||||||
@ -133,6 +136,7 @@ require (
|
|||||||
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect
|
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect
|
||||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
|
github.com/klauspost/compress v1.17.8 // indirect
|
||||||
github.com/magiconair/properties v1.8.7 // indirect
|
github.com/magiconair/properties v1.8.7 // indirect
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||||
@ -145,7 +149,6 @@ require (
|
|||||||
github.com/onsi/gomega v1.27.10 // indirect
|
github.com/onsi/gomega v1.27.10 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||||
github.com/perimeterx/marshmallow v1.1.5 // indirect
|
github.com/perimeterx/marshmallow v1.1.5 // indirect
|
||||||
github.com/posthog/posthog-go v1.3.3 // indirect
|
|
||||||
github.com/prometheus/client_golang v1.19.1 // indirect
|
github.com/prometheus/client_golang v1.19.1 // indirect
|
||||||
github.com/prometheus/client_model v0.6.1 // indirect
|
github.com/prometheus/client_model v0.6.1 // indirect
|
||||||
github.com/prometheus/common v0.55.0 // indirect
|
github.com/prometheus/common v0.55.0 // indirect
|
||||||
@ -162,6 +165,8 @@ require (
|
|||||||
github.com/stretchr/objx v0.5.2 // indirect
|
github.com/stretchr/objx v0.5.2 // indirect
|
||||||
github.com/subosito/gotenv v1.6.0 // indirect
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a // indirect
|
github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a // indirect
|
||||||
|
github.com/ulikunitz/xz v0.5.12 // indirect
|
||||||
|
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
||||||
go.opencensus.io v0.24.0 // indirect
|
go.opencensus.io v0.24.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 // indirect
|
||||||
@ -189,7 +194,7 @@ require (
|
|||||||
cloud.google.com/go/profiler v0.3.1
|
cloud.google.com/go/profiler v0.3.1
|
||||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
|
||||||
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b
|
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
|
35
go.sum
35
go.sum
@ -29,6 +29,8 @@ github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg6
|
|||||||
github.com/BobuSumisu/aho-corasick v1.0.3 h1:uuf+JHwU9CHP2Vx+wAy6jcksJThhJS9ehR8a+4nPE9g=
|
github.com/BobuSumisu/aho-corasick v1.0.3 h1:uuf+JHwU9CHP2Vx+wAy6jcksJThhJS9ehR8a+4nPE9g=
|
||||||
github.com/BobuSumisu/aho-corasick v1.0.3/go.mod h1:hm4jLcvZKI2vRF2WDU1N4p/jpWtpOzp3nLmi9AzX/XE=
|
github.com/BobuSumisu/aho-corasick v1.0.3/go.mod h1:hm4jLcvZKI2vRF2WDU1N4p/jpWtpOzp3nLmi9AzX/XE=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ=
|
||||||
|
github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
|
||||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||||
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
||||||
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
||||||
@ -40,6 +42,8 @@ github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA4
|
|||||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||||
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||||
|
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
|
||||||
|
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
||||||
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
|
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
|
||||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||||
@ -91,6 +95,7 @@ github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E=
|
|||||||
github.com/bool64/shared v0.1.5/go.mod h1:081yz68YC9jeFB3+Bbmno2RFWvGKv1lPKkMP6MHJlPs=
|
github.com/bool64/shared v0.1.5/go.mod h1:081yz68YC9jeFB3+Bbmno2RFWvGKv1lPKkMP6MHJlPs=
|
||||||
github.com/buildkite/yaml v2.1.0+incompatible h1:xirI+ql5GzfikVNDmt+yeiXpf/v1Gt03qXTtT5WXdr8=
|
github.com/buildkite/yaml v2.1.0+incompatible h1:xirI+ql5GzfikVNDmt+yeiXpf/v1Gt03qXTtT5WXdr8=
|
||||||
github.com/buildkite/yaml v2.1.0+incompatible/go.mod h1:UoU8vbcwu1+vjZq01+KrpSeLBgQQIjL/H7Y6KwikUrI=
|
github.com/buildkite/yaml v2.1.0+incompatible/go.mod h1:UoU8vbcwu1+vjZq01+KrpSeLBgQQIjL/H7Y6KwikUrI=
|
||||||
|
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||||
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
|
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
|
||||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||||
@ -106,6 +111,9 @@ github.com/charmbracelet/x/ansi v0.1.4 h1:IEU3D6+dWwPSgZ6HBH+v6oUuZ/nVawMiWj5831
|
|||||||
github.com/charmbracelet/x/ansi v0.1.4/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
|
github.com/charmbracelet/x/ansi v0.1.4/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
|
||||||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||||
|
github.com/cloudflare/circl v1.3.8 h1:j+V8jJt09PoeMFIu2uh5JUyEaIHTXVOHslFoLNAKqwI=
|
||||||
|
github.com/cloudflare/circl v1.3.8/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
||||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||||
@ -254,7 +262,6 @@ github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB
|
|||||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
|
||||||
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
|
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
|
||||||
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
@ -302,7 +309,6 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
|||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
@ -339,8 +345,6 @@ github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z
|
|||||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
|
||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
|
||||||
github.com/gotidy/ptr v1.4.0 h1:7++suUs+HNHMnyz6/AW3SE+4EnBhupPSQTSI7QNijVc=
|
github.com/gotidy/ptr v1.4.0 h1:7++suUs+HNHMnyz6/AW3SE+4EnBhupPSQTSI7QNijVc=
|
||||||
github.com/gotidy/ptr v1.4.0/go.mod h1:MjRBG6/IETiiZGWI8LrRtISXEji+8b/jigmj2q0mEyM=
|
github.com/gotidy/ptr v1.4.0/go.mod h1:MjRBG6/IETiiZGWI8LrRtISXEji+8b/jigmj2q0mEyM=
|
||||||
github.com/gregjones/httpcache v0.0.0-20181110185634-c63ab54fda8f/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
github.com/gregjones/httpcache v0.0.0-20181110185634-c63ab54fda8f/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||||
@ -483,6 +487,8 @@ github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa
|
|||||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
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/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
|
||||||
|
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
@ -688,6 +694,8 @@ github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE
|
|||||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||||
|
github.com/sassoftware/go-rpmutils v0.4.0 h1:ojND82NYBxgwrV+mX1CWsd5QJvvEZTKddtCdFLPWhpg=
|
||||||
|
github.com/sassoftware/go-rpmutils v0.4.0/go.mod h1:3goNWi7PGAT3/dlql2lv3+MSN5jNYPjT5mVcQcIsYzI=
|
||||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||||
github.com/sercand/kuberesolver/v5 v5.1.1 h1:CYH+d67G0sGBj7q5wLK61yzqJJ8gLLC8aeprPTHb6yY=
|
github.com/sercand/kuberesolver/v5 v5.1.1 h1:CYH+d67G0sGBj7q5wLK61yzqJJ8gLLC8aeprPTHb6yY=
|
||||||
@ -703,8 +711,6 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
|
|||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/slack-go/slack v0.14.0 h1:6c0UTfbRnvRssZUsZ2qe0Iu07VAMPjRqOa6oX8ewF4k=
|
|
||||||
github.com/slack-go/slack v0.14.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw=
|
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||||
@ -743,7 +749,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
@ -772,6 +777,8 @@ github.com/tidwall/jsonc v0.3.2/go.mod h1:dw+3CIxqHi+t8eFSpzzMlcVYxKp08UP5CD8/uS
|
|||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
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/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||||
|
github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
|
||||||
|
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||||
github.com/unrolled/secure v1.15.0 h1:q7x+pdp8jAHnbzxu6UheP8fRlG/rwYTb8TPuQ3rn9Og=
|
github.com/unrolled/secure v1.15.0 h1:q7x+pdp8jAHnbzxu6UheP8fRlG/rwYTb8TPuQ3rn9Og=
|
||||||
github.com/unrolled/secure v1.15.0/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40=
|
github.com/unrolled/secure v1.15.0/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40=
|
||||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
@ -779,6 +786,8 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX
|
|||||||
github.com/vearutop/statigz v1.4.0 h1:RQL0KG3j/uyA/PFpHeZ/L6l2ta920/MxlOAIGEOuwmU=
|
github.com/vearutop/statigz v1.4.0 h1:RQL0KG3j/uyA/PFpHeZ/L6l2ta920/MxlOAIGEOuwmU=
|
||||||
github.com/vearutop/statigz v1.4.0/go.mod h1:LYTolBLiz9oJISwiVKnOQoIwhO1LWX1A7OECawGS8XE=
|
github.com/vearutop/statigz v1.4.0/go.mod h1:LYTolBLiz9oJISwiVKnOQoIwhO1LWX1A7OECawGS8XE=
|
||||||
github.com/vinzenz/yaml v0.0.0-20170920082545-91409cdd725d/go.mod h1:mb5taDqMnJiZNRQ3+02W2IFG+oEz1+dTuCXkp4jpkfo=
|
github.com/vinzenz/yaml v0.0.0-20170920082545-91409cdd725d/go.mod h1:mb5taDqMnJiZNRQ3+02W2IFG+oEz1+dTuCXkp4jpkfo=
|
||||||
|
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/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA=
|
github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA=
|
||||||
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
|
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
|
||||||
@ -824,6 +833,8 @@ go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
|||||||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||||
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||||
@ -849,6 +860,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
|||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||||
|
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||||
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
||||||
@ -894,7 +907,9 @@ 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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
|
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||||
@ -947,6 +962,8 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/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-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.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
@ -956,7 +973,9 @@ golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
|||||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
|
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||||
@ -967,7 +986,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
|||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
|
@ -100,10 +100,10 @@ func (c *APIController) GetAllArtifactsByRegistry(
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
artifacts, err = c.ArtifactStore.GetAllArtifactsByRepo(
|
artifacts, err = c.ArtifactStore.GetArtifactsByRepo(
|
||||||
ctx, regInfo.parentID, regInfo.RegistryIdentifier,
|
ctx, regInfo.parentID, regInfo.RegistryIdentifier,
|
||||||
regInfo.sortByField, regInfo.sortByOrder, regInfo.limit, regInfo.offset, regInfo.searchTerm, regInfo.labels)
|
regInfo.sortByField, regInfo.sortByOrder, regInfo.limit, regInfo.offset, regInfo.searchTerm, regInfo.labels)
|
||||||
count, _ = c.ArtifactStore.CountAllArtifactsByRepo(
|
count, _ = c.ArtifactStore.CountArtifactsByRepo(
|
||||||
ctx, regInfo.parentID, regInfo.RegistryIdentifier,
|
ctx, regInfo.parentID, regInfo.RegistryIdentifier,
|
||||||
regInfo.searchTerm, regInfo.labels)
|
regInfo.searchTerm, regInfo.labels)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
84
registry/app/api/controller/pkg/rpm/controller.go
Normal file
84
registry/app/api/controller/pkg/rpm/controller.go
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rpm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"mime/multipart"
|
||||||
|
|
||||||
|
urlprovider "github.com/harness/gitness/app/url"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/filemanager"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/rpm"
|
||||||
|
rpmtype "github.com/harness/gitness/registry/app/pkg/types/rpm"
|
||||||
|
"github.com/harness/gitness/registry/app/store"
|
||||||
|
"github.com/harness/gitness/store/database/dbtx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Controller interface {
|
||||||
|
UploadPackageFile(
|
||||||
|
ctx context.Context,
|
||||||
|
info rpmtype.ArtifactInfo,
|
||||||
|
file multipart.File,
|
||||||
|
) *PutArtifactResponse
|
||||||
|
|
||||||
|
DownloadPackageFile(
|
||||||
|
ctx context.Context,
|
||||||
|
info rpmtype.ArtifactInfo,
|
||||||
|
) *GetArtifactResponse
|
||||||
|
|
||||||
|
GetRepoData(
|
||||||
|
ctx context.Context,
|
||||||
|
info rpmtype.ArtifactInfo,
|
||||||
|
fileName string,
|
||||||
|
) *GetRepoDataResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
// Controller handles RPM package operations.
|
||||||
|
type controller struct {
|
||||||
|
fileManager filemanager.FileManager
|
||||||
|
proxyStore store.UpstreamProxyConfigRepository
|
||||||
|
tx dbtx.Transactor
|
||||||
|
registryDao store.RegistryRepository
|
||||||
|
imageDao store.ImageRepository
|
||||||
|
artifactDao store.ArtifactRepository
|
||||||
|
urlProvider urlprovider.Provider
|
||||||
|
local rpm.LocalRegistry
|
||||||
|
proxy rpm.Proxy
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewController creates a new RPM controller.
|
||||||
|
func NewController(
|
||||||
|
proxyStore store.UpstreamProxyConfigRepository,
|
||||||
|
registryDao store.RegistryRepository,
|
||||||
|
imageDao store.ImageRepository,
|
||||||
|
artifactDao store.ArtifactRepository,
|
||||||
|
fileManager filemanager.FileManager,
|
||||||
|
tx dbtx.Transactor,
|
||||||
|
urlProvider urlprovider.Provider,
|
||||||
|
local rpm.LocalRegistry,
|
||||||
|
proxy rpm.Proxy,
|
||||||
|
) Controller {
|
||||||
|
return &controller{
|
||||||
|
proxyStore: proxyStore,
|
||||||
|
registryDao: registryDao,
|
||||||
|
imageDao: imageDao,
|
||||||
|
artifactDao: artifactDao,
|
||||||
|
fileManager: fileManager,
|
||||||
|
tx: tx,
|
||||||
|
urlProvider: urlProvider,
|
||||||
|
local: local,
|
||||||
|
proxy: proxy,
|
||||||
|
}
|
||||||
|
}
|
78
registry/app/api/controller/pkg/rpm/download.go
Normal file
78
registry/app/api/controller/pkg/rpm/download.go
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rpm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/registry/app/pkg"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/base"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/response"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/rpm"
|
||||||
|
rpmtype "github.com/harness/gitness/registry/app/pkg/types/rpm"
|
||||||
|
registrytypes "github.com/harness/gitness/registry/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *controller) DownloadPackageFile(
|
||||||
|
ctx context.Context,
|
||||||
|
info rpmtype.ArtifactInfo,
|
||||||
|
) *GetArtifactResponse {
|
||||||
|
f := func(registry registrytypes.Registry, a pkg.Artifact) response.Response {
|
||||||
|
info.RegIdentifier = registry.Name
|
||||||
|
info.RegistryID = registry.ID
|
||||||
|
info.Registry = registry
|
||||||
|
rpmRegistry, ok := a.(rpm.Registry)
|
||||||
|
if !ok {
|
||||||
|
return &GetArtifactResponse{
|
||||||
|
BaseResponse{
|
||||||
|
fmt.Errorf("invalid registry type: expected rpm.Registry"),
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
"", nil, nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
headers, fileReader, readCloser, redirectURL, err := rpmRegistry.DownloadPackageFile(ctx, info)
|
||||||
|
return &GetArtifactResponse{
|
||||||
|
BaseResponse{
|
||||||
|
err,
|
||||||
|
headers,
|
||||||
|
},
|
||||||
|
redirectURL, fileReader, readCloser,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := base.ProxyWrapper(ctx, c.registryDao, f, info)
|
||||||
|
if err != nil {
|
||||||
|
return &GetArtifactResponse{
|
||||||
|
BaseResponse{
|
||||||
|
err,
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
"", nil, nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getResponse, ok := result.(*GetArtifactResponse)
|
||||||
|
if !ok {
|
||||||
|
return &GetArtifactResponse{
|
||||||
|
BaseResponse{
|
||||||
|
fmt.Errorf("invalid response type: expected GetArtifactResponse"),
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
"", nil, nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getResponse
|
||||||
|
}
|
69
registry/app/api/controller/pkg/rpm/metadata.go
Normal file
69
registry/app/api/controller/pkg/rpm/metadata.go
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rpm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/registry/app/pkg"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/base"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/response"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/rpm"
|
||||||
|
rpmtype "github.com/harness/gitness/registry/app/pkg/types/rpm"
|
||||||
|
registrytypes "github.com/harness/gitness/registry/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetRepoData represents the metadata of a RPM package.
|
||||||
|
func (c *controller) GetRepoData(ctx context.Context, info rpmtype.ArtifactInfo, fileName string) *GetRepoDataResponse {
|
||||||
|
f := func(registry registrytypes.Registry, a pkg.Artifact) response.Response {
|
||||||
|
info.RegIdentifier = registry.Name
|
||||||
|
info.RegistryID = registry.ID
|
||||||
|
info.Registry = registry
|
||||||
|
rpmRegistry, ok := a.(rpm.Registry)
|
||||||
|
if !ok {
|
||||||
|
return &GetRepoDataResponse{
|
||||||
|
BaseResponse{
|
||||||
|
fmt.Errorf("invalid registry type: expected rpm.Registry"),
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
"", nil, nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
responseHeaders, fileReader, _, redirectURL, err := rpmRegistry.GetRepoData(ctx, info, fileName)
|
||||||
|
|
||||||
|
return &GetRepoDataResponse{
|
||||||
|
BaseResponse{
|
||||||
|
err,
|
||||||
|
responseHeaders,
|
||||||
|
},
|
||||||
|
redirectURL, fileReader, fileReader,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := base.ProxyWrapper(ctx, c.registryDao, f, info)
|
||||||
|
metadataResponse, ok := result.(*GetRepoDataResponse)
|
||||||
|
if !ok {
|
||||||
|
return &GetRepoDataResponse{
|
||||||
|
BaseResponse{
|
||||||
|
err,
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
"", nil, nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return metadataResponse
|
||||||
|
}
|
55
registry/app/api/controller/pkg/rpm/response.go
Normal file
55
registry/app/api/controller/pkg/rpm/response.go
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rpm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/commons"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/response"
|
||||||
|
"github.com/harness/gitness/registry/app/storage"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ response.Response = (*GetRepoDataResponse)(nil)
|
||||||
|
var _ response.Response = (*GetArtifactResponse)(nil)
|
||||||
|
var _ response.Response = (*PutArtifactResponse)(nil)
|
||||||
|
|
||||||
|
type BaseResponse struct {
|
||||||
|
Error error
|
||||||
|
ResponseHeaders *commons.ResponseHeaders
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r BaseResponse) GetError() error {
|
||||||
|
return r.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetRepoDataResponse struct {
|
||||||
|
BaseResponse
|
||||||
|
RedirectURL string
|
||||||
|
Body *storage.FileReader
|
||||||
|
ReadCloser io.ReadCloser
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetArtifactResponse struct {
|
||||||
|
BaseResponse
|
||||||
|
RedirectURL string
|
||||||
|
Body *storage.FileReader
|
||||||
|
ReadCloser io.ReadCloser
|
||||||
|
}
|
||||||
|
|
||||||
|
type PutArtifactResponse struct {
|
||||||
|
BaseResponse
|
||||||
|
Sha256 string
|
||||||
|
}
|
71
registry/app/api/controller/pkg/rpm/upload_package.go
Normal file
71
registry/app/api/controller/pkg/rpm/upload_package.go
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rpm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"mime/multipart"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/registry/app/pkg"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/base"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/response"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/rpm"
|
||||||
|
rpmtype "github.com/harness/gitness/registry/app/pkg/types/rpm"
|
||||||
|
registrytypes "github.com/harness/gitness/registry/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UploadPackageFile uploads the package file to the storage.
|
||||||
|
func (c *controller) UploadPackageFile(
|
||||||
|
ctx context.Context,
|
||||||
|
info rpmtype.ArtifactInfo,
|
||||||
|
file multipart.File,
|
||||||
|
) *PutArtifactResponse {
|
||||||
|
f := func(registry registrytypes.Registry, a pkg.Artifact) response.Response {
|
||||||
|
info.RegIdentifier = registry.Name
|
||||||
|
info.RegistryID = registry.ID
|
||||||
|
rpmRegistry, ok := a.(rpm.Registry)
|
||||||
|
if !ok {
|
||||||
|
return &PutArtifactResponse{
|
||||||
|
BaseResponse{
|
||||||
|
Error: fmt.Errorf("invalid registry type: expected rpm.Registry"),
|
||||||
|
ResponseHeaders: nil,
|
||||||
|
},
|
||||||
|
"",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
headers, sha256, err := rpmRegistry.UploadPackageFile(ctx, info, file)
|
||||||
|
return &PutArtifactResponse{
|
||||||
|
BaseResponse{
|
||||||
|
Error: err,
|
||||||
|
ResponseHeaders: headers,
|
||||||
|
},
|
||||||
|
sha256,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := base.NoProxyWrapper(ctx, c.registryDao, f, info)
|
||||||
|
rs, ok := result.(*PutArtifactResponse)
|
||||||
|
if !ok {
|
||||||
|
return &PutArtifactResponse{
|
||||||
|
BaseResponse{
|
||||||
|
Error: err,
|
||||||
|
ResponseHeaders: nil,
|
||||||
|
},
|
||||||
|
"",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rs
|
||||||
|
}
|
41
registry/app/api/controller/pkg/rpm/wire.go
Normal file
41
registry/app/api/controller/pkg/rpm/wire.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rpm
|
||||||
|
|
||||||
|
import (
|
||||||
|
urlprovider "github.com/harness/gitness/app/url"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/filemanager"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/rpm"
|
||||||
|
"github.com/harness/gitness/registry/app/store"
|
||||||
|
"github.com/harness/gitness/store/database/dbtx"
|
||||||
|
|
||||||
|
"github.com/google/wire"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ControllerProvider(
|
||||||
|
proxyStore store.UpstreamProxyConfigRepository,
|
||||||
|
registryDao store.RegistryRepository,
|
||||||
|
imageDao store.ImageRepository,
|
||||||
|
artifactDao store.ArtifactRepository,
|
||||||
|
fileManager filemanager.FileManager,
|
||||||
|
tx dbtx.Transactor,
|
||||||
|
urlProvider urlprovider.Provider,
|
||||||
|
local rpm.LocalRegistry,
|
||||||
|
proxy rpm.Proxy,
|
||||||
|
) Controller {
|
||||||
|
return NewController(proxyStore, registryDao, imageDao, artifactDao, fileManager, tx, urlProvider, local, proxy)
|
||||||
|
}
|
||||||
|
|
||||||
|
var ControllerSet = wire.NewSet(ControllerProvider)
|
@ -101,6 +101,7 @@ const (
|
|||||||
PathPackageTypePython PathPackageType = "python"
|
PathPackageTypePython PathPackageType = "python"
|
||||||
PathPackageTypeNuget PathPackageType = "nuget"
|
PathPackageTypeNuget PathPackageType = "nuget"
|
||||||
PathPackageTypeNpm PathPackageType = "npm"
|
PathPackageTypeNpm PathPackageType = "npm"
|
||||||
|
PathPackageTypeRPM PathPackageType = "rpm"
|
||||||
)
|
)
|
||||||
|
|
||||||
var packageTypeMap = map[PathPackageType]artifact2.PackageType{
|
var packageTypeMap = map[PathPackageType]artifact2.PackageType{
|
||||||
@ -109,6 +110,7 @@ var packageTypeMap = map[PathPackageType]artifact2.PackageType{
|
|||||||
PathPackageTypePython: artifact2.PackageTypePYTHON,
|
PathPackageTypePython: artifact2.PackageTypePYTHON,
|
||||||
PathPackageTypeNuget: artifact2.PackageTypeNUGET,
|
PathPackageTypeNuget: artifact2.PackageTypeNUGET,
|
||||||
PathPackageTypeNpm: artifact2.PackageTypeNPM,
|
PathPackageTypeNpm: artifact2.PackageTypeNPM,
|
||||||
|
PathPackageTypeRPM: artifact2.PackageTypeRPM,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) GetAuthenticator() authn.Authenticator {
|
func (h *handler) GetAuthenticator() authn.Authenticator {
|
||||||
|
78
registry/app/api/handler/rpm/download.go
Normal file
78
registry/app/api/handler/rpm/download.go
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rpm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/commons"
|
||||||
|
rpmtype "github.com/harness/gitness/registry/app/pkg/types/rpm"
|
||||||
|
"github.com/harness/gitness/registry/request"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (h *handler) DownloadPackageFile(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
info, ok := request.ArtifactInfoFrom(ctx).(*rpmtype.ArtifactInfo)
|
||||||
|
if !ok {
|
||||||
|
h.HandleErrors(ctx, []error{fmt.Errorf("failed to fetch info from context")}, w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
info.Version = r.PathValue("version")
|
||||||
|
info.Image = r.PathValue("name")
|
||||||
|
info.Arch = r.PathValue("architecture")
|
||||||
|
info.FileName = r.PathValue("file")
|
||||||
|
response := h.controller.DownloadPackageFile(ctx, *info)
|
||||||
|
if response == nil {
|
||||||
|
h.HandleErrors(ctx, []error{fmt.Errorf("failed to get response from controller")}, w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if response.Body != nil {
|
||||||
|
err := response.Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("Failed to close body: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.ReadCloser != nil {
|
||||||
|
err := response.ReadCloser.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("Failed to close read closer: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if response.GetError() != nil {
|
||||||
|
h.HandleError(ctx, w, response.GetError())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.RedirectURL != "" {
|
||||||
|
http.Redirect(w, r, response.RedirectURL, http.StatusTemporaryRedirect)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := commons.ServeContent(w, r, response.Body, info.FileName, response.ReadCloser)
|
||||||
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("Failed to serve content: %v", err)
|
||||||
|
h.HandleError(ctx, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
response.ResponseHeaders.WriteToResponse(w)
|
||||||
|
}
|
59
registry/app/api/handler/rpm/handler.go
Normal file
59
registry/app/api/handler/rpm/handler.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rpm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
rpm "github.com/harness/gitness/registry/app/api/controller/pkg/rpm"
|
||||||
|
"github.com/harness/gitness/registry/app/api/handler/packages"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg"
|
||||||
|
rpmtype "github.com/harness/gitness/registry/app/pkg/types/rpm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Handler interface {
|
||||||
|
pkg.ArtifactInfoProvider
|
||||||
|
UploadPackageFile(writer http.ResponseWriter, request *http.Request)
|
||||||
|
GetRepoData(writer http.ResponseWriter, request *http.Request)
|
||||||
|
DownloadPackageFile(http.ResponseWriter, *http.Request)
|
||||||
|
}
|
||||||
|
|
||||||
|
type handler struct {
|
||||||
|
packages.Handler
|
||||||
|
controller rpm.Controller
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHandler(
|
||||||
|
controller rpm.Controller,
|
||||||
|
packageHandler packages.Handler,
|
||||||
|
) Handler {
|
||||||
|
return &handler{
|
||||||
|
Handler: packageHandler,
|
||||||
|
controller: controller,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ Handler = (*handler)(nil)
|
||||||
|
|
||||||
|
func (h *handler) GetPackageArtifactInfo(r *http.Request) (pkg.PackageArtifactInfo, error) {
|
||||||
|
info, err := h.Handler.GetArtifactInfo(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &rpmtype.ArtifactInfo{
|
||||||
|
ArtifactInfo: info,
|
||||||
|
}, nil
|
||||||
|
}
|
78
registry/app/api/handler/rpm/repodata.go
Normal file
78
registry/app/api/handler/rpm/repodata.go
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rpm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/app/api/render"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/commons"
|
||||||
|
rpmtype "github.com/harness/gitness/registry/app/pkg/types/rpm"
|
||||||
|
"github.com/harness/gitness/registry/request"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (h *handler) GetRepoData(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
contextInfo := request.ArtifactInfoFrom(ctx)
|
||||||
|
info, ok := contextInfo.(*rpmtype.ArtifactInfo)
|
||||||
|
if !ok {
|
||||||
|
render.TranslatedUserError(r.Context(), w, fmt.Errorf("invalid request context"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fileName := r.PathValue("file")
|
||||||
|
|
||||||
|
packageData := h.controller.GetRepoData(r.Context(), *info, fileName)
|
||||||
|
if packageData == nil {
|
||||||
|
h.HandleErrors(ctx, []error{fmt.Errorf("failed to get response from controller")}, w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if packageData.Body != nil {
|
||||||
|
err := packageData.Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("Failed to close body: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if packageData.ReadCloser != nil {
|
||||||
|
err := packageData.ReadCloser.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("Failed to close read closer: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if packageData.GetError() != nil {
|
||||||
|
h.HandleError(ctx, w, packageData.GetError())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if packageData.RedirectURL != "" {
|
||||||
|
http.Redirect(w, r, packageData.RedirectURL, http.StatusTemporaryRedirect)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := commons.ServeContent(w, r, packageData.Body, info.FileName, packageData.ReadCloser)
|
||||||
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("Failed to serve content: %v", err)
|
||||||
|
h.HandleError(ctx, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
packageData.ResponseHeaders.WriteToResponse(w)
|
||||||
|
}
|
56
registry/app/api/handler/rpm/upload.go
Normal file
56
registry/app/api/handler/rpm/upload.go
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rpm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/registry/app/dist_temp/errcode"
|
||||||
|
rpmtype "github.com/harness/gitness/registry/app/pkg/types/rpm"
|
||||||
|
"github.com/harness/gitness/registry/request"
|
||||||
|
)
|
||||||
|
|
||||||
|
const formFileKey = "file"
|
||||||
|
|
||||||
|
func (h *handler) UploadPackageFile(w http.ResponseWriter, r *http.Request) {
|
||||||
|
file, _, err := r.FormFile(formFileKey)
|
||||||
|
if err != nil {
|
||||||
|
h.HandleErrors2(r.Context(), errcode.ErrCodeInvalidRequest.WithMessage(fmt.Sprintf("failed to parse file: %s, "+
|
||||||
|
"please provide correct file path ", err.Error())), w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
contextInfo := request.ArtifactInfoFrom(r.Context())
|
||||||
|
info, ok := contextInfo.(*rpmtype.ArtifactInfo)
|
||||||
|
if !ok {
|
||||||
|
h.HandleErrors2(r.Context(), errcode.ErrCodeInvalidRequest.WithMessage("failed to fetch info from context"), w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response := h.controller.UploadPackageFile(r.Context(), *info, file)
|
||||||
|
if response.GetError() != nil {
|
||||||
|
h.HandleError(r.Context(), w, response.GetError())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.ResponseHeaders.WriteToResponse(w)
|
||||||
|
_, err = w.Write([]byte(fmt.Sprintf("Pushed.\nSha256: %s", response.Sha256)))
|
||||||
|
if err != nil {
|
||||||
|
h.HandleError(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
@ -22,7 +22,6 @@ import (
|
|||||||
"github.com/harness/gitness/types/enum"
|
"github.com/harness/gitness/types/enum"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StoreOriginalURL stores the original URL in the context.
|
|
||||||
func RequestPackageAccess(
|
func RequestPackageAccess(
|
||||||
packageHandler packages.Handler,
|
packageHandler packages.Handler,
|
||||||
reqPermissions ...enum.Permission,
|
reqPermissions ...enum.Permission,
|
||||||
|
@ -2707,6 +2707,7 @@ components:
|
|||||||
- HELM
|
- HELM
|
||||||
- NUGET
|
- NUGET
|
||||||
- NPM
|
- NPM
|
||||||
|
- RPM
|
||||||
SectionType:
|
SectionType:
|
||||||
type: string
|
type: string
|
||||||
description: refers to client setup section type
|
description: refers to client setup section type
|
||||||
|
@ -33,6 +33,7 @@ const (
|
|||||||
PackageTypeNPM PackageType = "NPM"
|
PackageTypeNPM PackageType = "NPM"
|
||||||
PackageTypeNUGET PackageType = "NUGET"
|
PackageTypeNUGET PackageType = "NUGET"
|
||||||
PackageTypePYTHON PackageType = "PYTHON"
|
PackageTypePYTHON PackageType = "PYTHON"
|
||||||
|
PackageTypeRPM PackageType = "RPM"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Defines values for RegistryType.
|
// Defines values for RegistryType.
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/harness/gitness/registry/app/api/handler/nuget"
|
"github.com/harness/gitness/registry/app/api/handler/nuget"
|
||||||
"github.com/harness/gitness/registry/app/api/handler/packages"
|
"github.com/harness/gitness/registry/app/api/handler/packages"
|
||||||
"github.com/harness/gitness/registry/app/api/handler/python"
|
"github.com/harness/gitness/registry/app/api/handler/python"
|
||||||
|
"github.com/harness/gitness/registry/app/api/handler/rpm"
|
||||||
"github.com/harness/gitness/registry/app/api/middleware"
|
"github.com/harness/gitness/registry/app/api/middleware"
|
||||||
"github.com/harness/gitness/types/enum"
|
"github.com/harness/gitness/types/enum"
|
||||||
|
|
||||||
@ -48,6 +49,7 @@ func NewRouter(
|
|||||||
pythonHandler python.Handler,
|
pythonHandler python.Handler,
|
||||||
nugetHandler nuget.Handler,
|
nugetHandler nuget.Handler,
|
||||||
npmHandler npm.Handler,
|
npmHandler npm.Handler,
|
||||||
|
rpmHandler rpm.Handler,
|
||||||
) Handler {
|
) Handler {
|
||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
|
|
||||||
@ -190,6 +192,19 @@ func NewRouter(
|
|||||||
registerRevisionRoutes(r, npmHandler, packageHandler)
|
registerRevisionRoutes(r, npmHandler, packageHandler)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
r.Route("/rpm", func(r chi.Router) {
|
||||||
|
r.Use(middlewareauthn.Attempt(packageHandler.GetAuthenticator()))
|
||||||
|
r.Use(middleware.CheckAuth())
|
||||||
|
r.With(middleware.StoreArtifactInfo(rpmHandler)).
|
||||||
|
With(middleware.RequestPackageAccess(packageHandler, enum.PermissionArtifactsUpload)).
|
||||||
|
Put("/*", rpmHandler.UploadPackageFile)
|
||||||
|
r.With(middleware.StoreArtifactInfo(rpmHandler)).
|
||||||
|
With(middleware.RequestPackageAccess(packageHandler, enum.PermissionArtifactsDownload)).
|
||||||
|
Get("/repodata/{file}", rpmHandler.GetRepoData)
|
||||||
|
r.With(middleware.StoreArtifactInfo(rpmHandler)).
|
||||||
|
With(middleware.RequestPackageAccess(packageHandler, enum.PermissionArtifactsDownload)).
|
||||||
|
Get("/package/{name}/{version}/{architecture}/{file}", rpmHandler.DownloadPackageFile)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
return r
|
return r
|
||||||
|
@ -29,6 +29,7 @@ import (
|
|||||||
hoci "github.com/harness/gitness/registry/app/api/handler/oci"
|
hoci "github.com/harness/gitness/registry/app/api/handler/oci"
|
||||||
"github.com/harness/gitness/registry/app/api/handler/packages"
|
"github.com/harness/gitness/registry/app/api/handler/packages"
|
||||||
"github.com/harness/gitness/registry/app/api/handler/python"
|
"github.com/harness/gitness/registry/app/api/handler/python"
|
||||||
|
rpm "github.com/harness/gitness/registry/app/api/handler/rpm"
|
||||||
generic2 "github.com/harness/gitness/registry/app/api/router/generic"
|
generic2 "github.com/harness/gitness/registry/app/api/router/generic"
|
||||||
"github.com/harness/gitness/registry/app/api/router/harness"
|
"github.com/harness/gitness/registry/app/api/router/harness"
|
||||||
mavenRouter "github.com/harness/gitness/registry/app/api/router/maven"
|
mavenRouter "github.com/harness/gitness/registry/app/api/router/maven"
|
||||||
@ -122,8 +123,17 @@ func PackageHandlerProvider(
|
|||||||
pypiHandler python.Handler,
|
pypiHandler python.Handler,
|
||||||
nugetHandler nuget.Handler,
|
nugetHandler nuget.Handler,
|
||||||
npmHandler npm.Handler,
|
npmHandler npm.Handler,
|
||||||
|
rpmHandler rpm.Handler,
|
||||||
) packagerrouter.Handler {
|
) packagerrouter.Handler {
|
||||||
return packagerrouter.NewRouter(handler, mavenHandler, genericHandler, pypiHandler, nugetHandler, npmHandler)
|
return packagerrouter.NewRouter(
|
||||||
|
handler,
|
||||||
|
mavenHandler,
|
||||||
|
genericHandler,
|
||||||
|
pypiHandler,
|
||||||
|
nugetHandler,
|
||||||
|
npmHandler,
|
||||||
|
rpmHandler,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
var WireSet = wire.NewSet(APIHandlerProvider, OCIHandlerProvider, AppRouterProvider,
|
var WireSet = wire.NewSet(APIHandlerProvider, OCIHandlerProvider, AppRouterProvider,
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
"github.com/harness/gitness/registry/app/api/controller/pkg/npm"
|
"github.com/harness/gitness/registry/app/api/controller/pkg/npm"
|
||||||
nuget2 "github.com/harness/gitness/registry/app/api/controller/pkg/nuget"
|
nuget2 "github.com/harness/gitness/registry/app/api/controller/pkg/nuget"
|
||||||
python2 "github.com/harness/gitness/registry/app/api/controller/pkg/python"
|
python2 "github.com/harness/gitness/registry/app/api/controller/pkg/python"
|
||||||
|
rpm2 "github.com/harness/gitness/registry/app/api/controller/pkg/rpm"
|
||||||
"github.com/harness/gitness/registry/app/api/handler/generic"
|
"github.com/harness/gitness/registry/app/api/handler/generic"
|
||||||
mavenhandler "github.com/harness/gitness/registry/app/api/handler/maven"
|
mavenhandler "github.com/harness/gitness/registry/app/api/handler/maven"
|
||||||
npm2 "github.com/harness/gitness/registry/app/api/handler/npm"
|
npm2 "github.com/harness/gitness/registry/app/api/handler/npm"
|
||||||
@ -31,6 +32,7 @@ import (
|
|||||||
ocihandler "github.com/harness/gitness/registry/app/api/handler/oci"
|
ocihandler "github.com/harness/gitness/registry/app/api/handler/oci"
|
||||||
"github.com/harness/gitness/registry/app/api/handler/packages"
|
"github.com/harness/gitness/registry/app/api/handler/packages"
|
||||||
pypi2 "github.com/harness/gitness/registry/app/api/handler/python"
|
pypi2 "github.com/harness/gitness/registry/app/api/handler/python"
|
||||||
|
rpm "github.com/harness/gitness/registry/app/api/handler/rpm"
|
||||||
"github.com/harness/gitness/registry/app/api/router"
|
"github.com/harness/gitness/registry/app/api/router"
|
||||||
storagedriver "github.com/harness/gitness/registry/app/driver"
|
storagedriver "github.com/harness/gitness/registry/app/driver"
|
||||||
"github.com/harness/gitness/registry/app/driver/factory"
|
"github.com/harness/gitness/registry/app/driver/factory"
|
||||||
@ -45,6 +47,7 @@ import (
|
|||||||
npm22 "github.com/harness/gitness/registry/app/pkg/npm"
|
npm22 "github.com/harness/gitness/registry/app/pkg/npm"
|
||||||
"github.com/harness/gitness/registry/app/pkg/nuget"
|
"github.com/harness/gitness/registry/app/pkg/nuget"
|
||||||
"github.com/harness/gitness/registry/app/pkg/python"
|
"github.com/harness/gitness/registry/app/pkg/python"
|
||||||
|
rpmregistry "github.com/harness/gitness/registry/app/pkg/rpm"
|
||||||
"github.com/harness/gitness/registry/app/store"
|
"github.com/harness/gitness/registry/app/store"
|
||||||
"github.com/harness/gitness/registry/app/store/database"
|
"github.com/harness/gitness/registry/app/store/database"
|
||||||
"github.com/harness/gitness/registry/config"
|
"github.com/harness/gitness/registry/config"
|
||||||
@ -155,6 +158,13 @@ func NewNPMHandlerProvider(
|
|||||||
return npm2.NewHandler(controller, packageHandler)
|
return npm2.NewHandler(controller, packageHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewRpmHandlerProvider(
|
||||||
|
controller rpm2.Controller,
|
||||||
|
packageHandler packages.Handler,
|
||||||
|
) rpm.Handler {
|
||||||
|
return rpm.NewHandler(controller, packageHandler)
|
||||||
|
}
|
||||||
|
|
||||||
func NewGenericHandlerProvider(
|
func NewGenericHandlerProvider(
|
||||||
spaceStore corestore.SpaceStore, controller *generic2.Controller, tokenStore corestore.TokenStore,
|
spaceStore corestore.SpaceStore, controller *generic2.Controller, tokenStore corestore.TokenStore,
|
||||||
userCtrl *usercontroller.Controller, authenticator authn.Authenticator, urlProvider urlprovider.Provider,
|
userCtrl *usercontroller.Controller, authenticator authn.Authenticator, urlProvider urlprovider.Provider,
|
||||||
@ -180,6 +190,7 @@ var WireSet = wire.NewSet(
|
|||||||
NewPythonHandlerProvider,
|
NewPythonHandlerProvider,
|
||||||
NewNugetHandlerProvider,
|
NewNugetHandlerProvider,
|
||||||
NewNPMHandlerProvider,
|
NewNPMHandlerProvider,
|
||||||
|
NewRpmHandlerProvider,
|
||||||
database.WireSet,
|
database.WireSet,
|
||||||
pkg.WireSet,
|
pkg.WireSet,
|
||||||
docker.WireSet,
|
docker.WireSet,
|
||||||
@ -195,6 +206,8 @@ var WireSet = wire.NewSet(
|
|||||||
nuget2.ControllerSet,
|
nuget2.ControllerSet,
|
||||||
npm.ControllerSet,
|
npm.ControllerSet,
|
||||||
base.WireSet,
|
base.WireSet,
|
||||||
|
rpm2.ControllerSet,
|
||||||
|
rpmregistry.WireSet,
|
||||||
)
|
)
|
||||||
|
|
||||||
func Wire(_ *types.Config) (RegistryApp, error) {
|
func Wire(_ *types.Config) (RegistryApp, error) {
|
||||||
|
@ -18,4 +18,5 @@ type File struct {
|
|||||||
Size int64 `json:"size"`
|
Size int64 `json:"size"`
|
||||||
Filename string `json:"file_name"`
|
Filename string `json:"file_name"`
|
||||||
CreatedAt int64 `json:"created_at"`
|
CreatedAt int64 `json:"created_at"`
|
||||||
|
Sha256 string `json:"sha256"`
|
||||||
}
|
}
|
||||||
|
103
registry/app/metadata/rpm/metadata.go
Normal file
103
registry/app/metadata/rpm/metadata.go
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rpm
|
||||||
|
|
||||||
|
import "github.com/harness/gitness/registry/app/metadata"
|
||||||
|
|
||||||
|
var _ metadata.Metadata = (*RpmMetadata)(nil)
|
||||||
|
|
||||||
|
type Metadata struct {
|
||||||
|
VersionMetadata VersionMetadata `json:"version_metadata,omitempty"`
|
||||||
|
FileMetadata FileMetadata `json:"file_metadata,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type VersionMetadata struct {
|
||||||
|
License string `json:"license,omitempty"`
|
||||||
|
ProjectURL string `json:"project_url,omitempty"`
|
||||||
|
Summary string `json:"summary,omitempty"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileMetadata struct {
|
||||||
|
Architecture string `json:"architecture,omitempty"`
|
||||||
|
Epoch string `json:"epoch,omitempty"`
|
||||||
|
Version string `json:"version,omitempty"`
|
||||||
|
Release string `json:"release,omitempty"`
|
||||||
|
Vendor string `json:"vendor,omitempty"`
|
||||||
|
Group string `json:"group,omitempty"`
|
||||||
|
Packager string `json:"packager,omitempty"`
|
||||||
|
SourceRpm string `json:"source_rpm,omitempty"`
|
||||||
|
BuildHost string `json:"build_host,omitempty"`
|
||||||
|
BuildTime uint64 `json:"build_time,omitempty"`
|
||||||
|
FileTime uint64 `json:"file_time,omitempty"`
|
||||||
|
InstalledSize uint64 `json:"installed_size,omitempty"`
|
||||||
|
ArchiveSize uint64 `json:"archive_size,omitempty"`
|
||||||
|
|
||||||
|
Provides []*Entry `json:"provide,omitempty"`
|
||||||
|
Requires []*Entry `json:"require,omitempty"`
|
||||||
|
Conflicts []*Entry `json:"conflict,omitempty"`
|
||||||
|
Obsoletes []*Entry `json:"obsolete,omitempty"`
|
||||||
|
|
||||||
|
Files []*File `json:"files,omitempty"`
|
||||||
|
|
||||||
|
Changelogs []*Changelog `json:"changelogs,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Entry struct {
|
||||||
|
Name string `json:"name" xml:"name,attr"`
|
||||||
|
Flags string `json:"flags,omitempty" xml:"flags,attr,omitempty"`
|
||||||
|
Version string `json:"version,omitempty" xml:"ver,attr,omitempty"`
|
||||||
|
Epoch string `json:"epoch,omitempty" xml:"epoch,attr,omitempty"`
|
||||||
|
Release string `json:"release,omitempty" xml:"rel,attr,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type File struct {
|
||||||
|
Path string `json:"path" xml:",chardata"` // nolint: tagliatelle
|
||||||
|
Type string `json:"type,omitempty" xml:"type,attr,omitempty"`
|
||||||
|
IsExecutable bool `json:"is_executable" xml:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Changelog struct {
|
||||||
|
Author string `json:"author,omitempty" xml:"author,attr"`
|
||||||
|
Date int64 `json:"date,omitempty" xml:"date,attr"`
|
||||||
|
Text string `json:"text,omitempty" xml:",chardata"` // nolint: tagliatelle
|
||||||
|
}
|
||||||
|
|
||||||
|
// RpmMetadata represents the metadata for a RPM package.
|
||||||
|
//
|
||||||
|
//nolint:revive
|
||||||
|
type RpmMetadata struct {
|
||||||
|
Metadata
|
||||||
|
Files []metadata.File `json:"files"`
|
||||||
|
FileCount int64 `json:"file_count"`
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *RpmMetadata) GetSize() int64 {
|
||||||
|
return p.Size
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *RpmMetadata) UpdateSize(size int64) {
|
||||||
|
p.Size += size
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *RpmMetadata) GetFiles() []metadata.File {
|
||||||
|
return p.Files
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *RpmMetadata) SetFiles(files []metadata.File) {
|
||||||
|
p.Files = files
|
||||||
|
p.FileCount = int64(len(files))
|
||||||
|
}
|
@ -56,7 +56,9 @@ type LocalBase interface {
|
|||||||
Upload(
|
Upload(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
info pkg.ArtifactInfo,
|
info pkg.ArtifactInfo,
|
||||||
fileName, version, path string,
|
fileName,
|
||||||
|
version,
|
||||||
|
path string,
|
||||||
file io.ReadCloser,
|
file io.ReadCloser,
|
||||||
metadata metadata.Metadata,
|
metadata metadata.Metadata,
|
||||||
) (*commons.ResponseHeaders, string, error)
|
) (*commons.ResponseHeaders, string, error)
|
||||||
@ -121,7 +123,9 @@ func (l *localBase) UploadFile(
|
|||||||
func (l *localBase) Upload(
|
func (l *localBase) Upload(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
info pkg.ArtifactInfo,
|
info pkg.ArtifactInfo,
|
||||||
fileName, version, path string,
|
fileName,
|
||||||
|
version,
|
||||||
|
path string,
|
||||||
file io.ReadCloser,
|
file io.ReadCloser,
|
||||||
metadata metadata.Metadata,
|
metadata metadata.Metadata,
|
||||||
) (*commons.ResponseHeaders, string, error) {
|
) (*commons.ResponseHeaders, string, error) {
|
||||||
@ -228,10 +232,8 @@ func (l *localBase) Download(
|
|||||||
path := "/" + info.Image + "/" + version + "/" + fileName
|
path := "/" + info.Image + "/" + version + "/" + fileName
|
||||||
reg, _ := l.registryDao.GetByRootParentIDAndName(ctx, info.RootParentID, info.RegIdentifier)
|
reg, _ := l.registryDao.GetByRootParentIDAndName(ctx, info.RootParentID, info.RegIdentifier)
|
||||||
|
|
||||||
fileReader, _, redirectURL, err := l.fileManager.DownloadFile(ctx, path, types.Registry{
|
fileReader, _, redirectURL, err := l.fileManager.DownloadFile(ctx, path, reg.ID,
|
||||||
ID: reg.ID,
|
info.RegIdentifier, info.RootIdentifier)
|
||||||
Name: info.RegIdentifier,
|
|
||||||
}, info.RootIdentifier)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return responseHeaders, nil, "", err
|
return responseHeaders, nil, "", err
|
||||||
}
|
}
|
||||||
@ -296,6 +298,7 @@ func (l *localBase) updateMetadata(
|
|||||||
files = append(files, metadata.File{
|
files = append(files, metadata.File{
|
||||||
Size: fileInfo.Size, Filename: fileInfo.Filename,
|
Size: fileInfo.Size, Filename: fileInfo.Filename,
|
||||||
CreatedAt: time.Now().UnixMilli(),
|
CreatedAt: time.Now().UnixMilli(),
|
||||||
|
Sha256: fileInfo.Sha256,
|
||||||
})
|
})
|
||||||
inputMetadata.SetFiles(files)
|
inputMetadata.SetFiles(files)
|
||||||
inputMetadata.UpdateSize(fileInfo.Size)
|
inputMetadata.UpdateSize(fileInfo.Size)
|
||||||
@ -303,7 +306,7 @@ func (l *localBase) updateMetadata(
|
|||||||
} else {
|
} else {
|
||||||
files = append(files, metadata.File{
|
files = append(files, metadata.File{
|
||||||
Size: fileInfo.Size, Filename: fileInfo.Filename,
|
Size: fileInfo.Size, Filename: fileInfo.Filename,
|
||||||
CreatedAt: time.Now().UnixMilli(),
|
Sha256: fileInfo.Sha256, CreatedAt: time.Now().UnixMilli(),
|
||||||
})
|
})
|
||||||
inputMetadata.SetFiles(files)
|
inputMetadata.SetFiles(files)
|
||||||
inputMetadata.UpdateSize(fileInfo.Size)
|
inputMetadata.UpdateSize(fileInfo.Size)
|
||||||
|
@ -209,13 +209,14 @@ func (f *FileManager) SaveNode(
|
|||||||
func (f *FileManager) DownloadFile(
|
func (f *FileManager) DownloadFile(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
filePath string,
|
filePath string,
|
||||||
regInfo types.Registry,
|
registryID int64,
|
||||||
|
registryIdentifier string,
|
||||||
rootIdentifier string,
|
rootIdentifier string,
|
||||||
) (fileReader *storage.FileReader, size int64, redirectURL string, err error) {
|
) (fileReader *storage.FileReader, size int64, redirectURL string, err error) {
|
||||||
node, err := f.nodesDao.GetByPathAndRegistryID(ctx, regInfo.ID, filePath)
|
node, err := f.nodesDao.GetByPathAndRegistryID(ctx, registryID, filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, "", fmt.Errorf("failed to get the file for path: %s, "+
|
return nil, 0, "", fmt.Errorf("failed to get the file for path: %s, "+
|
||||||
"with registry: %s", filePath, regInfo.Name)
|
"with registry: %s", filePath, registryIdentifier)
|
||||||
}
|
}
|
||||||
blob, err := f.genericBlobDao.FindByID(ctx, node.BlobID)
|
blob, err := f.genericBlobDao.FindByID(ctx, node.BlobID)
|
||||||
|
|
||||||
@ -226,7 +227,7 @@ func (f *FileManager) DownloadFile(
|
|||||||
|
|
||||||
completeFilaPath := path.Join(rootPathString + rootIdentifier + rootPathString + files + rootPathString + blob.Sha256)
|
completeFilaPath := path.Join(rootPathString + rootIdentifier + rootPathString + files + rootPathString + blob.Sha256)
|
||||||
//
|
//
|
||||||
blobContext := f.App.GetBlobsContext(ctx, regInfo.Name, rootIdentifier)
|
blobContext := f.App.GetBlobsContext(ctx, registryIdentifier, rootIdentifier)
|
||||||
reader, redirectURL, err := blobContext.genericBlobStore.Get(ctx, completeFilaPath, blob.Size)
|
reader, redirectURL, err := blobContext.genericBlobStore.Get(ctx, completeFilaPath, blob.Size)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -225,10 +225,8 @@ func (c Controller) PullArtifact(ctx context.Context, info pkg.GenericArtifactIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
path := "/" + info.Image + "/" + info.Version + "/" + info.FileName
|
path := "/" + info.Image + "/" + info.Version + "/" + info.FileName
|
||||||
fileReader, _, redirectURL, err := c.fileManager.DownloadFile(ctx, path, types.Registry{
|
fileReader, _, redirectURL, err := c.fileManager.DownloadFile(ctx, path, info.RegistryID,
|
||||||
ID: info.RegistryID,
|
info.RegIdentifier, info.RootIdentifier)
|
||||||
Name: info.RegIdentifier,
|
|
||||||
}, info.RootIdentifier)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return responseHeaders, nil, "", errcode.ErrCodeRootNotFound.WithDetail(err)
|
return responseHeaders, nil, "", errcode.ErrCodeRootNotFound.WithDetail(err)
|
||||||
}
|
}
|
||||||
|
@ -106,10 +106,8 @@ func (r *LocalRegistry) FetchArtifact(ctx context.Context, info pkg.MavenArtifac
|
|||||||
}
|
}
|
||||||
var fileReader *storage.FileReader
|
var fileReader *storage.FileReader
|
||||||
if serveFile {
|
if serveFile {
|
||||||
fileReader, _, redirectURL, err = r.fileManager.DownloadFile(ctx, filePath, types.Registry{
|
fileReader, _, redirectURL, err = r.fileManager.DownloadFile(ctx, filePath, info.RegistryID,
|
||||||
ID: info.RegistryID,
|
info.RootIdentifier, info.RootIdentifier)
|
||||||
Name: info.RootIdentifier,
|
|
||||||
}, info.RootIdentifier)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return processError(err)
|
return processError(err)
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ func SetHeaders(
|
|||||||
responseHeaders.Code = http.StatusOK
|
responseHeaders.Code = http.StatusOK
|
||||||
responseHeaders.Headers["Content-Length"] = fmt.Sprintf("%d", fileInfo.Size)
|
responseHeaders.Headers["Content-Length"] = fmt.Sprintf("%d", fileInfo.Size)
|
||||||
responseHeaders.Headers["LastModified"] = fmt.Sprintf("%d", fileInfo.CreatedAt.Unix())
|
responseHeaders.Headers["LastModified"] = fmt.Sprintf("%d", fileInfo.CreatedAt.Unix())
|
||||||
responseHeaders.Headers["Filename"] = fileInfo.Filename
|
responseHeaders.Headers["FileName"] = fileInfo.Filename
|
||||||
switch ext {
|
switch ext {
|
||||||
case extensionJar:
|
case extensionJar:
|
||||||
responseHeaders.Headers["Content-Type"] = contentTypeJar
|
responseHeaders.Headers["Content-Type"] = contentTypeJar
|
||||||
|
@ -36,7 +36,6 @@ import (
|
|||||||
nugettype "github.com/harness/gitness/registry/app/pkg/types/nuget"
|
nugettype "github.com/harness/gitness/registry/app/pkg/types/nuget"
|
||||||
"github.com/harness/gitness/registry/app/storage"
|
"github.com/harness/gitness/registry/app/storage"
|
||||||
"github.com/harness/gitness/registry/app/store"
|
"github.com/harness/gitness/registry/app/store"
|
||||||
"github.com/harness/gitness/registry/types"
|
|
||||||
"github.com/harness/gitness/store/database/dbtx"
|
"github.com/harness/gitness/store/database/dbtx"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
@ -67,14 +66,17 @@ type localRegistry struct {
|
|||||||
urlProvider urlprovider.Provider
|
urlProvider urlprovider.Provider
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *localRegistry) GetServiceEndpoint(ctx context.Context,
|
func (c *localRegistry) GetServiceEndpoint(
|
||||||
info nugettype.ArtifactInfo) *nugettype.ServiceEndpoint {
|
ctx context.Context,
|
||||||
|
info nugettype.ArtifactInfo,
|
||||||
|
) *nugettype.ServiceEndpoint {
|
||||||
baseURL := c.urlProvider.RegistryURL(ctx, "pkg", info.RootIdentifier, info.RegIdentifier, "nuget")
|
baseURL := c.urlProvider.RegistryURL(ctx, "pkg", info.RootIdentifier, info.RegIdentifier, "nuget")
|
||||||
serviceEndpoints := buildServiceEndpoint(baseURL)
|
serviceEndpoints := buildServiceEndpoint(baseURL)
|
||||||
return serviceEndpoints
|
return serviceEndpoints
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *localRegistry) UploadPackage(ctx context.Context,
|
func (c *localRegistry) UploadPackage(
|
||||||
|
ctx context.Context,
|
||||||
info nugettype.ArtifactInfo,
|
info nugettype.ArtifactInfo,
|
||||||
fileReader io.ReadCloser,
|
fileReader io.ReadCloser,
|
||||||
) (headers *commons.ResponseHeaders, sha256 string, err error) {
|
) (headers *commons.ResponseHeaders, sha256 string, err error) {
|
||||||
@ -96,8 +98,10 @@ func (c *localRegistry) UploadPackage(ctx context.Context,
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *localRegistry) buildMetadata(info nugettype.ArtifactInfo,
|
func (c *localRegistry) buildMetadata(
|
||||||
fileReader io.Reader) (metadata nugetmetadata.Metadata, err error) {
|
info nugettype.ArtifactInfo,
|
||||||
|
fileReader io.Reader,
|
||||||
|
) (metadata nugetmetadata.Metadata, err error) {
|
||||||
pathUUID := uuid.NewString()
|
pathUUID := uuid.NewString()
|
||||||
tmpFile, err2 := os.CreateTemp(os.TempDir(), info.RootIdentifier+"-"+pathUUID+"*")
|
tmpFile, err2 := os.CreateTemp(os.TempDir(), info.RootIdentifier+"-"+pathUUID+"*")
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
@ -154,8 +158,10 @@ func (c *localRegistry) parseMetadata(f io.Reader) (metadata nugetmetadata.Metad
|
|||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *localRegistry) DownloadPackage(ctx context.Context,
|
func (c *localRegistry) DownloadPackage(
|
||||||
info nugettype.ArtifactInfo) (*commons.ResponseHeaders, *storage.FileReader, string, error) {
|
ctx context.Context,
|
||||||
|
info nugettype.ArtifactInfo,
|
||||||
|
) (*commons.ResponseHeaders, *storage.FileReader, string, error) {
|
||||||
responseHeaders := &commons.ResponseHeaders{
|
responseHeaders := &commons.ResponseHeaders{
|
||||||
Headers: make(map[string]string),
|
Headers: make(map[string]string),
|
||||||
Code: 0,
|
Code: 0,
|
||||||
@ -163,10 +169,8 @@ func (c *localRegistry) DownloadPackage(ctx context.Context,
|
|||||||
|
|
||||||
path := "/" + info.Image + "/" + info.Version + "/" + info.Filename
|
path := "/" + info.Image + "/" + info.Version + "/" + info.Filename
|
||||||
|
|
||||||
fileReader, _, redirectURL, err := c.fileManager.DownloadFile(ctx, path, types.Registry{
|
fileReader, _, redirectURL, err := c.fileManager.DownloadFile(ctx, path, info.RegistryID,
|
||||||
ID: info.RegistryID,
|
info.RegIdentifier, info.RootIdentifier)
|
||||||
Name: info.RegIdentifier,
|
|
||||||
}, info.RootIdentifier)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return responseHeaders, nil, "", err
|
return responseHeaders, nil, "", err
|
||||||
}
|
}
|
||||||
|
509
registry/app/pkg/rpm/helper.go
Normal file
509
registry/app/pkg/rpm/helper.go
Normal file
@ -0,0 +1,509 @@
|
|||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rpm
|
||||||
|
|
||||||
|
//nolint:gosec
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/md5"
|
||||||
|
"crypto/sha1"
|
||||||
|
"crypto/sha256"
|
||||||
|
"crypto/sha512"
|
||||||
|
"encoding"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"hash"
|
||||||
|
"io"
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
rpmmetadata "github.com/harness/gitness/registry/app/metadata/rpm"
|
||||||
|
"github.com/harness/gitness/registry/validation"
|
||||||
|
|
||||||
|
"github.com/sassoftware/go-rpmutils"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
sIFMT = 0xf000
|
||||||
|
sIFDIR = 0x4000
|
||||||
|
sIXUSR = 0x40
|
||||||
|
sIXGRP = 0x8
|
||||||
|
sIXOTH = 0x1
|
||||||
|
|
||||||
|
sizeMD5 = 92
|
||||||
|
sizeSHA1 = 96
|
||||||
|
sizeSHA256 = 108
|
||||||
|
sizeSHA512 = 204
|
||||||
|
size = sizeMD5 + sizeSHA1 + sizeSHA256 + sizeSHA512
|
||||||
|
|
||||||
|
RepoMdFile = "repomd.xml"
|
||||||
|
RepoDataPrefix = "repodata/"
|
||||||
|
|
||||||
|
DefaultMemorySize = 32 * 1024 * 1024
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidMemorySize = errors.New("memory size must be greater 0 and lower math.MaxInt32")
|
||||||
|
ErrWriteAfterRead = errors.New("write is unsupported after a read operation")
|
||||||
|
)
|
||||||
|
|
||||||
|
func parsePackage(r io.Reader) (*rpmPackage, error) {
|
||||||
|
rpm, err := rpmutils.ReadRpm(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
nevra, err := rpm.Header.GetNEVRA()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
version := fmt.Sprintf("%s-%s", nevra.Version, nevra.Release)
|
||||||
|
if nevra.Epoch != "" && nevra.Epoch != "0" {
|
||||||
|
version = fmt.Sprintf("%s-%s", nevra.Epoch, version)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &rpmPackage{
|
||||||
|
Name: nevra.Name,
|
||||||
|
Version: version,
|
||||||
|
VersionMetadata: &rpmmetadata.VersionMetadata{
|
||||||
|
Summary: getString(rpm.Header, rpmutils.SUMMARY),
|
||||||
|
Description: getString(rpm.Header, rpmutils.DESCRIPTION),
|
||||||
|
License: getString(rpm.Header, rpmutils.LICENSE),
|
||||||
|
ProjectURL: getString(rpm.Header, rpmutils.URL),
|
||||||
|
},
|
||||||
|
FileMetadata: &rpmmetadata.FileMetadata{
|
||||||
|
Architecture: nevra.Arch,
|
||||||
|
Epoch: nevra.Epoch,
|
||||||
|
Version: nevra.Version,
|
||||||
|
Release: nevra.Release,
|
||||||
|
Vendor: getString(rpm.Header, rpmutils.VENDOR),
|
||||||
|
Group: getString(rpm.Header, rpmutils.GROUP),
|
||||||
|
Packager: getString(rpm.Header, rpmutils.PACKAGER),
|
||||||
|
SourceRpm: getString(rpm.Header, rpmutils.SOURCERPM),
|
||||||
|
BuildHost: getString(rpm.Header, rpmutils.BUILDHOST),
|
||||||
|
BuildTime: getUInt64(rpm.Header, rpmutils.BUILDTIME),
|
||||||
|
FileTime: getUInt64(rpm.Header, rpmutils.FILEMTIMES),
|
||||||
|
InstalledSize: getUInt64(rpm.Header, rpmutils.SIZE),
|
||||||
|
ArchiveSize: getUInt64(rpm.Header, rpmutils.SIG_PAYLOADSIZE),
|
||||||
|
|
||||||
|
Provides: getEntries(rpm.Header, rpmutils.PROVIDENAME, rpmutils.PROVIDEVERSION, rpmutils.PROVIDEFLAGS),
|
||||||
|
Requires: getEntries(rpm.Header, rpmutils.REQUIRENAME, rpmutils.REQUIREVERSION, rpmutils.REQUIREFLAGS),
|
||||||
|
Conflicts: getEntries(rpm.Header, rpmutils.CONFLICTNAME, rpmutils.CONFLICTVERSION, rpmutils.CONFLICTFLAGS),
|
||||||
|
Obsoletes: getEntries(rpm.Header, rpmutils.OBSOLETENAME, rpmutils.OBSOLETEVERSION, rpmutils.OBSOLETEFLAGS),
|
||||||
|
Files: getFiles(rpm.Header),
|
||||||
|
Changelogs: getChangelogs(rpm.Header),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if !validation.IsValidURL(p.VersionMetadata.ProjectURL) {
|
||||||
|
p.VersionMetadata.ProjectURL = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getString(h *rpmutils.RpmHeader, tag int) string {
|
||||||
|
values, err := h.GetStrings(tag)
|
||||||
|
if err != nil || len(values) < 1 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return values[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUInt64(h *rpmutils.RpmHeader, tag int) uint64 {
|
||||||
|
values, err := h.GetUint64s(tag)
|
||||||
|
if err != nil || len(values) < 1 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return values[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// nolint: gocritic
|
||||||
|
func getEntries(h *rpmutils.RpmHeader, namesTag, versionsTag, flagsTag int) []*rpmmetadata.Entry {
|
||||||
|
names, err := h.GetStrings(namesTag)
|
||||||
|
if err != nil || len(names) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
flags, err := h.GetUint64s(flagsTag)
|
||||||
|
if err != nil || len(flags) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
versions, err := h.GetStrings(versionsTag)
|
||||||
|
if err != nil || len(versions) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(names) != len(flags) || len(names) != len(versions) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
entries := make([]*rpmmetadata.Entry, 0, len(names))
|
||||||
|
for i := range names {
|
||||||
|
e := &rpmmetadata.Entry{
|
||||||
|
Name: names[i],
|
||||||
|
}
|
||||||
|
|
||||||
|
flags := flags[i]
|
||||||
|
if (flags&rpmutils.RPMSENSE_GREATER) != 0 && (flags&rpmutils.RPMSENSE_EQUAL) != 0 {
|
||||||
|
e.Flags = "GE"
|
||||||
|
} else if (flags&rpmutils.RPMSENSE_LESS) != 0 && (flags&rpmutils.RPMSENSE_EQUAL) != 0 {
|
||||||
|
e.Flags = "LE"
|
||||||
|
} else if (flags & rpmutils.RPMSENSE_GREATER) != 0 {
|
||||||
|
e.Flags = "GT"
|
||||||
|
} else if (flags & rpmutils.RPMSENSE_LESS) != 0 {
|
||||||
|
e.Flags = "LT"
|
||||||
|
} else if (flags & rpmutils.RPMSENSE_EQUAL) != 0 {
|
||||||
|
e.Flags = "EQ"
|
||||||
|
}
|
||||||
|
|
||||||
|
version := versions[i]
|
||||||
|
if version != "" {
|
||||||
|
parts := strings.Split(version, "-")
|
||||||
|
|
||||||
|
versionParts := strings.Split(parts[0], ":")
|
||||||
|
if len(versionParts) == 2 {
|
||||||
|
e.Version = versionParts[1]
|
||||||
|
e.Epoch = versionParts[0]
|
||||||
|
} else {
|
||||||
|
e.Version = versionParts[0]
|
||||||
|
e.Epoch = "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(parts) > 1 {
|
||||||
|
e.Release = parts[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entries = append(entries, e)
|
||||||
|
}
|
||||||
|
return entries
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFiles(h *rpmutils.RpmHeader) []*rpmmetadata.File {
|
||||||
|
baseNames, _ := h.GetStrings(rpmutils.BASENAMES)
|
||||||
|
dirNames, _ := h.GetStrings(rpmutils.DIRNAMES)
|
||||||
|
dirIndexes, _ := h.GetUint32s(rpmutils.DIRINDEXES)
|
||||||
|
fileFlags, _ := h.GetUint32s(rpmutils.FILEFLAGS)
|
||||||
|
fileModes, _ := h.GetUint32s(rpmutils.FILEMODES)
|
||||||
|
|
||||||
|
files := make([]*rpmmetadata.File, 0, len(baseNames))
|
||||||
|
for i := range baseNames {
|
||||||
|
if len(dirIndexes) <= i {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dirIndex := dirIndexes[i]
|
||||||
|
if len(dirNames) <= int(dirIndex) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileType string
|
||||||
|
var isExecutable bool
|
||||||
|
if i < len(fileFlags) && (fileFlags[i]&rpmutils.RPMFILE_GHOST) != 0 {
|
||||||
|
fileType = "ghost"
|
||||||
|
} else if i < len(fileModes) {
|
||||||
|
if (fileModes[i] & sIFMT) == sIFDIR {
|
||||||
|
fileType = "dir"
|
||||||
|
} else {
|
||||||
|
mode := fileModes[i] & ^uint32(sIFMT)
|
||||||
|
isExecutable = (mode&sIXUSR) != 0 || (mode&sIXGRP) != 0 || (mode&sIXOTH) != 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
files = append(files, &rpmmetadata.File{
|
||||||
|
Path: dirNames[dirIndex] + baseNames[i],
|
||||||
|
Type: fileType,
|
||||||
|
IsExecutable: isExecutable,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return files
|
||||||
|
}
|
||||||
|
|
||||||
|
func getChangelogs(h *rpmutils.RpmHeader) []*rpmmetadata.Changelog {
|
||||||
|
texts, err := h.GetStrings(rpmutils.CHANGELOGTEXT)
|
||||||
|
if err != nil || len(texts) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
authors, err := h.GetStrings(rpmutils.CHANGELOGNAME)
|
||||||
|
if err != nil || len(authors) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
times, err := h.GetUint32s(rpmutils.CHANGELOGTIME)
|
||||||
|
if err != nil || len(times) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(texts) != len(authors) || len(texts) != len(times) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
changelogs := make([]*rpmmetadata.Changelog, 0, len(texts))
|
||||||
|
for i := range texts {
|
||||||
|
changelogs = append(changelogs, &rpmmetadata.Changelog{
|
||||||
|
Author: authors[i],
|
||||||
|
Date: int64(times[i]),
|
||||||
|
Text: texts[i],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return changelogs
|
||||||
|
}
|
||||||
|
|
||||||
|
type writtenCounter struct {
|
||||||
|
written int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *writtenCounter) Write(buf []byte) (int, error) {
|
||||||
|
n := len(buf)
|
||||||
|
|
||||||
|
wc.written += int64(n)
|
||||||
|
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *writtenCounter) Written() int64 {
|
||||||
|
return wc.written
|
||||||
|
}
|
||||||
|
|
||||||
|
type readAtSeeker interface {
|
||||||
|
io.ReadSeeker
|
||||||
|
io.ReaderAt
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileBackedBuffer struct {
|
||||||
|
maxMemorySize int64
|
||||||
|
size int64
|
||||||
|
buffer bytes.Buffer
|
||||||
|
file *os.File
|
||||||
|
reader readAtSeeker
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFileBackedBuffer(maxMemorySize int) (*FileBackedBuffer, error) {
|
||||||
|
if maxMemorySize < 0 || maxMemorySize > math.MaxInt32 {
|
||||||
|
return nil, ErrInvalidMemorySize
|
||||||
|
}
|
||||||
|
|
||||||
|
return &FileBackedBuffer{
|
||||||
|
maxMemorySize: int64(maxMemorySize),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//nolint:nestif
|
||||||
|
func (b *FileBackedBuffer) Write(p []byte) (int, error) {
|
||||||
|
if b.reader != nil {
|
||||||
|
return 0, ErrWriteAfterRead
|
||||||
|
}
|
||||||
|
|
||||||
|
var n int
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if b.file != nil {
|
||||||
|
n, err = b.file.Write(p)
|
||||||
|
} else {
|
||||||
|
if b.size+int64(len(p)) > b.maxMemorySize {
|
||||||
|
b.file, err = os.CreateTemp("", "gitness-buffer-")
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.Copy(b.file, &b.buffer)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err = b.buffer.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
b.size += int64(n)
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *FileBackedBuffer) Size() int64 {
|
||||||
|
return b.size
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *FileBackedBuffer) switchToReader() error {
|
||||||
|
if b.reader != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.file != nil {
|
||||||
|
if _, err := b.file.Seek(0, io.SeekStart); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.reader = b.file
|
||||||
|
} else {
|
||||||
|
b.reader = bytes.NewReader(b.buffer.Bytes())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *FileBackedBuffer) Read(p []byte) (int, error) {
|
||||||
|
if err := b.switchToReader(); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.reader.Read(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *FileBackedBuffer) ReadAt(p []byte, off int64) (int, error) {
|
||||||
|
if err := b.switchToReader(); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.reader.ReadAt(p, off)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *FileBackedBuffer) Seek(offset int64, whence int) (int64, error) {
|
||||||
|
if err := b.switchToReader(); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.reader.Seek(offset, whence)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *FileBackedBuffer) Close() error {
|
||||||
|
if b.file != nil {
|
||||||
|
err := b.file.Close()
|
||||||
|
os.Remove(b.file.Name())
|
||||||
|
b.file = nil
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type HashedBuffer struct {
|
||||||
|
*FileBackedBuffer
|
||||||
|
hash *MultiHasher
|
||||||
|
combinedWriter io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHashedBuffer() (*HashedBuffer, error) {
|
||||||
|
return NewHashedBufferWithSize(DefaultMemorySize)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHashedBufferWithSize(maxMemorySize int) (*HashedBuffer, error) {
|
||||||
|
b, err := NewFileBackedBuffer(maxMemorySize)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
hash := NewMultiHasher()
|
||||||
|
|
||||||
|
combinedWriter := io.MultiWriter(b, hash)
|
||||||
|
|
||||||
|
return &HashedBuffer{
|
||||||
|
b,
|
||||||
|
hash,
|
||||||
|
combinedWriter,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateHashedBufferFromReader(r io.Reader) (*HashedBuffer, error) {
|
||||||
|
return CreateHashedBufferFromReaderWithSize(r, DefaultMemorySize)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateHashedBufferFromReaderWithSize(r io.Reader, maxMemorySize int) (*HashedBuffer, error) {
|
||||||
|
b, err := NewHashedBufferWithSize(maxMemorySize)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.Copy(b, r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *HashedBuffer) Write(p []byte) (int, error) {
|
||||||
|
return b.combinedWriter.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *HashedBuffer) Sums() (hashMD5, hashSHA1, hashSHA256, hashSHA512 []byte) {
|
||||||
|
return b.hash.Sums()
|
||||||
|
}
|
||||||
|
|
||||||
|
type MultiHasher struct {
|
||||||
|
md5 hash.Hash
|
||||||
|
sha1 hash.Hash
|
||||||
|
sha256 hash.Hash
|
||||||
|
sha512 hash.Hash
|
||||||
|
|
||||||
|
combinedWriter io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
//nolint:gosec
|
||||||
|
func NewMultiHasher() *MultiHasher {
|
||||||
|
md5 := md5.New()
|
||||||
|
sha1 := sha1.New()
|
||||||
|
sha256 := sha256.New()
|
||||||
|
sha512 := sha512.New()
|
||||||
|
|
||||||
|
combinedWriter := io.MultiWriter(md5, sha1, sha256, sha512)
|
||||||
|
|
||||||
|
return &MultiHasher{
|
||||||
|
md5,
|
||||||
|
sha1,
|
||||||
|
sha256,
|
||||||
|
sha512,
|
||||||
|
combinedWriter,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// nolint:errcheck
|
||||||
|
func (h *MultiHasher) MarshalBinary() ([]byte, error) {
|
||||||
|
md5Bytes, err := h.md5.(encoding.BinaryMarshaler).MarshalBinary()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sha1Bytes, err := h.sha1.(encoding.BinaryMarshaler).MarshalBinary()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sha256Bytes, err := h.sha256.(encoding.BinaryMarshaler).MarshalBinary()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sha512Bytes, err := h.sha512.(encoding.BinaryMarshaler).MarshalBinary()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
b := make([]byte, 0, size)
|
||||||
|
b = append(b, md5Bytes...)
|
||||||
|
b = append(b, sha1Bytes...)
|
||||||
|
b = append(b, sha256Bytes...)
|
||||||
|
b = append(b, sha512Bytes...)
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *MultiHasher) Write(p []byte) (int, error) {
|
||||||
|
return h.combinedWriter.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *MultiHasher) Sums() (hashMD5, hashSHA1, hashSHA256, hashSHA512 []byte) {
|
||||||
|
hashMD5 = h.md5.Sum(nil)
|
||||||
|
hashSHA1 = h.sha1.Sum(nil)
|
||||||
|
hashSHA256 = h.sha256.Sum(nil)
|
||||||
|
hashSHA512 = h.sha512.Sum(nil)
|
||||||
|
return hashMD5, hashSHA1, hashSHA256, hashSHA512
|
||||||
|
}
|
179
registry/app/pkg/rpm/local.go
Normal file
179
registry/app/pkg/rpm/local.go
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rpm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"mime/multipart"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
urlprovider "github.com/harness/gitness/app/url"
|
||||||
|
"github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
|
||||||
|
rpmmetadata "github.com/harness/gitness/registry/app/metadata/rpm"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/base"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/commons"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/filemanager"
|
||||||
|
rpmtype "github.com/harness/gitness/registry/app/pkg/types/rpm"
|
||||||
|
"github.com/harness/gitness/registry/app/storage"
|
||||||
|
"github.com/harness/gitness/registry/app/store"
|
||||||
|
"github.com/harness/gitness/store/database/dbtx"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ pkg.Artifact = (*localRegistry)(nil)
|
||||||
|
var _ Registry = (*localRegistry)(nil)
|
||||||
|
|
||||||
|
type localRegistry struct {
|
||||||
|
localBase base.LocalBase
|
||||||
|
fileManager filemanager.FileManager
|
||||||
|
proxyStore store.UpstreamProxyConfigRepository
|
||||||
|
tx dbtx.Transactor
|
||||||
|
registryDao store.RegistryRepository
|
||||||
|
imageDao store.ImageRepository
|
||||||
|
artifactDao store.ArtifactRepository
|
||||||
|
urlProvider urlprovider.Provider
|
||||||
|
localRegistryHelper LocalRegistryHelper
|
||||||
|
}
|
||||||
|
|
||||||
|
type LocalRegistry interface {
|
||||||
|
Registry
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLocalRegistry(
|
||||||
|
localBase base.LocalBase,
|
||||||
|
fileManager filemanager.FileManager,
|
||||||
|
proxyStore store.UpstreamProxyConfigRepository,
|
||||||
|
tx dbtx.Transactor,
|
||||||
|
registryDao store.RegistryRepository,
|
||||||
|
imageDao store.ImageRepository,
|
||||||
|
artifactDao store.ArtifactRepository,
|
||||||
|
urlProvider urlprovider.Provider,
|
||||||
|
localRegistryHelper LocalRegistryHelper,
|
||||||
|
) LocalRegistry {
|
||||||
|
return &localRegistry{
|
||||||
|
localBase: localBase,
|
||||||
|
fileManager: fileManager,
|
||||||
|
proxyStore: proxyStore,
|
||||||
|
tx: tx,
|
||||||
|
registryDao: registryDao,
|
||||||
|
imageDao: imageDao,
|
||||||
|
artifactDao: artifactDao,
|
||||||
|
urlProvider: urlProvider,
|
||||||
|
localRegistryHelper: localRegistryHelper,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *localRegistry) GetArtifactType() artifact.RegistryType {
|
||||||
|
return artifact.RegistryTypeVIRTUAL
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *localRegistry) GetPackageTypes() []artifact.PackageType {
|
||||||
|
return []artifact.PackageType{artifact.PackageTypeRPM}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *localRegistry) UploadPackageFile(
|
||||||
|
ctx context.Context,
|
||||||
|
info rpmtype.ArtifactInfo,
|
||||||
|
file multipart.File,
|
||||||
|
) (headers *commons.ResponseHeaders, sha256 string, err error) {
|
||||||
|
buf, err := CreateHashedBufferFromReader(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
defer buf.Close()
|
||||||
|
|
||||||
|
pkg, err := parsePackage(buf)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("failded to parse rpm package: %v", err)
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := buf.Seek(0, io.SeekStart); err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
info.Image = pkg.Name
|
||||||
|
info.Version = pkg.Version + "." + pkg.FileMetadata.Architecture
|
||||||
|
info.Metadata = rpmmetadata.Metadata{
|
||||||
|
VersionMetadata: *pkg.VersionMetadata,
|
||||||
|
FileMetadata: *pkg.FileMetadata,
|
||||||
|
}
|
||||||
|
|
||||||
|
fileName := fmt.Sprintf("%s-%s.%s.rpm", pkg.Name, pkg.Version, pkg.FileMetadata.Architecture)
|
||||||
|
if info.FileName == "" {
|
||||||
|
info.FileName = fileName
|
||||||
|
}
|
||||||
|
|
||||||
|
path := fmt.Sprintf("%s/%s/%s/%s", pkg.Name, pkg.Version, pkg.FileMetadata.Architecture, fileName)
|
||||||
|
rs, sha256, err := c.localBase.Upload(ctx, info.ArtifactInfo, fileName, info.Version, path, buf,
|
||||||
|
&rpmmetadata.RpmMetadata{
|
||||||
|
Metadata: info.Metadata,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: make it async / atomic operation, implement artifact status (sync successful, sync failed..... statuses)
|
||||||
|
err = c.localRegistryHelper.BuildRegistryFiles(ctx, info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
return rs, sha256, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *localRegistry) GetRepoData(
|
||||||
|
ctx context.Context,
|
||||||
|
info rpmtype.ArtifactInfo,
|
||||||
|
fileName string,
|
||||||
|
) (*commons.ResponseHeaders,
|
||||||
|
*storage.FileReader,
|
||||||
|
io.ReadCloser,
|
||||||
|
string,
|
||||||
|
error,
|
||||||
|
) {
|
||||||
|
responseHeaders := &commons.ResponseHeaders{
|
||||||
|
Headers: make(map[string]string),
|
||||||
|
Code: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
fileReader, _, redirectURL, err := c.fileManager.DownloadFile(
|
||||||
|
ctx, "/"+RepoDataPrefix+fileName, info.RegistryID, info.RegIdentifier, info.RootIdentifier,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return responseHeaders, nil, nil, "", err
|
||||||
|
}
|
||||||
|
responseHeaders.Code = http.StatusOK
|
||||||
|
return responseHeaders, fileReader, nil, redirectURL, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *localRegistry) DownloadPackageFile(
|
||||||
|
ctx context.Context,
|
||||||
|
info rpmtype.ArtifactInfo,
|
||||||
|
) (*commons.ResponseHeaders, *storage.FileReader, io.ReadCloser, string, error) {
|
||||||
|
headers, fileReader, redirectURL, err := c.localBase.Download(
|
||||||
|
ctx, info.ArtifactInfo,
|
||||||
|
fmt.Sprintf("%s/%s", info.Version, info.Arch),
|
||||||
|
info.FileName,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, "", err
|
||||||
|
}
|
||||||
|
return headers, fileReader, nil, redirectURL, nil
|
||||||
|
}
|
316
registry/app/pkg/rpm/local_helper.go
Normal file
316
registry/app/pkg/rpm/local_helper.go
Normal file
@ -0,0 +1,316 @@
|
|||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rpm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"compress/gzip"
|
||||||
|
"context"
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
rpmmetadata "github.com/harness/gitness/registry/app/metadata/rpm"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/filemanager"
|
||||||
|
rpmtype "github.com/harness/gitness/registry/app/pkg/types/rpm"
|
||||||
|
"github.com/harness/gitness/registry/app/store"
|
||||||
|
)
|
||||||
|
|
||||||
|
const artifactBatchLimit = 50
|
||||||
|
|
||||||
|
type LocalRegistryHelper interface {
|
||||||
|
BuildRegistryFiles(ctx context.Context, info rpmtype.ArtifactInfo) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type localRegistryHelper struct {
|
||||||
|
fileManager filemanager.FileManager
|
||||||
|
artifactDao store.ArtifactRepository
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLocalRegistryHelper(
|
||||||
|
fileManager filemanager.FileManager,
|
||||||
|
artifactDao store.ArtifactRepository,
|
||||||
|
) LocalRegistryHelper {
|
||||||
|
return &localRegistryHelper{
|
||||||
|
fileManager: fileManager,
|
||||||
|
artifactDao: artifactDao,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *localRegistryHelper) BuildRegistryFiles(ctx context.Context, info rpmtype.ArtifactInfo) error {
|
||||||
|
lastArtifactID := int64(0)
|
||||||
|
var packageInfos []*packageInfo
|
||||||
|
|
||||||
|
for {
|
||||||
|
artifacts, err := l.artifactDao.GetAllArtifactsByRepo(ctx, info.RegistryID, artifactBatchLimit, lastArtifactID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, a := range *artifacts {
|
||||||
|
metadata := rpmmetadata.RpmMetadata{}
|
||||||
|
err := json.Unmarshal(a.Metadata, &metadata)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
packageInfos = append(packageInfos, &packageInfo{
|
||||||
|
Name: a.Name,
|
||||||
|
Sha256: metadata.GetFiles()[0].Sha256,
|
||||||
|
Size: metadata.GetFiles()[0].Size,
|
||||||
|
VersionMetadata: &metadata.VersionMetadata,
|
||||||
|
FileMetadata: &metadata.FileMetadata,
|
||||||
|
})
|
||||||
|
if a.ID > lastArtifactID {
|
||||||
|
lastArtifactID = a.ID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(*artifacts) < artifactBatchLimit {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
primary, err := l.buildPrimary(ctx, packageInfos, info)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fileLists, err := l.buildFilelists(ctx, packageInfos, info)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
other, err := l.buildOther(ctx, packageInfos, info)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return l.buildRepomd(ctx, []*repoData{
|
||||||
|
primary,
|
||||||
|
fileLists,
|
||||||
|
other,
|
||||||
|
}, info)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *localRegistryHelper) buildPrimary(
|
||||||
|
ctx context.Context,
|
||||||
|
pds []*packageInfo,
|
||||||
|
info rpmtype.ArtifactInfo,
|
||||||
|
) (*repoData, error) {
|
||||||
|
packages := make([]*primaryPackage, 0, len(pds))
|
||||||
|
for _, pd := range pds {
|
||||||
|
files := make([]*rpmmetadata.File, 0, 3)
|
||||||
|
for _, f := range pd.FileMetadata.Files {
|
||||||
|
if f.IsExecutable {
|
||||||
|
files = append(files, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
packageVersion := fmt.Sprintf("%s-%s", pd.FileMetadata.Version, pd.FileMetadata.Release)
|
||||||
|
packages = append(packages, &primaryPackage{
|
||||||
|
Type: "rpm",
|
||||||
|
Name: pd.Name,
|
||||||
|
Architecture: pd.FileMetadata.Architecture,
|
||||||
|
Version: primaryVersion{
|
||||||
|
Epoch: pd.FileMetadata.Epoch,
|
||||||
|
Version: pd.FileMetadata.Version,
|
||||||
|
Release: pd.FileMetadata.Release,
|
||||||
|
},
|
||||||
|
Checksum: primaryChecksum{
|
||||||
|
Type: "sha256",
|
||||||
|
Checksum: pd.Sha256,
|
||||||
|
Pkgid: "YES",
|
||||||
|
},
|
||||||
|
Summary: pd.VersionMetadata.Summary,
|
||||||
|
Description: pd.VersionMetadata.Description,
|
||||||
|
Packager: pd.FileMetadata.Packager,
|
||||||
|
URL: pd.VersionMetadata.ProjectURL,
|
||||||
|
Time: primaryTimes{
|
||||||
|
File: pd.FileMetadata.FileTime,
|
||||||
|
Build: pd.FileMetadata.BuildTime,
|
||||||
|
},
|
||||||
|
Size: primarySizes{
|
||||||
|
Package: pd.Size,
|
||||||
|
Installed: pd.FileMetadata.InstalledSize,
|
||||||
|
Archive: pd.FileMetadata.ArchiveSize,
|
||||||
|
},
|
||||||
|
Location: PrimaryLocation{
|
||||||
|
Href: fmt.Sprintf("package/%s/%s/%s/%s",
|
||||||
|
url.PathEscape(pd.Name),
|
||||||
|
url.PathEscape(packageVersion),
|
||||||
|
url.PathEscape(pd.FileMetadata.Architecture),
|
||||||
|
url.PathEscape(fmt.Sprintf("%s-%s.%s.rpm", pd.Name, packageVersion, pd.FileMetadata.Architecture))),
|
||||||
|
},
|
||||||
|
Format: primaryFormat{
|
||||||
|
License: pd.VersionMetadata.License,
|
||||||
|
Vendor: pd.FileMetadata.Vendor,
|
||||||
|
Group: pd.FileMetadata.Group,
|
||||||
|
Buildhost: pd.FileMetadata.BuildHost,
|
||||||
|
Sourcerpm: pd.FileMetadata.SourceRpm,
|
||||||
|
Provides: primaryEntryList{
|
||||||
|
Entries: pd.FileMetadata.Provides,
|
||||||
|
},
|
||||||
|
Requires: primaryEntryList{
|
||||||
|
Entries: pd.FileMetadata.Requires,
|
||||||
|
},
|
||||||
|
Conflicts: primaryEntryList{
|
||||||
|
Entries: pd.FileMetadata.Conflicts,
|
||||||
|
},
|
||||||
|
Obsoletes: primaryEntryList{
|
||||||
|
Entries: pd.FileMetadata.Obsoletes,
|
||||||
|
},
|
||||||
|
Files: files,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return l.addDataAsFileToRepo(ctx, "primary", &primaryMetadata{
|
||||||
|
Xmlns: "http://linux.duke.edu/metadata/common",
|
||||||
|
XmlnsRpm: "http://linux.duke.edu/metadata/rpm",
|
||||||
|
PackageCount: len(pds),
|
||||||
|
Packages: packages,
|
||||||
|
}, info)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *localRegistryHelper) buildOther(
|
||||||
|
ctx context.Context,
|
||||||
|
pds []*packageInfo,
|
||||||
|
info rpmtype.ArtifactInfo,
|
||||||
|
) (*repoData, error) {
|
||||||
|
packages := make([]*otherPackage, 0, len(pds))
|
||||||
|
for _, pd := range pds {
|
||||||
|
packages = append(packages, &otherPackage{
|
||||||
|
Pkgid: pd.Sha256,
|
||||||
|
Name: pd.Name,
|
||||||
|
Architecture: pd.FileMetadata.Architecture,
|
||||||
|
Version: otherVersion{
|
||||||
|
Epoch: pd.FileMetadata.Epoch,
|
||||||
|
Version: pd.FileMetadata.Version,
|
||||||
|
Release: pd.FileMetadata.Release,
|
||||||
|
},
|
||||||
|
Changelogs: pd.FileMetadata.Changelogs,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return l.addDataAsFileToRepo(ctx, "other", &otherdata{
|
||||||
|
Xmlns: "http://linux.duke.edu/metadata/other",
|
||||||
|
PackageCount: len(pds),
|
||||||
|
Packages: packages,
|
||||||
|
}, info)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *localRegistryHelper) buildFilelists(
|
||||||
|
ctx context.Context,
|
||||||
|
pds []*packageInfo,
|
||||||
|
info rpmtype.ArtifactInfo,
|
||||||
|
) (*repoData, error) { //nolint:dupl
|
||||||
|
packages := make([]*fileListPackage, 0, len(pds))
|
||||||
|
for _, pd := range pds {
|
||||||
|
packages = append(packages, &fileListPackage{
|
||||||
|
Pkgid: pd.Sha256,
|
||||||
|
Name: pd.Name,
|
||||||
|
Architecture: pd.FileMetadata.Architecture,
|
||||||
|
Version: fileListVersion{
|
||||||
|
Epoch: pd.FileMetadata.Epoch,
|
||||||
|
Version: pd.FileMetadata.Version,
|
||||||
|
Release: pd.FileMetadata.Release,
|
||||||
|
},
|
||||||
|
Files: pd.FileMetadata.Files,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return l.addDataAsFileToRepo(ctx, "filelists", &filelists{
|
||||||
|
Xmlns: "http://linux.duke.edu/metadata/other",
|
||||||
|
PackageCount: len(pds),
|
||||||
|
Packages: packages,
|
||||||
|
}, info)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *localRegistryHelper) buildRepomd(
|
||||||
|
ctx context.Context,
|
||||||
|
data []*repoData,
|
||||||
|
info rpmtype.ArtifactInfo,
|
||||||
|
) error {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
buf.WriteString(xml.Header)
|
||||||
|
if err := xml.NewEncoder(&buf).Encode(&repomd{
|
||||||
|
Xmlns: "http://linux.duke.edu/metadata/repo",
|
||||||
|
XmlnsRpm: "http://linux.duke.edu/metadata/rpm",
|
||||||
|
Data: data,
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
repomdContent, _ := CreateHashedBufferFromReader(&buf)
|
||||||
|
defer repomdContent.Close()
|
||||||
|
|
||||||
|
_, err := l.fileManager.UploadFile(ctx, RepoDataPrefix+RepoMdFile, info.RegIdentifier, info.RegistryID,
|
||||||
|
info.RootParentID, info.RootIdentifier, repomdContent, repomdContent, RepoMdFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *localRegistryHelper) addDataAsFileToRepo(
|
||||||
|
ctx context.Context,
|
||||||
|
filetype string,
|
||||||
|
obj any,
|
||||||
|
info rpmtype.ArtifactInfo,
|
||||||
|
) (*repoData, error) {
|
||||||
|
content, _ := NewHashedBuffer()
|
||||||
|
defer content.Close()
|
||||||
|
|
||||||
|
gzw := gzip.NewWriter(content)
|
||||||
|
wc := &writtenCounter{}
|
||||||
|
h := sha256.New()
|
||||||
|
|
||||||
|
w := io.MultiWriter(gzw, wc, h)
|
||||||
|
_, _ = w.Write([]byte(xml.Header))
|
||||||
|
|
||||||
|
if err := xml.NewEncoder(w).Encode(obj); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := gzw.Close(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
filename := filetype + ".xml.gz"
|
||||||
|
_, err := l.fileManager.UploadFile(ctx, RepoDataPrefix+filename, info.RegIdentifier, info.RegistryID,
|
||||||
|
info.RootParentID, info.RootIdentifier, content, content, filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, _, hashSHA256, _ := content.Sums()
|
||||||
|
|
||||||
|
return &repoData{
|
||||||
|
Type: filetype,
|
||||||
|
Checksum: repoChecksum{
|
||||||
|
Type: "sha256",
|
||||||
|
Value: hex.EncodeToString(hashSHA256),
|
||||||
|
},
|
||||||
|
OpenChecksum: repoChecksum{
|
||||||
|
Type: "sha256",
|
||||||
|
Value: hex.EncodeToString(h.Sum(nil)),
|
||||||
|
},
|
||||||
|
Location: repoLocation{
|
||||||
|
Href: "repodata/" + filename,
|
||||||
|
},
|
||||||
|
Timestamp: time.Now().Unix(),
|
||||||
|
Size: content.Size(),
|
||||||
|
OpenSize: wc.Written(),
|
||||||
|
}, nil
|
||||||
|
}
|
113
registry/app/pkg/rpm/proxy.go
Normal file
113
registry/app/pkg/rpm/proxy.go
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rpm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"mime/multipart"
|
||||||
|
|
||||||
|
urlprovider "github.com/harness/gitness/app/url"
|
||||||
|
"github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
|
||||||
|
"github.com/harness/gitness/registry/app/dist_temp/errcode"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/commons"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/filemanager"
|
||||||
|
rpmtype "github.com/harness/gitness/registry/app/pkg/types/rpm"
|
||||||
|
"github.com/harness/gitness/registry/app/storage"
|
||||||
|
"github.com/harness/gitness/registry/app/store"
|
||||||
|
"github.com/harness/gitness/store/database/dbtx"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ pkg.Artifact = (*proxy)(nil)
|
||||||
|
var _ Registry = (*proxy)(nil)
|
||||||
|
|
||||||
|
type proxy struct {
|
||||||
|
fileManager filemanager.FileManager
|
||||||
|
proxyStore store.UpstreamProxyConfigRepository
|
||||||
|
tx dbtx.Transactor
|
||||||
|
registryDao store.RegistryRepository
|
||||||
|
imageDao store.ImageRepository
|
||||||
|
artifactDao store.ArtifactRepository
|
||||||
|
urlProvider urlprovider.Provider
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *proxy) DownloadPackageFile(
|
||||||
|
_ context.Context,
|
||||||
|
_ rpmtype.ArtifactInfo,
|
||||||
|
) (*commons.ResponseHeaders, *storage.FileReader, io.ReadCloser, string, error) {
|
||||||
|
// TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
type Proxy interface {
|
||||||
|
Registry
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewProxy(
|
||||||
|
fileManager filemanager.FileManager,
|
||||||
|
proxyStore store.UpstreamProxyConfigRepository,
|
||||||
|
tx dbtx.Transactor,
|
||||||
|
registryDao store.RegistryRepository,
|
||||||
|
imageDao store.ImageRepository,
|
||||||
|
artifactDao store.ArtifactRepository,
|
||||||
|
urlProvider urlprovider.Provider,
|
||||||
|
) Proxy {
|
||||||
|
return &proxy{
|
||||||
|
proxyStore: proxyStore,
|
||||||
|
registryDao: registryDao,
|
||||||
|
imageDao: imageDao,
|
||||||
|
artifactDao: artifactDao,
|
||||||
|
fileManager: fileManager,
|
||||||
|
tx: tx,
|
||||||
|
urlProvider: urlProvider,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *proxy) GetArtifactType() artifact.RegistryType {
|
||||||
|
return artifact.RegistryTypeUPSTREAM
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *proxy) GetPackageTypes() []artifact.PackageType {
|
||||||
|
return []artifact.PackageType{artifact.PackageTypeRPM}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPackageMetadata returns the metadata of a RPM package.
|
||||||
|
func (r *proxy) GetRepoData(
|
||||||
|
_ context.Context,
|
||||||
|
_ rpmtype.ArtifactInfo,
|
||||||
|
_ string,
|
||||||
|
) (*commons.ResponseHeaders,
|
||||||
|
*storage.FileReader,
|
||||||
|
io.ReadCloser,
|
||||||
|
string,
|
||||||
|
error,
|
||||||
|
) {
|
||||||
|
return nil, nil, nil, "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UploadPackageFile FIXME: Extract this upload function for all types of packageTypes
|
||||||
|
// uploads the package file to the storage.
|
||||||
|
func (r *proxy) UploadPackageFile(
|
||||||
|
ctx context.Context,
|
||||||
|
_ rpmtype.ArtifactInfo,
|
||||||
|
_ multipart.File,
|
||||||
|
) (*commons.ResponseHeaders, string, error) {
|
||||||
|
log.Error().Ctx(ctx).Msg("Not implemented")
|
||||||
|
return nil, "", errcode.ErrCodeInvalidRequest.WithDetail(fmt.Errorf("not implemented"))
|
||||||
|
}
|
49
registry/app/pkg/rpm/registry.go
Normal file
49
registry/app/pkg/rpm/registry.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rpm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"mime/multipart"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/registry/app/pkg"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/commons"
|
||||||
|
rpm "github.com/harness/gitness/registry/app/pkg/types/rpm"
|
||||||
|
"github.com/harness/gitness/registry/app/storage"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Registry interface {
|
||||||
|
pkg.Artifact
|
||||||
|
|
||||||
|
UploadPackageFile(
|
||||||
|
ctx context.Context,
|
||||||
|
info rpm.ArtifactInfo,
|
||||||
|
file multipart.File,
|
||||||
|
) (*commons.ResponseHeaders, string, error)
|
||||||
|
|
||||||
|
DownloadPackageFile(ctx context.Context, info rpm.ArtifactInfo) (
|
||||||
|
*commons.ResponseHeaders,
|
||||||
|
*storage.FileReader,
|
||||||
|
io.ReadCloser,
|
||||||
|
string,
|
||||||
|
error,
|
||||||
|
)
|
||||||
|
GetRepoData(ctx context.Context, info rpm.ArtifactInfo, fileName string) (*commons.ResponseHeaders,
|
||||||
|
*storage.FileReader,
|
||||||
|
io.ReadCloser,
|
||||||
|
string,
|
||||||
|
error)
|
||||||
|
}
|
25
registry/app/pkg/rpm/remote_helper.go
Normal file
25
registry/app/pkg/rpm/remote_helper.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rpm
|
||||||
|
|
||||||
|
type RemoteRegistryHelper interface {
|
||||||
|
}
|
||||||
|
|
||||||
|
type remoteRegistryHelper struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRemoteRegistryHelper() RemoteRegistryHelper {
|
||||||
|
return &remoteRegistryHelper{}
|
||||||
|
}
|
173
registry/app/pkg/rpm/types.go
Normal file
173
registry/app/pkg/rpm/types.go
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rpm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/xml"
|
||||||
|
|
||||||
|
rpmmetadata "github.com/harness/gitness/registry/app/metadata/rpm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type primaryVersion struct {
|
||||||
|
Epoch string `xml:"epoch,attr"`
|
||||||
|
Version string `xml:"ver,attr"`
|
||||||
|
Release string `xml:"rel,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type primaryChecksum struct {
|
||||||
|
Checksum string `xml:",chardata"` //nolint: tagliatelle
|
||||||
|
Type string `xml:"type,attr"`
|
||||||
|
Pkgid string `xml:"pkgid,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type primaryTimes struct {
|
||||||
|
File uint64 `xml:"file,attr"`
|
||||||
|
Build uint64 `xml:"build,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type primarySizes struct {
|
||||||
|
Package int64 `xml:"package,attr"`
|
||||||
|
Installed uint64 `xml:"installed,attr"`
|
||||||
|
Archive uint64 `xml:"archive,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PrimaryLocation struct {
|
||||||
|
Href string `xml:"href,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type primaryEntryList struct {
|
||||||
|
Entries []*rpmmetadata.Entry `xml:"rpm:entry"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type primaryFormat struct {
|
||||||
|
License string `xml:"rpm:license"`
|
||||||
|
Vendor string `xml:"rpm:vendor"`
|
||||||
|
Group string `xml:"rpm:group"`
|
||||||
|
Buildhost string `xml:"rpm:buildhost"`
|
||||||
|
Sourcerpm string `xml:"rpm:sourcerpm"`
|
||||||
|
Provides primaryEntryList `xml:"rpm:provides"`
|
||||||
|
Requires primaryEntryList `xml:"rpm:requires"`
|
||||||
|
Conflicts primaryEntryList `xml:"rpm:conflicts"`
|
||||||
|
Obsoletes primaryEntryList `xml:"rpm:obsoletes"`
|
||||||
|
Files []*rpmmetadata.File `xml:"file"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type primaryPackage struct {
|
||||||
|
XMLName xml.Name `xml:"package"`
|
||||||
|
Type string `xml:"type,attr"`
|
||||||
|
Name string `xml:"name"`
|
||||||
|
Architecture string `xml:"arch"`
|
||||||
|
Version primaryVersion `xml:"version"`
|
||||||
|
Checksum primaryChecksum `xml:"checksum"`
|
||||||
|
Summary string `xml:"summary"`
|
||||||
|
Description string `xml:"description"`
|
||||||
|
Packager string `xml:"packager"`
|
||||||
|
URL string `xml:"url"`
|
||||||
|
Time primaryTimes `xml:"time"`
|
||||||
|
Size primarySizes `xml:"size"`
|
||||||
|
Location PrimaryLocation `xml:"location"`
|
||||||
|
Format primaryFormat `xml:"format"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type primaryMetadata struct {
|
||||||
|
XMLName xml.Name `xml:"metadata"`
|
||||||
|
Xmlns string `xml:"xmlns,attr"`
|
||||||
|
XmlnsRpm string `xml:"xmlns:rpm,attr"`
|
||||||
|
PackageCount int `xml:"packages,attr"`
|
||||||
|
Packages []*primaryPackage `xml:"package"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type otherVersion struct {
|
||||||
|
Epoch string `xml:"epoch,attr"`
|
||||||
|
Version string `xml:"ver,attr"`
|
||||||
|
Release string `xml:"rel,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type otherPackage struct {
|
||||||
|
Pkgid string `xml:"pkgid,attr"`
|
||||||
|
Name string `xml:"name,attr"`
|
||||||
|
Architecture string `xml:"arch,attr"`
|
||||||
|
Version otherVersion `xml:"version"`
|
||||||
|
Changelogs []*rpmmetadata.Changelog `xml:"changelog"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type otherdata struct {
|
||||||
|
XMLName xml.Name `xml:"otherdata"`
|
||||||
|
Xmlns string `xml:"xmlns,attr"`
|
||||||
|
PackageCount int `xml:"packages,attr"`
|
||||||
|
Packages []*otherPackage `xml:"package"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type fileListVersion struct {
|
||||||
|
Epoch string `xml:"epoch,attr"`
|
||||||
|
Version string `xml:"ver,attr"`
|
||||||
|
Release string `xml:"rel,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type fileListPackage struct {
|
||||||
|
Pkgid string `xml:"pkgid,attr"`
|
||||||
|
Name string `xml:"name,attr"`
|
||||||
|
Architecture string `xml:"arch,attr"`
|
||||||
|
Version fileListVersion `xml:"version"`
|
||||||
|
Files []*rpmmetadata.File `xml:"file"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type filelists struct {
|
||||||
|
XMLName xml.Name `xml:"filelists"`
|
||||||
|
Xmlns string `xml:"xmlns,attr"`
|
||||||
|
PackageCount int `xml:"packages,attr"`
|
||||||
|
Packages []*fileListPackage `xml:"package"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type repomd struct {
|
||||||
|
XMLName xml.Name `xml:"repomd"`
|
||||||
|
Xmlns string `xml:"xmlns,attr"`
|
||||||
|
XmlnsRpm string `xml:"xmlns:rpm,attr"`
|
||||||
|
Data []*repoData `xml:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type repoChecksum struct {
|
||||||
|
Value string `xml:",chardata"` //nolint: tagliatelle
|
||||||
|
Type string `xml:"type,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type repoLocation struct {
|
||||||
|
Href string `xml:"href,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type repoData struct {
|
||||||
|
Type string `xml:"type,attr"`
|
||||||
|
Checksum repoChecksum `xml:"checksum"`
|
||||||
|
OpenChecksum repoChecksum `xml:"open-checksum"` //nolint: tagliatelle
|
||||||
|
Location repoLocation `xml:"location"`
|
||||||
|
Timestamp int64 `xml:"timestamp"`
|
||||||
|
Size int64 `xml:"size"`
|
||||||
|
OpenSize int64 `xml:"open-size"` //nolint: tagliatelle
|
||||||
|
}
|
||||||
|
|
||||||
|
type packageInfo struct {
|
||||||
|
Name string
|
||||||
|
Sha256 string
|
||||||
|
Size int64
|
||||||
|
VersionMetadata *rpmmetadata.VersionMetadata
|
||||||
|
FileMetadata *rpmmetadata.FileMetadata
|
||||||
|
}
|
||||||
|
|
||||||
|
type rpmPackage struct {
|
||||||
|
Name string
|
||||||
|
Version string
|
||||||
|
VersionMetadata *rpmmetadata.VersionMetadata
|
||||||
|
FileMetadata *rpmmetadata.FileMetadata
|
||||||
|
}
|
65
registry/app/pkg/rpm/wire.go
Normal file
65
registry/app/pkg/rpm/wire.go
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rpm
|
||||||
|
|
||||||
|
import (
|
||||||
|
urlprovider "github.com/harness/gitness/app/url"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/base"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/filemanager"
|
||||||
|
"github.com/harness/gitness/registry/app/store"
|
||||||
|
"github.com/harness/gitness/store/database/dbtx"
|
||||||
|
|
||||||
|
"github.com/google/wire"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LocalRegistryProvider(
|
||||||
|
localBase base.LocalBase,
|
||||||
|
fileManager filemanager.FileManager,
|
||||||
|
proxyStore store.UpstreamProxyConfigRepository,
|
||||||
|
tx dbtx.Transactor,
|
||||||
|
registryDao store.RegistryRepository,
|
||||||
|
imageDao store.ImageRepository,
|
||||||
|
artifactDao store.ArtifactRepository,
|
||||||
|
urlProvider urlprovider.Provider,
|
||||||
|
helper LocalRegistryHelper,
|
||||||
|
) LocalRegistry {
|
||||||
|
registry := NewLocalRegistry(localBase, fileManager, proxyStore, tx, registryDao, imageDao, artifactDao,
|
||||||
|
urlProvider, helper)
|
||||||
|
base.Register(registry)
|
||||||
|
return registry
|
||||||
|
}
|
||||||
|
|
||||||
|
func ProxyProvider(
|
||||||
|
proxyStore store.UpstreamProxyConfigRepository,
|
||||||
|
registryDao store.RegistryRepository,
|
||||||
|
imageDao store.ImageRepository,
|
||||||
|
artifactDao store.ArtifactRepository,
|
||||||
|
fileManager filemanager.FileManager,
|
||||||
|
tx dbtx.Transactor,
|
||||||
|
urlProvider urlprovider.Provider,
|
||||||
|
) Proxy {
|
||||||
|
proxy := NewProxy(fileManager, proxyStore, tx, registryDao, imageDao, artifactDao, urlProvider)
|
||||||
|
base.Register(proxy)
|
||||||
|
return proxy
|
||||||
|
}
|
||||||
|
|
||||||
|
func LocalRegistryHelperProvider(
|
||||||
|
fileManager filemanager.FileManager,
|
||||||
|
artifactDao store.ArtifactRepository,
|
||||||
|
) LocalRegistryHelper {
|
||||||
|
return NewLocalRegistryHelper(fileManager, artifactDao)
|
||||||
|
}
|
||||||
|
|
||||||
|
var WireSet = wire.NewSet(LocalRegistryProvider, ProxyProvider, LocalRegistryHelperProvider)
|
54
registry/app/pkg/types/rpm/types.go
Normal file
54
registry/app/pkg/types/rpm/types.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rpm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/harness/gitness/registry/app/metadata/rpm"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ArtifactInfo struct {
|
||||||
|
pkg.ArtifactInfo
|
||||||
|
Version string
|
||||||
|
Arch string
|
||||||
|
FileName string
|
||||||
|
Metadata rpm.Metadata
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a ArtifactInfo) GetVersion() string {
|
||||||
|
return a.Version
|
||||||
|
}
|
||||||
|
|
||||||
|
// BaseArtifactInfo implements pkg.PackageArtifactInfo interface.
|
||||||
|
func (a ArtifactInfo) BaseArtifactInfo() pkg.ArtifactInfo {
|
||||||
|
return a.ArtifactInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a ArtifactInfo) GetImageVersion() (exists bool, imageVersion string) {
|
||||||
|
if a.Image != "" && a.Version != "" {
|
||||||
|
return true, pkg.JoinWithSeparator(":", a.Image, a.Version)
|
||||||
|
}
|
||||||
|
return false, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type File struct {
|
||||||
|
FileURL string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
type PackageMetadata struct {
|
||||||
|
Name string
|
||||||
|
Files []File
|
||||||
|
}
|
@ -459,12 +459,12 @@ type ArtifactRepository interface {
|
|||||||
ctx context.Context, parentID int64,
|
ctx context.Context, parentID int64,
|
||||||
registryIDs *[]string, search string, latestVersion bool, packageTypes []string,
|
registryIDs *[]string, search string, latestVersion bool, packageTypes []string,
|
||||||
) (int64, error)
|
) (int64, error)
|
||||||
GetAllArtifactsByRepo(
|
GetArtifactsByRepo(
|
||||||
ctx context.Context, parentID int64, repoKey string,
|
ctx context.Context, parentID int64, repoKey string,
|
||||||
sortByField string, sortByOrder string, limit int, offset int, search string,
|
sortByField string, sortByOrder string, limit int, offset int, search string,
|
||||||
labels []string,
|
labels []string,
|
||||||
) (*[]types.ArtifactMetadata, error)
|
) (*[]types.ArtifactMetadata, error)
|
||||||
CountAllArtifactsByRepo(
|
CountArtifactsByRepo(
|
||||||
ctx context.Context, parentID int64, repoKey string,
|
ctx context.Context, parentID int64, repoKey string,
|
||||||
search string, labels []string,
|
search string, labels []string,
|
||||||
) (int64, error)
|
) (int64, error)
|
||||||
@ -494,6 +494,10 @@ type ArtifactRepository interface {
|
|||||||
|
|
||||||
DeleteByVersionAndImageName(ctx context.Context, image string, version string, regID int64) (err error)
|
DeleteByVersionAndImageName(ctx context.Context, image string, version string, regID int64) (err error)
|
||||||
GetLatestByImageID(ctx context.Context, imageID int64) (*types.Artifact, error)
|
GetLatestByImageID(ctx context.Context, imageID int64) (*types.Artifact, error)
|
||||||
|
|
||||||
|
GetAllArtifactsByRepo(
|
||||||
|
ctx context.Context, registryID int64, batchSize int, artifactID int64,
|
||||||
|
) (*[]types.ArtifactMetadata, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type DownloadStatRepository interface {
|
type DownloadStatRepository interface {
|
||||||
|
@ -99,7 +99,8 @@ func (a ArtifactDao) GetByRegistryIDAndImage(ctx context.Context, registryID int
|
|||||||
}
|
}
|
||||||
|
|
||||||
artifacts := make([]types.Artifact, len(dst))
|
artifacts := make([]types.Artifact, len(dst))
|
||||||
for i, d := range dst {
|
for i := range dst {
|
||||||
|
d := dst[i]
|
||||||
art, err := a.mapToArtifact(ctx, &d)
|
art, err := a.mapToArtifact(ctx, &d)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "Failed to map artifact")
|
return nil, errors.Wrap(err, "Failed to map artifact")
|
||||||
@ -203,8 +204,10 @@ func (a ArtifactDao) DeleteByImageNameAndRegistryID(ctx context.Context, regID i
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a ArtifactDao) DeleteByVersionAndImageName(ctx context.Context, image string,
|
func (a ArtifactDao) DeleteByVersionAndImageName(
|
||||||
version string, regID int64) (err error) {
|
ctx context.Context, image string,
|
||||||
|
version string, regID int64,
|
||||||
|
) (err error) {
|
||||||
delStmt := databaseg.Builder.Delete("artifacts").
|
delStmt := databaseg.Builder.Delete("artifacts").
|
||||||
Where("artifact_id IN (SELECT a.artifact_id FROM artifacts a JOIN images i ON i.image_id = a.artifact_image_id"+
|
Where("artifact_id IN (SELECT a.artifact_id FROM artifacts a JOIN images i ON i.image_id = a.artifact_image_id"+
|
||||||
" WHERE a.artifact_name = ? AND i.image_name = ? AND i.image_registry_id = ?)", version, image, regID)
|
" WHERE a.artifact_name = ? AND i.image_name = ? AND i.image_registry_id = ?)", version, image, regID)
|
||||||
@ -399,8 +402,8 @@ func (a ArtifactDao) CountAllArtifactsByParentID(
|
|||||||
return count, nil
|
return count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a ArtifactDao) GetAllArtifactsByRepo(
|
func (a ArtifactDao) GetArtifactsByRepo(
|
||||||
ctx context.Context, parentID int64, repoKey string,
|
ctx context.Context, registryParentID int64, repoKey string,
|
||||||
sortByField string, sortByOrder string, limit int, offset int, search string,
|
sortByField string, sortByOrder string, limit int, offset int, search string,
|
||||||
labels []string,
|
labels []string,
|
||||||
) (*[]types.ArtifactMetadata, error) {
|
) (*[]types.ArtifactMetadata, error) {
|
||||||
@ -417,7 +420,7 @@ func (a ArtifactDao) GetAllArtifactsByRepo(
|
|||||||
JOIN images i ON i.image_id = a.artifact_image_id
|
JOIN images i ON i.image_id = a.artifact_image_id
|
||||||
JOIN registries r ON i.image_registry_id = r.registry_id
|
JOIN registries r ON i.image_registry_id = r.registry_id
|
||||||
WHERE r.registry_parent_id = ? AND r.registry_name = ? ) AS a1
|
WHERE r.registry_parent_id = ? AND r.registry_name = ? ) AS a1
|
||||||
ON a.artifact_id = a1.id`, parentID, repoKey, // nolint:goconst
|
ON a.artifact_id = a1.id`, registryParentID, repoKey, // nolint:goconst
|
||||||
).
|
).
|
||||||
Join("images i ON i.image_id = a.artifact_image_id").
|
Join("images i ON i.image_id = a.artifact_image_id").
|
||||||
Join("registries r ON i.image_registry_id = r.registry_id").
|
Join("registries r ON i.image_registry_id = r.registry_id").
|
||||||
@ -430,7 +433,7 @@ func (a ArtifactDao) GetAllArtifactsByRepo(
|
|||||||
JOIN images i ON i.image_id = t1.artifact_image_id
|
JOIN images i ON i.image_id = t1.artifact_image_id
|
||||||
JOIN registries r ON r.registry_id = i.image_registry_id
|
JOIN registries r ON r.registry_id = i.image_registry_id
|
||||||
WHERE r.registry_parent_id = ? AND r.registry_name = ? GROUP BY i.image_name) as t2
|
WHERE r.registry_parent_id = ? AND r.registry_name = ? GROUP BY i.image_name) as t2
|
||||||
ON i.image_name = t2.image_name`, parentID, repoKey,
|
ON i.image_name = t2.image_name`, registryParentID, repoKey,
|
||||||
).
|
).
|
||||||
Where("a1.rank = 1 ")
|
Where("a1.rank = 1 ")
|
||||||
|
|
||||||
@ -469,7 +472,7 @@ func (a ArtifactDao) GetAllArtifactsByRepo(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// nolint:goconst
|
// nolint:goconst
|
||||||
func (a ArtifactDao) CountAllArtifactsByRepo(
|
func (a ArtifactDao) CountArtifactsByRepo(
|
||||||
ctx context.Context, parentID int64, repoKey string,
|
ctx context.Context, parentID int64, repoKey string,
|
||||||
search string, labels []string,
|
search string, labels []string,
|
||||||
) (int64, error) {
|
) (int64, error) {
|
||||||
@ -747,11 +750,41 @@ func (a ArtifactDao) GetArtifactMetadata(
|
|||||||
return a.mapToArtifactMetadata(ctx, dst)
|
return a.mapToArtifactMetadata(ctx, dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a ArtifactDao) GetAllArtifactsByRepo(
|
||||||
|
ctx context.Context, registryID int64, batchSize int, artifactID int64,
|
||||||
|
) (*[]types.ArtifactMetadata, error) {
|
||||||
|
q := databaseg.Builder.Select(
|
||||||
|
`r.registry_name as repo_name, i.image_name as name,
|
||||||
|
a.artifact_id as artifact_id, a.artifact_version as version, a.artifact_metadata as metadata`,
|
||||||
|
).
|
||||||
|
From("artifacts a").
|
||||||
|
Join("images i ON i.image_id = a.artifact_image_id").
|
||||||
|
Join("registries r ON i.image_registry_id = r.registry_id").
|
||||||
|
Where("artifact_id > ? AND r.registry_id = ?", artifactID, registryID).
|
||||||
|
OrderBy("artifact_id ASC").
|
||||||
|
Limit(util.SafeIntToUInt64(batchSize))
|
||||||
|
|
||||||
|
sql, args, err := q.ToSql()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "Failed to convert query to sql")
|
||||||
|
}
|
||||||
|
|
||||||
|
db := dbtx.GetAccessor(ctx, a.db)
|
||||||
|
|
||||||
|
var dst []*artifactMetadataDB
|
||||||
|
if err = db.SelectContext(ctx, &dst, sql, args...); err != nil {
|
||||||
|
return nil, databaseg.ProcessSQLErrorf(ctx, err, "Failed executing GetAllArtifactsByRepo query")
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.mapToArtifactMetadataList(ctx, dst)
|
||||||
|
}
|
||||||
|
|
||||||
func (a ArtifactDao) mapToArtifactMetadata(
|
func (a ArtifactDao) mapToArtifactMetadata(
|
||||||
_ context.Context,
|
_ context.Context,
|
||||||
dst *artifactMetadataDB,
|
dst *artifactMetadataDB,
|
||||||
) (*types.ArtifactMetadata, error) {
|
) (*types.ArtifactMetadata, error) {
|
||||||
return &types.ArtifactMetadata{
|
return &types.ArtifactMetadata{
|
||||||
|
ID: dst.ID,
|
||||||
Name: dst.Name,
|
Name: dst.Name,
|
||||||
RepoName: dst.RepoName,
|
RepoName: dst.RepoName,
|
||||||
DownloadCount: dst.DownloadCount,
|
DownloadCount: dst.DownloadCount,
|
||||||
@ -761,6 +794,7 @@ func (a ArtifactDao) mapToArtifactMetadata(
|
|||||||
CreatedAt: time.UnixMilli(dst.CreatedAt),
|
CreatedAt: time.UnixMilli(dst.CreatedAt),
|
||||||
ModifiedAt: time.UnixMilli(dst.ModifiedAt),
|
ModifiedAt: time.UnixMilli(dst.ModifiedAt),
|
||||||
Version: dst.Version,
|
Version: dst.Version,
|
||||||
|
Metadata: *dst.Metadata,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ package database
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
@ -73,6 +74,7 @@ type tagDB struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type artifactMetadataDB struct {
|
type artifactMetadataDB struct {
|
||||||
|
ID int64 `db:"artifact_id"`
|
||||||
Name string `db:"name"`
|
Name string `db:"name"`
|
||||||
RepoName string `db:"repo_name"`
|
RepoName string `db:"repo_name"`
|
||||||
DownloadCount int64 `db:"download_count"`
|
DownloadCount int64 `db:"download_count"`
|
||||||
@ -83,6 +85,7 @@ type artifactMetadataDB struct {
|
|||||||
ModifiedAt int64 `db:"modified_at"`
|
ModifiedAt int64 `db:"modified_at"`
|
||||||
Tag *string `db:"tag"`
|
Tag *string `db:"tag"`
|
||||||
Version string `db:"version"`
|
Version string `db:"version"`
|
||||||
|
Metadata *json.RawMessage `db:"metadata"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type tagMetadataDB struct {
|
type tagMetadataDB struct {
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
|
"github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
|
||||||
@ -34,6 +35,7 @@ type Tag struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ArtifactMetadata struct {
|
type ArtifactMetadata struct {
|
||||||
|
ID int64
|
||||||
Name string
|
Name string
|
||||||
RepoName string
|
RepoName string
|
||||||
DownloadCount int64
|
DownloadCount int64
|
||||||
@ -43,6 +45,7 @@ type ArtifactMetadata struct {
|
|||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
ModifiedAt time.Time
|
ModifiedAt time.Time
|
||||||
Version string
|
Version string
|
||||||
|
Metadata json.RawMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
type ImageMetadata struct {
|
type ImageMetadata struct {
|
||||||
|
Loading…
Reference in New Issue
Block a user