From 1ccc809eb25930f40ee6d7c743a8cb3bb92df1fd Mon Sep 17 00:00:00 2001 From: Mojtaba Date: Fri, 6 Dec 2024 14:18:18 +0100 Subject: [PATCH] feat: custom registry draft commit --- e2e/registry/build_image_test.go | 78 +++++++++++++ e2e/registry/suite_setup_test.go | 56 +++++++++ e2e/suite.go | 1 + go.mod | 30 ----- go.sum | 117 ------------------- pkg/builder/builder.go | 59 ++++++---- pkg/builder/docker/docker.go | 28 ++++- pkg/builder/kaniko/kaniko.go | 86 ++++++++++++-- pkg/builder/kaniko/kaniko_test.go | 41 +------ pkg/builder/registry/ttl.sh.go | 187 ++++++++++++++++++++++++++++++ pkg/cert/cert.go | 59 ++++++++++ pkg/container/docker.go | 14 +-- pkg/instance/build.go | 11 +- pkg/instance/execution.go | 2 + pkg/instance/network.go | 7 ++ pkg/k8s/pod.go | 54 +++++++-- pkg/k8s/security.go | 25 ++++ pkg/k8s/types.go | 1 + pkg/knuu/errors.go | 1 + pkg/knuu/knuu.go | 75 +++++++++--- 20 files changed, 671 insertions(+), 261 deletions(-) create mode 100644 e2e/registry/build_image_test.go create mode 100644 e2e/registry/suite_setup_test.go create mode 100644 pkg/builder/registry/ttl.sh.go create mode 100644 pkg/cert/cert.go create mode 100644 pkg/k8s/security.go diff --git a/e2e/registry/build_image_test.go b/e2e/registry/build_image_test.go new file mode 100644 index 0000000..cc6dd9f --- /dev/null +++ b/e2e/registry/build_image_test.go @@ -0,0 +1,78 @@ +package system + +import ( + "context" + "strings" + "time" + + "github.com/celestiaorg/knuu/pkg/builder" + "github.com/celestiaorg/knuu/pkg/instance" +) + +const ( + gitRepo = "https://github.com/celestiaorg/knuu.git" + gitBranch = "test/build-from-git" // This branch has a Dockerfile and is protected as to not be deleted +) + +func (s *Suite) TestBuildFromGit() { + const namePrefix = "registry-build-from-git" + + // Setup + ctx := context.Background() + + target, err := s.createAndStartBuildFromGitInstance(ctx, namePrefix) + s.Require().NoError(err) + + s.T().Log("Getting file bytes") + // The file is created by the dockerfile in the repo, + // so to make sure it is built correctly, we check the file + data, err := target.Storage().GetFileBytes(ctx, "/test.txt") + s.Require().NoError(err) + + data = []byte(strings.TrimSpace(string(data))) + s.Assert().Equal([]byte("Hello, World!"), data, "file bytes do not match.") +} + +func (s *Suite) TestRegistryCacheWithBuildFromGit() { + const namePrefix = "cache-registry-build-from-git" + + // Setup + ctx := context.Background() + + _, err := s.createAndStartBuildFromGitInstance(ctx, namePrefix) + s.Require().NoError(err) + + startTime := time.Now() + + _, err = s.createAndStartBuildFromGitInstance(ctx, "2nd-"+namePrefix) + s.Require().NoError(err) + + duration := time.Since(startTime) + s.T().Logf("Time taken: %s", duration) +} + +func (s *Suite) createAndStartBuildFromGitInstance(ctx context.Context, namePrefix string) (*instance.Instance, error) { + s.T().Logf("Creating new instance %s", namePrefix) + target, err := s.Knuu.NewInstance(namePrefix) + s.Require().NoError(err) + + s.T().Log("Building the image") + + // This is a blocking call which builds the image from git repo + err = target.Build().SetGitRepo(ctx, builder.GitContext{ + Repo: gitRepo, + Branch: gitBranch, + Username: "", + Password: "", + }) + s.Require().NoError(err) + s.T().Log("Image built") + + s.Require().NoError(target.Build().Commit(ctx)) + + s.T().Logf("Starting instance %s", namePrefix) + s.Require().NoError(target.Execution().Start(ctx)) + + s.T().Log("Instance started") + return target, nil +} diff --git a/e2e/registry/suite_setup_test.go b/e2e/registry/suite_setup_test.go new file mode 100644 index 0000000..68bf952 --- /dev/null +++ b/e2e/registry/suite_setup_test.go @@ -0,0 +1,56 @@ +package system + +import ( + "context" + "testing" + "time" + + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/suite" + + "github.com/celestiaorg/knuu/e2e" + "github.com/celestiaorg/knuu/pkg/k8s" + "github.com/celestiaorg/knuu/pkg/knuu" + "github.com/celestiaorg/knuu/pkg/minio" +) + +const ( + testTimeout = time.Minute * 100 // the same time that is used in the ci/cd pipeline + alpineImage = "alpine:latest" +) + +type Suite struct { + e2e.Suite +} + +func TestRunSuite(t *testing.T) { + suite.Run(t, new(Suite)) +} + +func (s *Suite) SetupSuite() { + var ( + ctx = context.Background() + logger = logrus.New() + ) + + logger.SetLevel(logrus.DebugLevel) + + k8sClient, err := k8s.NewClient(ctx, knuu.DefaultScope(), logger) + s.Require().NoError(err, "Error creating k8s client") + + minioClient, err := minio.New(ctx, k8sClient, logger) + s.Require().NoError(err, "Error creating minio client") + + s.Knuu, err = knuu.New(ctx, knuu.Options{ + LocalRegistryEnabled: true, + K8sClient: k8sClient, + MinioClient: minioClient, // needed for build from git tests + Timeout: testTimeout, + }) + s.Require().NoError(err) + + s.T().Logf("Scope: %s", s.Knuu.Scope) + s.Knuu.HandleStopSignal(ctx) + + s.Executor.Kn = s.Knuu +} diff --git a/e2e/suite.go b/e2e/suite.go index ab89b53..1051a7c 100644 --- a/e2e/suite.go +++ b/e2e/suite.go @@ -56,6 +56,7 @@ func (s *Suite) TearDownTest() { } func (s *Suite) cleanupSuite() { + return s.T().Logf("Cleaning up knuu...") if err := s.Knuu.CleanUp(context.Background()); err != nil { s.T().Logf("Error cleaning up test suite: %v", err) diff --git a/go.mod b/go.mod index 5324d71..dd3bb30 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ go 1.22.5 require ( github.com/celestiaorg/bittwister v0.0.0-20231213180407-65cdbaf5b8c7 - github.com/docker/docker v26.1.4+incompatible github.com/google/uuid v1.6.0 github.com/minio/minio-go/v7 v7.0.74 github.com/sirupsen/logrus v1.9.3 @@ -17,15 +16,8 @@ require ( ) require ( - github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/acroca/go-symbols v0.1.1 // indirect github.com/cilium/ebpf v0.12.3 // indirect - github.com/containerd/log v0.1.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/distribution/reference v0.5.0 // indirect - github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11 // indirect - github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect @@ -33,7 +25,6 @@ require ( github.com/frankban/quicktest v1.14.6 // indirect github.com/go-ini/ini v1.67.0 // indirect github.com/go-logr/logr v1.4.1 // indirect - github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.3 // indirect @@ -49,56 +40,35 @@ require ( github.com/imdario/mergo v0.3.16 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/karrick/godirwalk v1.17.0 // indirect github.com/klauspost/compress v1.17.9 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/minio/md5-simd v1.1.2 // indirect - github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/spdystream v0.2.0 // indirect - github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/morikuni/aec v1.0.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect - github.com/nsf/gocode v0.0.0-20230322162601-b672b49f3818 // indirect - github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/ramya-rao-a/go-outline v0.0.0-20210608161538-9736a4bde949 // indirect github.com/rs/xid v1.5.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.5.2 // indirect - github.com/uudashr/gopkgs v1.3.2 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect - go.opentelemetry.io/otel v1.26.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 // indirect - go.opentelemetry.io/otel/metric v1.26.0 // indirect - go.opentelemetry.io/otel/sdk v1.26.0 // indirect - go.opentelemetry.io/otel/trace v1.26.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/crypto v0.29.0 // indirect golang.org/x/exp v0.0.0-20240213143201-ec583247a57a // indirect - golang.org/x/mod v0.22.0 // indirect golang.org/x/net v0.31.0 // indirect golang.org/x/oauth2 v0.17.0 // indirect - golang.org/x/sync v0.9.0 // indirect golang.org/x/sys v0.27.0 // indirect golang.org/x/term v0.26.0 // indirect golang.org/x/text v0.20.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.27.0 // indirect - golang.org/x/tools/cmd/guru v0.1.1-deprecated // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - gotest.tools/v3 v3.5.1 // indirect k8s.io/klog/v2 v2.120.1 // indirect k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect diff --git a/go.sum b/go.sum index aa90d21..1a3d5e5 100644 --- a/go.sum +++ b/go.sum @@ -1,38 +1,19 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -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/acroca/go-symbols v0.1.1 h1:q3IzaMNYocw/Bnc2a8jkXf0hM3+POfLoq30x8HYuaPE= -github.com/acroca/go-symbols v0.1.1/go.mod h1:RKAIDWtcELAw6/wjNJGWRYZ7QEinSWoJeJ2H5cfK6AM= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/celestiaorg/bittwister v0.0.0-20231213180407-65cdbaf5b8c7 h1:nxplQi8wrLMjhu260RuigXylC3pWoDu4OVumPHeojnk= github.com/celestiaorg/bittwister v0.0.0-20231213180407-65cdbaf5b8c7/go.mod h1:1EF5MfOxVf0WC51Gb7pJ6bcZxnXKNAf9pqWtjgPBAYc= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cilium/ebpf v0.12.3 h1:8ht6F9MquybnY97at+VDZb3eQQr8ev79RueWeVaEcG4= github.com/cilium/ebpf v0.12.3/go.mod h1:TctK1ivibvI3znr66ljgi4hqOT8EYQjz1KWBfb1UVgM= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= -github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= -github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v26.1.4+incompatible h1:vuTpXDuoga+Z38m1OZHzl7NKisKWaWlhjQk7IDPSLsU= -github.com/docker/docker v26.1.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11 h1:IPrmumsT9t5BS7XcPhgsCTlkWbYg80SEXUzDpReaU6Y= -github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11/go.mod h1:a6bNUGTbQBsY6VRHTr4h/rkOXjl244DyRD0tx3fgq4Q= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= @@ -49,11 +30,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= @@ -95,16 +73,12 @@ github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWS github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/karrick/godirwalk v1.17.0 h1:b4kY7nqDdioR/6qnbHQyDvmA17u5G1cZ6J+CZXwSWoI= -github.com/karrick/godirwalk v1.17.0/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= 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/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= @@ -112,7 +86,6 @@ github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ib github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -126,43 +99,28 @@ github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/minio-go/v7 v7.0.74 h1:fTo/XlPBTSpo3BAMshlwKL5RspXRv9us5UeHEGYCFe0= github.com/minio/minio-go/v7 v7.0.74/go.mod h1:qydcVzV8Hqtj1VtEocfxbmVFa2siu6HGa+LDEPogjD8= -github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= -github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= -github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/nsf/gocode v0.0.0-20230322162601-b672b49f3818 h1:btvxUuer0DCdhu/N5fvMxW759ASqzIsm6cF8D23TNYs= -github.com/nsf/gocode v0.0.0-20230322162601-b672b49f3818/go.mod h1:6Q8/OMaaKAgTX7/jt2bOXVDrm1eJhoNd+iwzghR7jvs= github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY= github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= github.com/onsi/gomega v1.31.0 h1:54UJxxj6cPInHS3a35wm6BK/F9nHYueZ1NVujHDrnXE= github.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8= -github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/ramya-rao-a/go-outline v0.0.0-20210608161538-9736a4bde949 h1:iaD+iVf9xGfajsJp+zYrg9Lrk6gMJ6/hZHO4cYq5D5o= -github.com/ramya-rao-a/go-outline v0.0.0-20210608161538-9736a4bde949/go.mod h1:9V3eNbj9Z53yO7cKB6cSX9f0O7rYdIiuGBhjA1YsQuw= github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= @@ -170,18 +128,15 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -189,28 +144,9 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 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/uudashr/gopkgs v1.3.2 h1:ACme7LZyeSNIRIl9HtAA0RsT0eePUsrkHDVb2+aswhg= -github.com/uudashr/gopkgs v1.3.2/go.mod h1:MtCdKVJkxW7hNKWXPNWfpaeEp8+Ml3Q8myb4yWhn2Hg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= -go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= -go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 h1:1u/AyyOqAWzy+SkPxDpahCNZParHV8Vid1RnI2clyDE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0/go.mod h1:z46paqbJ9l7c9fIPCXTqTGwhQZ5XoTIsfeFYWboizjs= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 h1:1wp/gyxsuYtuE/JFxsQRtcCDtMrO2qMvlfXALU5wkzI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0/go.mod h1:gbTHmghkGgqxMomVQQMur1Nba4M0MQ8AYThXDUjsJ38= -go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= -go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= -go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= -go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= -go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= -go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= -go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= -go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= 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.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -221,10 +157,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= -golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -235,14 +167,7 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= -golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= -golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= -golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -253,12 +178,7 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -269,40 +189,22 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= -golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= golang.org/x/sys v0.27.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-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= -golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -310,10 +212,6 @@ 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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= @@ -326,16 +224,9 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= -golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= -golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE= -golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= -golang.org/x/tools/cmd/guru v0.1.1-deprecated h1:WiL3pQGXG71u4N45C0eRkE2IcEMAiQdDZ2H5lGspNjM= -golang.org/x/tools/cmd/guru v0.1.1-deprecated/go.mod h1:yFb7vixnH8+ByFZ63niwlvUUxyTE/6ULZ6AiEHZwlTk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -347,17 +238,11 @@ google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= -google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= -google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= @@ -373,8 +258,6 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= -gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= k8s.io/api v0.30.2 h1:+ZhRj+28QT4UOH+BKznu4CBgPWgkXO7XAvMcMl0qKvI= diff --git a/pkg/builder/builder.go b/pkg/builder/builder.go index 36b81dd..80b1a31 100644 --- a/pkg/builder/builder.go +++ b/pkg/builder/builder.go @@ -5,17 +5,26 @@ import ( "crypto/sha256" "encoding/hex" "fmt" + "strings" +) + +const ( + DefaultRegistryAddress = "ttl.sh" + DefaultImageTTL = "24h" // used as a tag for the ephemeral images on ttl.sh + DefaultImageTag = "latest" + DefaultCacheRepoName = "cl-kaniko-cache" // only abcdefghijklmnopqrstuvwxyz0123456789_-./ are allowed ) type Builder interface { - Build(ctx context.Context, b *BuilderOptions) (logs string, err error) + Build(ctx context.Context, b BuilderOptions) (logs string, err error) + ResolveImageName(buildContext string) (*ResolvedImage, error) + CacheOptions() *CacheOptions } type BuilderOptions struct { - ImageName string + ImageName string // Custom image name (if provided by the user) BuildContext string Args []ArgInterface - Destination string Cache *CacheOptions } @@ -25,23 +34,22 @@ type CacheOptions struct { Repo string } -func (c *CacheOptions) Default(buildContext string) (*CacheOptions, error) { - if buildContext == "" { - return nil, ErrBuildContextEmpty - } +type ResolvedImage struct { + Name string + Registry string + Tag string +} - ctxHash, err := hashString(buildContext) - if err != nil { - return nil, err - } +func (r *ResolvedImage) ToString() string { + return fmt.Sprintf("%s/%s:%s", r.Registry, r.Name, r.Tag) +} +func DefaultCacheOptions() *CacheOptions { return &CacheOptions{ Enabled: true, Dir: "", - // ttl.sh with the hash of build context is used as the cache repo - // Kaniko adds a string tag to the image name, so we don't need to add it here - Repo: fmt.Sprintf("ttl.sh/%s:24h", ctxHash), - }, nil + Repo: ImageWithRegistry(DefaultCacheRepoName, DefaultRegistryAddress), + } } func DefaultImageName(buildContext string) (string, error) { @@ -49,12 +57,23 @@ func DefaultImageName(buildContext string) (string, error) { return "", ErrBuildContextEmpty } - ctxHash, err := hashString(buildContext) - if err != nil { - return "", err - } + return hashString(buildContext) +} + +func IsImageWithTag(image string) bool { + return strings.Contains(image, ":") +} + +func IsImageWithRegistry(image string) bool { + return strings.Contains(image, "/") +} + +func ImageWithRegistry(name, registry string) string { + return fmt.Sprintf("%s/%s", registry, name) +} - return fmt.Sprintf("ttl.sh/%s:24h", ctxHash), nil +func ImageWithTag(name, tag string) string { + return fmt.Sprintf("%s:%s", name, tag) } func hashString(s string) (string, error) { diff --git a/pkg/builder/docker/docker.go b/pkg/builder/docker/docker.go index 85bd08b..3a1fd81 100644 --- a/pkg/builder/docker/docker.go +++ b/pkg/builder/docker/docker.go @@ -21,7 +21,7 @@ type Docker struct { var _ builder.Builder = &Docker{} -func (d *Docker) Build(_ context.Context, b *builder.BuilderOptions) (logs string, err error) { +func (d *Docker) Build(_ context.Context, b builder.BuilderOptions) (logs string, err error) { if builder.IsGitContext(b.BuildContext) { return "", ErrGitContextNotSupported } @@ -43,27 +43,27 @@ func (d *Docker) Build(_ context.Context, b *builder.BuilderOptions) (logs strin logrus.Debug("created new docker builder instance") } - logrus.Debug("building docker image: ", b.Destination) + logrus.Debug("building docker image: ", b.ImageName) buildContext := builder.GetDirFromBuildContext(b.BuildContext) // Since in docker the image name and destination must be the same, we just use the destination as the image name - cmd = exec.Command("docker", "buildx", "build", "--load", "--platform", "linux/amd64", "-t", b.Destination, buildContext) + cmd = exec.Command("docker", "buildx", "build", "--load", "--platform", "linux/amd64", "-t", b.ImageName, buildContext) cmdLogs, err := runCommand(cmd) if err != nil { return "", ErrFailedToBuildImage.Wrap(err) } logs += cmdLogs + "\n" - logrus.Debug("built docker image: ", b.Destination) + logrus.Debug("built docker image: ", b.ImageName) logrus.Debug("logs: ", cmdLogs) - cmd = exec.Command("docker", "push", b.Destination) + cmd = exec.Command("docker", "push", b.ImageName) cmdLogs, err = runCommand(cmd) if err != nil { return "", ErrFailedToPushImage.Wrap(err) } logs += cmdLogs + "\n" - logrus.Debug("pushed docker image: ", b.Destination) + logrus.Debug("pushed docker image: ", b.ImageName) logrus.Debug("logs: ", cmdLogs) if err := os.RemoveAll(b.BuildContext); err != nil { @@ -73,6 +73,22 @@ func (d *Docker) Build(_ context.Context, b *builder.BuilderOptions) (logs strin return logs, nil } +func (d *Docker) CacheOptions() *builder.CacheOptions { + return builder.DefaultCacheOptions() +} + +func (d *Docker) ResolveImageName(buildContext string) (*builder.ResolvedImage, error) { + imageName, err := builder.DefaultImageName(buildContext) + if err != nil { + return nil, err + } + return &builder.ResolvedImage{ + Name: imageName, + Registry: builder.DefaultRegistryAddress, + Tag: builder.DefaultImageTTL, + }, nil +} + func runCommand(cmd *exec.Cmd) (logs string, err error) { var stdout, stderr bytes.Buffer cmd.Stdout = &stdout diff --git a/pkg/builder/kaniko/kaniko.go b/pkg/builder/kaniko/kaniko.go index b187da7..7c76993 100644 --- a/pkg/builder/kaniko/kaniko.go +++ b/pkg/builder/kaniko/kaniko.go @@ -22,6 +22,9 @@ const ( kanikoContainerName = "kaniko-container" kanikoJobNamePrefix = "kaniko-build-job" + kanikoRegistryCertsVolName = "registry-certs" + kanikoRegistryCertsMountPath = "/kaniko/certs/" + DefaultParallelism = int32(1) DefaultBackoffLimit = int32(5) @@ -31,12 +34,28 @@ const ( type Kaniko struct { *system.SystemDependencies + Registry *RegistryOptions +} + +// RegistryOptions contains the options for the registry +type RegistryOptions struct { + Address string + Cert []byte + SecretName string } var _ builder.Builder = &Kaniko{} -func (k *Kaniko) Build(ctx context.Context, b *builder.BuilderOptions) (logs string, err error) { - job, err := k.prepareJob(ctx, b) +func (k *Kaniko) Build(ctx context.Context, b builder.BuilderOptions) (logs string, err error) { + if b.ImageName == "" { + image, err := k.ResolveImageName(b.BuildContext) + if err != nil { + return "", err + } + b.ImageName = image.ToString() + } + + job, err := k.prepareJob(ctx, &b) if err != nil { return "", ErrPreparingJob.Wrap(err) } @@ -68,6 +87,40 @@ func (k *Kaniko) Build(ctx context.Context, b *builder.BuilderOptions) (logs str return logs, nil } +func (k *Kaniko) CacheOptions() *builder.CacheOptions { + if k.Registry == nil { + return builder.DefaultCacheOptions() + } + + return &builder.CacheOptions{ + Enabled: true, + Repo: builder.ImageWithRegistry(builder.DefaultCacheRepoName, k.Registry.Address), + } +} + +func (k *Kaniko) ResolveImageName(buildContext string) (*builder.ResolvedImage, error) { + imageName, err := builder.DefaultImageName(buildContext) + if err != nil { + return nil, err + } + + var ( + registry = builder.DefaultRegistryAddress + tag = builder.DefaultImageTTL + ) + + if k.Registry != nil { + registry = k.Registry.Address + tag = builder.DefaultImageTag // Use default tag instead of TTL if custom registry + } + + return &builder.ResolvedImage{ + Name: imageName, + Registry: registry, + Tag: tag, + }, nil +} + func (k *Kaniko) waitForJobCompletion(ctx context.Context, job *batchv1.Job) (*batchv1.Job, error) { watcher, err := k.K8sClient.Clientset().BatchV1().Jobs(k.K8sClient.Namespace()).Watch(ctx, metav1.ListOptions{ FieldSelector: fmt.Sprintf("metadata.name=%s", job.Name), @@ -160,14 +213,30 @@ func (k *Kaniko) prepareJob(ctx context.Context, b *builder.BuilderOptions) (*ba { Name: kanikoContainerName, Image: kanikoImage, // debug has a shell - Args: prepareArgs(b), + Args: k.prepareArgs(b), Resources: v1.ResourceRequirements{ Requests: v1.ResourceList{ v1.ResourceEphemeralStorage: ephemeralStorage, }, }, + // VolumeMounts: []v1.VolumeMount{ + // { + // Name: kanikoRegistryCertsVolName, + // MountPath: kanikoRegistryCertsMountPath, + // }, + // }, }, }, + // Volumes: []v1.Volume{ + // { + // Name: kanikoRegistryCertsVolName, + // VolumeSource: v1.VolumeSource{ + // Secret: &v1.SecretVolumeSource{ + // SecretName: k.Registry.SecretName, + // }, + // }, + // }, + // }, RestartPolicy: "Never", // Ensure that the Pod does not restart }, }, @@ -252,18 +321,13 @@ func (k *Kaniko) mountDir(ctx context.Context, bCtx string, job *batchv1.Job) (* return job, nil } -func prepareArgs(b *builder.BuilderOptions) []string { +func (k *Kaniko) prepareArgs(b *builder.BuilderOptions) []string { args := []string{ "--context=" + b.BuildContext, - // TODO: see if we need it or not - // --git gitoptions Branch to clone if build context is a git repository (default branch=,single-branch=false,recurse-submodules=false) - - // TODO: we might need to add some options to get the auth token for the registry - "--destination=" + b.Destination, - // "--verbosity=debug", // log level + "--destination=" + b.ImageName, + "--skip-tls-verify", // Skip TLS verification for all registries } - // TODO: we need to add some configs to get the auth token for the cache repo if b.Cache != nil && b.Cache.Enabled { args = append(args, "--cache=true") if b.Cache.Dir != "" { diff --git a/pkg/builder/kaniko/kaniko_test.go b/pkg/builder/kaniko/kaniko_test.go index 2006a6f..6ff6565 100644 --- a/pkg/builder/kaniko/kaniko_test.go +++ b/pkg/builder/kaniko/kaniko_test.go @@ -38,16 +38,11 @@ func TestKanikoBuilder(t *testing.T) { t.Run("BuildSuccess", func(t *testing.T) { blCtx := "git://github.com/mojtaba-esk/sample-docker" - cacheOpts := &builder.CacheOptions{} - cacheOpts, err := cacheOpts.Default(blCtx) - require.NoError(t, err, "GetDefaultCacheOptions should succeed") - - buildOptions := &builder.BuilderOptions{ + buildOptions := builder.BuilderOptions{ ImageName: testImage, BuildContext: blCtx, - Destination: testDestination, Args: []builder.ArgInterface{&builder.BuildArg{Value: "SOME_ARG=some_value"}}, - Cache: cacheOpts, + Cache: kb.CacheOptions(), } var ( @@ -71,10 +66,9 @@ func TestKanikoBuilder(t *testing.T) { }) t.Run("BuildWithContextCancellation", func(t *testing.T) { - buildOptions := &builder.BuilderOptions{ + buildOptions := builder.BuilderOptions{ ImageName: testImage, BuildContext: "git://example.com/repo", - Destination: testDestination, } // Cancel the context to simulate cancellation during the build @@ -126,32 +120,3 @@ func createPodFromJob(job *batchv1.Job) *v1.Pod { }, } } - -func TestGetDefaultCacheOptions(t *testing.T) { - t.Parallel() - - tt := []struct { - buildContext string - expectedRepo string - expectedError bool - }{ - {"git://example.com/repo", "ttl.sh/fd46c51aa5aff87d0f8a329fc578ffcb3b43f8db8aff920d0d01429e15eb9850:24h", false}, - {"", "", true}, - } - - for _, tc := range tt { - t.Run(tc.buildContext, func(t *testing.T) { - cacheOptions := &builder.CacheOptions{} - cacheOptions, err := cacheOptions.Default(tc.buildContext) - - if tc.expectedError { - assert.Error(t, err, "Expected an error, but got none") - assert.Nil(t, cacheOptions, "Cache options should be nil on error") - } else { - assert.NoError(t, err, "Unexpected error") - assert.NotNil(t, cacheOptions, "Cache options should not be nil") - assert.Equal(t, tc.expectedRepo, cacheOptions.Repo, "Unexpected cache repo value") - } - }) - } -} diff --git a/pkg/builder/registry/ttl.sh.go b/pkg/builder/registry/ttl.sh.go new file mode 100644 index 0000000..411a4f0 --- /dev/null +++ b/pkg/builder/registry/ttl.sh.go @@ -0,0 +1,187 @@ +// Package registry provides a local registry for building images. +package registry + +import ( + "context" + "fmt" + "strings" + + "k8s.io/apimachinery/pkg/api/resource" + + "github.com/celestiaorg/knuu/pkg/cert" + "github.com/celestiaorg/knuu/pkg/instance" +) + +const ( + TtlShSecretName = "ttlsh-registry-certs" + TtlShInstanceName = "ttlsh-registry" + + ttlShDefaultImage = "mojiz/ttl.sh:dev" + ttlShDefaultPort = 5001 + ttlShConfigFile = "/knuu/config.yml" + ttlShStoragePath = "/var/lib/registry" + ttlShCertFilePath = "/knuu/certs/cert.pem" + ttlShKeyFilePath = "/knuu/certs/key.pem" + ttlShDefaultStorageSize = "10Gi" +) + +type TtlSh struct { + instance *instance.Instance + port int + cert []byte +} + +type TtlShOptions struct { + Port int + Image string + StorageSize resource.Quantity + LogLevel string +} + +func NewTtlSh(ctx context.Context, ins *instance.Instance, opts TtlShOptions) (*TtlSh, error) { + if opts.Image == "" { + opts.Image = ttlShDefaultImage + } + + if err := ins.Build().SetImage(ctx, opts.Image); err != nil { + return nil, err + } + + if err := ins.Build().Commit(ctx); err != nil { + return nil, err + } + + if opts.Port == 0 { + opts.Port = ttlShDefaultPort + } + + if err := ins.Network().AddPortTCP(opts.Port); err != nil { + return nil, err + } + + if opts.StorageSize.IsZero() { + opts.StorageSize = resource.MustParse(ttlShDefaultStorageSize) + } + + if err := ins.Storage().AddVolume(ttlShStoragePath, opts.StorageSize); err != nil { + return nil, err + } + + if opts.LogLevel == "" { + opts.LogLevel = ins.Logger.GetLevel().String() + } + + if err := ins.Storage().AddFileBytes( + generateTtlShConfig(opts), ttlShConfigFile, "0:0", + ); err != nil { + return nil, err + } + + if err := ins.Build().SetStartCommand("registry", "serve", ttlShConfigFile); err != nil { + return nil, err + } + + hostname := ins.Network().HostName() + certPEM, err := setupTLSForTtlSh(ctx, ins, hostname) + if err != nil { + return nil, err + } + + // TLS is enabled, so headless service does not work + ins.Network().SetHeadless(false) + + if err := ins.Execution().Start(ctx); err != nil { + return nil, err + } + + t := &TtlSh{ + instance: ins, + port: opts.Port, + cert: certPEM, + } + ins.Logger.Infof("TTL.sh local registry started at `%s`", t.GetAddress()) + + return t, nil +} + +func (t *TtlSh) Cert() []byte { + return t.cert +} + +func generateTtlShConfig(opts TtlShOptions) []byte { + // secret := uuid.New().String() // just a random secret + return []byte(fmt.Sprintf( + `version: 0.1 +log: + level: %s + +storage: + filesystem: + rootdirectory: %s + +http: + addr: 0.0.0.0:%d + tls: + certificate: %s + key: %s +`, + strings.ToLower(opts.LogLevel), + ttlShStoragePath, + opts.Port, + ttlShCertFilePath, + ttlShKeyFilePath, + )) + // return []byte(fmt.Sprintf( + // `version: 0.1 + // log: + // level: %s + + // storage: + // filesystem: + // rootdirectory: %s + + // http: + // + // addr: 0.0.0.0:%d + // secret: "%s" + // tls: + // certificate: %s + // key: %s + // host: "localhost:%d"`, + // strings.ToLower(opts.LogLevel), + // ttlShStoragePath, + // opts.Port, + // secret, + // ttlShCertFilePath, + // ttlShKeyFilePath, + // opts.Port, + // )) +} + +func setupTLSForTtlSh(ctx context.Context, ins *instance.Instance, hostname string) (certPEM []byte, err error) { + certPEM, keyPEM, err := cert.GenerateSelfSignedCert(hostname) + if err != nil { + return nil, err + } + + if err := ins.K8sClient.CreateTLSSecret(ctx, TtlShSecretName, certPEM, keyPEM); err != nil { + return nil, err + } + + if err := ins.Storage().AddFileBytes(certPEM, ttlShCertFilePath, "0:0"); err != nil { + return nil, err + } + + if err := ins.Storage().AddFileBytes(keyPEM, ttlShKeyFilePath, "0:0"); err != nil { + return nil, err + } + + return certPEM, nil +} + +func (t *TtlSh) GetAddress() string { + if t.instance == nil { + panic("TTL.sh instance is not initialized") + } + return fmt.Sprintf("%s:%d", t.instance.Network().HostName(), t.port) +} diff --git a/pkg/cert/cert.go b/pkg/cert/cert.go new file mode 100644 index 0000000..268d147 --- /dev/null +++ b/pkg/cert/cert.go @@ -0,0 +1,59 @@ +package cert + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "math/big" + "time" +) + +const ( + certValidityPeriod = 365 * 24 * time.Hour +) + +func GenerateSelfSignedCert(hostname string) (cert []byte, key []byte, err error) { + priv, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + if err != nil { + return nil, nil, err + } + + notBefore := time.Now() + notAfter := notBefore.Add(certValidityPeriod) + + serialNumber, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) + if err != nil { + return nil, nil, err + } + + template := x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{ + Organization: []string{"Dynamic Registry"}, + }, + NotBefore: notBefore, + NotAfter: notAfter, + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + DNSNames: []string{hostname}, + } + + certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) + if err != nil { + return nil, nil, err + } + + privBytes, err := x509.MarshalECPrivateKey(priv) + if err != nil { + return nil, nil, err + } + + certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER}) + keyPEM := pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: privBytes}) + + return certPEM, keyPEM, nil +} diff --git a/pkg/container/docker.go b/pkg/container/docker.go index c63cbc7..613e3e4 100644 --- a/pkg/container/docker.go +++ b/pkg/container/docker.go @@ -112,9 +112,8 @@ func (f *BuilderFactory) PushBuilderImage(ctx context.Context, imageName string) return ErrImageBuilderNotSet } - logs, err := f.imageBuilder.Build(ctx, &builder.BuilderOptions{ + logs, err := f.imageBuilder.Build(ctx, builder.BuilderOptions{ ImageName: f.imageNameTo, - Destination: f.imageNameTo, // in docker the image name and destination are the same BuildContext: builder.DirContext{Path: f.buildContext}.BuildContext(), Args: f.args, }) @@ -133,23 +132,16 @@ func (f *BuilderFactory) BuildImageFromGitRepo(ctx context.Context, gitCtx build f.imageNameTo = imageName - cOpts := &builder.CacheOptions{} - cOpts, err = cOpts.Default(buildCtx) - if err != nil { - return ErrFailedToGetDefaultCacheOptions.Wrap(err) - } - f.logger.Debugf("Building image %s from git repo %s", imageName, gitCtx.Repo) if f.imageBuilder == nil { return ErrImageBuilderNotSet } - logs, err := f.imageBuilder.Build(ctx, &builder.BuilderOptions{ + logs, err := f.imageBuilder.Build(ctx, builder.BuilderOptions{ ImageName: imageName, - Destination: imageName, BuildContext: buildCtx, - Cache: cOpts, + Cache: f.imageBuilder.CacheOptions(), Args: f.args, }) diff --git a/pkg/instance/build.go b/pkg/instance/build.go index aa1bb54..d09f14b 100644 --- a/pkg/instance/build.go +++ b/pkg/instance/build.go @@ -81,13 +81,15 @@ func (b *build) SetGitRepo(ctx context.Context, gitContext builder.GitContext, a if err != nil { return ErrGettingBuildContext.Wrap(err) } - imageName, err := builder.DefaultImageName(bCtx) + + resolvedImage, err := b.instance.ImageBuilder.ResolveImageName(bCtx) if err != nil { - return ErrGettingImageName.Wrap(err) + return err } + b.imageName = resolvedImage.ToString() factory, err := container.NewBuilderFactory(container.BuilderFactoryOptions{ - ImageName: imageName, + ImageName: b.imageName, BuildContext: b.getBuildDir(), ImageBuilder: b.instance.ImageBuilder, Args: args, @@ -97,10 +99,9 @@ func (b *build) SetGitRepo(ctx context.Context, gitContext builder.GitContext, a return ErrCreatingBuilder.Wrap(err) } b.builderFactory = factory - b.imageName = imageName b.instance.SetState(StatePreparing) - return b.builderFactory.BuildImageFromGitRepo(ctx, gitContext, imageName) + return b.builderFactory.BuildImageFromGitRepo(ctx, gitContext, b.imageName) } // SetStartCommand sets the command to run in the instance diff --git a/pkg/instance/execution.go b/pkg/instance/execution.go index f105834..a43ed00 100644 --- a/pkg/instance/execution.go +++ b/pkg/instance/execution.go @@ -7,6 +7,7 @@ import ( "time" "github.com/celestiaorg/knuu/pkg/k8s" + v1 "k8s.io/api/core/v1" "github.com/sirupsen/logrus" ) @@ -414,6 +415,7 @@ func (e *execution) prepareReplicaSetConfig() k8s.ReplicaSetConfig { FsGroup: e.instance.storage.fsGroup, ContainerConfig: containerConfig, SidecarConfigs: sidecarConfigs, + ImagePullSecrets: []v1.LocalObjectReference{{Name: "registry-cert-secret"}}, } return k8s.ReplicaSetConfig{ diff --git a/pkg/instance/network.go b/pkg/instance/network.go index 27503fd..e29a201 100644 --- a/pkg/instance/network.go +++ b/pkg/instance/network.go @@ -16,6 +16,7 @@ type network struct { portsTCP []int portsUDP []int kubernetesService *v1.Service + notHeadless bool } func (i *Instance) Network() *network { @@ -145,6 +146,10 @@ func (n *network) HostName() string { return n.instance.K8sClient.ServiceDNS(n.instance.name) } +func (n *network) SetHeadless(headless bool) { + n.notHeadless = !headless +} + // deployService deploys the service for the instance func (n *network) deployService(ctx context.Context, portsTCP, portsUDP []int) error { // a sidecar instance should use the parent instance's service @@ -162,6 +167,7 @@ func (n *network) deployService(ctx context.Context, portsTCP, portsUDP []int) e SelectorMap: labels, TCPPorts: portsTCP, UDPPorts: portsUDP, + NotHeadless: n.notHeadless, }) if err != nil { return ErrDeployingService.WithParams(n.instance.name).Wrap(err) @@ -191,6 +197,7 @@ func (n *network) patchService(ctx context.Context, portsTCP, portsUDP []int) er SelectorMap: labels, TCPPorts: portsTCP, UDPPorts: portsUDP, + NotHeadless: n.notHeadless, }) if err != nil { return ErrPatchingService.WithParams(serviceName).Wrap(err) diff --git a/pkg/k8s/pod.go b/pkg/k8s/pod.go index 0127d5d..f2dc23d 100644 --- a/pkg/k8s/pod.go +++ b/pkg/k8s/pod.go @@ -54,14 +54,15 @@ type ContainerConfig struct { } type PodConfig struct { - Namespace string // Kubernetes namespace of the Pod - Name string // Name to assign to the Pod - Labels map[string]string // Labels to apply to the Pod - ServiceAccountName string // ServiceAccount to assign to Pod - FsGroup int64 // FSGroup to apply to the Pod - ContainerConfig ContainerConfig // ContainerConfig for the Pod - SidecarConfigs []ContainerConfig // SideCarConfigs for the Pod - Annotations map[string]string // Annotations to apply to the Pod + Namespace string // Kubernetes namespace of the Pod + Name string // Name to assign to the Pod + Labels map[string]string // Labels to apply to the Pod + ServiceAccountName string // ServiceAccount to assign to Pod + FsGroup int64 // FSGroup to apply to the Pod + ContainerConfig ContainerConfig // ContainerConfig for the Pod + SidecarConfigs []ContainerConfig // SideCarConfigs for the Pod + Annotations map[string]string // Annotations to apply to the Pod + ImagePullSecrets []v1.LocalObjectReference // Image pull secrets for the container } type Volume struct { @@ -541,6 +542,27 @@ func prepareContainer(config ContainerConfig) v1.Container { // prepareInitContainers creates a slice of v1.Container as init containers. func (c *Client) prepareInitContainers(config ContainerConfig, init bool) []v1.Container { + if strings.HasPrefix(config.Name, "registry-build-from-git") { + if exists, err := c.ConfigMapExists(context.Background(), "ttlsh-registry-certs"); err == nil && exists { + return []v1.Container{ + { + Name: "init-container", + Image: "debian:bullseye-slim", + // SecurityContext: &v1.SecurityContext{ + // RunAsUser: ptr.To[int64](defaultContainerUser), + // }, + Command: []string{"sh", "-c", "apt-get update && apt-get install -y ca-certificates && cp /certs/cert.pem /usr/local/share/ca-certificates/registry-cert.crt && update-ca-certificates"}, + VolumeMounts: []v1.VolumeMount{ + { + Name: "cert-volume", + MountPath: "/certs", + }, + }, + }, + } + } + } + if !init || len(config.Volumes) == 0 { return nil } @@ -570,6 +592,22 @@ func (c *Client) preparePodSpec(spec PodConfig, init bool) v1.PodSpec { InitContainers: c.prepareInitContainers(spec.ContainerConfig, init), Containers: []v1.Container{prepareContainer(spec.ContainerConfig)}, Volumes: preparePodVolumes(spec.ContainerConfig), + // ImagePullSecrets: spec.ImagePullSecrets, + } + + // TODO: FIXME Remove this + if strings.HasPrefix(spec.Name, "registry-build-from-git") { + if exists, err := c.ConfigMapExists(context.Background(), "ttlsh-registry-certs"); err == nil && exists { + podSpec.Volumes = append(podSpec.Volumes, v1.Volume{ + Name: "cert-volume", + VolumeSource: v1.VolumeSource{ + ConfigMap: &v1.ConfigMapVolumeSource{ + LocalObjectReference: v1.LocalObjectReference{Name: "ttlsh-registry-certs"}, + DefaultMode: ptr.To[int32](defaultFileModeForVolume), + }, + }, + }) + } } // Prepare sidecar containers and append to the pod spec diff --git a/pkg/k8s/security.go b/pkg/k8s/security.go new file mode 100644 index 0000000..a888a40 --- /dev/null +++ b/pkg/k8s/security.go @@ -0,0 +1,25 @@ +package k8s + +import ( + "context" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func (c *Client) CreateTLSSecret(ctx context.Context, secretName string, cert, key []byte) error { + secret := &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: secretName, + Namespace: c.namespace, + }, + Data: map[string][]byte{ + "cert.pem": cert, + "key.pem": key, + }, + Type: v1.SecretTypeOpaque, + } + + _, err := c.clientset.CoreV1().Secrets(c.namespace).Create(ctx, secret, metav1.CreateOptions{}) + return err +} diff --git a/pkg/k8s/types.go b/pkg/k8s/types.go index 6e9cb0a..ae33b6a 100644 --- a/pkg/k8s/types.go +++ b/pkg/k8s/types.go @@ -32,6 +32,7 @@ type KubeManager interface { CreateService(ctx context.Context, name string, opts ServiceOptions) (*corev1.Service, error) CreateServiceAccount(ctx context.Context, name string, labels map[string]string) error CustomResourceDefinitionExists(ctx context.Context, gvr *schema.GroupVersionResource) (bool, error) + CreateTLSSecret(ctx context.Context, secretName string, cert, key []byte) error DaemonSetExists(ctx context.Context, name string) (bool, error) DeleteConfigMap(ctx context.Context, name string) error DeleteDaemonSet(ctx context.Context, name string) error diff --git a/pkg/knuu/errors.go b/pkg/knuu/errors.go index 99e4032..901c7a9 100644 --- a/pkg/knuu/errors.go +++ b/pkg/knuu/errors.go @@ -210,4 +210,5 @@ var ( ErrScopeMismatch = errors.New("ScopeMismatch", "scope '%s' set in options does not match scope '%s' set by the k8sClient namespace") ErrHandleTimeout = errors.New("HandleTimeout", "error starting handle timeout") ErrDeprecated = errors.New("Deprecated", "deprecated") + ErrCannotCreateLocalRegistry = errors.New("CannotCreateLocalRegistry", "cannot create local registry") ) diff --git a/pkg/knuu/knuu.go b/pkg/knuu/knuu.go index 2babcb0..49bdc8a 100644 --- a/pkg/knuu/knuu.go +++ b/pkg/knuu/knuu.go @@ -16,6 +16,7 @@ import ( "github.com/celestiaorg/knuu/pkg/builder" "github.com/celestiaorg/knuu/pkg/builder/kaniko" + "github.com/celestiaorg/knuu/pkg/builder/registry" "github.com/celestiaorg/knuu/pkg/instance" "github.com/celestiaorg/knuu/pkg/k8s" "github.com/celestiaorg/knuu/pkg/log" @@ -39,19 +40,21 @@ const ( type Knuu struct { *system.SystemDependencies - stopMu sync.Mutex - clusterDomain string + stopMu sync.Mutex + clusterDomain string + localRegistryEnabled bool } type Options struct { - K8sClient k8s.KubeManager - MinioClient *minio.Minio - ImageBuilder builder.Builder - Scope string - ProxyEnabled bool - Timeout time.Duration - Logger *logrus.Logger - ClusterDomain string // optional, if not set, "cluster.local" will be used + K8sClient k8s.KubeManager + MinioClient *minio.Minio + ImageBuilder builder.Builder + Scope string + ProxyEnabled bool + LocalRegistryEnabled bool // if true, a local registry will be deployed and docker images will be pushed to it + Timeout time.Duration + Logger *logrus.Logger + ClusterDomain string // optional, if not set, "cluster.local" will be used } func New(ctx context.Context, opts Options) (*Knuu, error) { @@ -68,7 +71,8 @@ func New(ctx context.Context, opts Options) (*Knuu, error) { Scope: opts.Scope, StartTime: time.Now().UTC().Format(TimeFormat), }, - clusterDomain: opts.ClusterDomain, + clusterDomain: opts.ClusterDomain, + localRegistryEnabled: opts.LocalRegistryEnabled, } if err := setDefaults(ctx, k); err != nil { @@ -171,6 +175,49 @@ func (k *Knuu) handleTimeout(ctx context.Context, timeout time.Duration, timeout return nil } +func (k *Knuu) setupDefaultImageBuilder(ctx context.Context) error { + if k.ImageBuilder != nil { + return nil + } + + if !k.localRegistryEnabled { + k.ImageBuilder = &kaniko.Kaniko{ + SystemDependencies: k.SystemDependencies, + } + return nil + } + + rgIns, err := k.NewInstance(registry.TtlShInstanceName) + if err != nil { + return ErrCannotCreateLocalRegistry.Wrap(err) + } + rg, err := registry.NewTtlSh(ctx, rgIns, registry.TtlShOptions{}) + if err != nil { + return ErrCannotCreateLocalRegistry.Wrap(err) + } + + _, err = k.K8sClient.CreateConfigMap(ctx, + "ttlsh-registry-certs", + nil, + map[string]string{ + "cert.pem": string(rg.Cert()), + }) + if err != nil { + return err + } + + k.ImageBuilder = &kaniko.Kaniko{ + SystemDependencies: k.SystemDependencies, + Registry: &kaniko.RegistryOptions{ + Address: rg.GetAddress(), + Cert: rg.Cert(), + SecretName: registry.TtlShSecretName, + }, + } + + return nil +} + func DefaultScope() string { t := time.Now() return fmt.Sprintf("%s-%03d", t.Format("20060102-150405"), t.Nanosecond()/1e6) @@ -217,10 +264,8 @@ func setDefaults(ctx context.Context, k *Knuu) error { } } - if k.ImageBuilder == nil { - k.ImageBuilder = &kaniko.Kaniko{ - SystemDependencies: k.SystemDependencies, - } + if err := k.setupDefaultImageBuilder(ctx); err != nil { + return err } return nil