mirror of
https://github.com/labring/sealos.git
synced 2026-09-01 15:38:06 +08:00
feat(image-cri-shim): implement synchronization of image-cri-shim config from ConfigMap (#6091)
* feat(configmap): enhance logging for image-cri-shim config synchronization Signed-off-by: cuisongliu <cuisongliu@qq.com> * feat(configmap): refactor kube client creation and add tests for config synchronization Signed-off-by: cuisongliu <cuisongliu@qq.com> * feat(configmap): add test for syncing registry config from ConfigMap Signed-off-by: cuisongliu <cuisongliu@qq.com> * chore: add license header to configmap_sync.go and configmap_sync_test.go; log shim config in image_cri_shim_test.go Signed-off-by: cuisongliu <cuisongliu@qq.com> * refactor(configmap): remove redundant warning log for no updates in image-cri-shim config Signed-off-by: cuisongliu <cuisongliu@qq.com> * refactor(configmap): reduce wait time for shim log checks in tests Signed-off-by: cuisongliu <cuisongliu@qq.com> * refactor(configmap): remove duplicate import of sigs.k8s.io/yaml Signed-off-by: cuisongliu <cuisongliu@qq.com> --------- Signed-off-by: cuisongliu <cuisongliu@qq.com>
This commit is contained in:
@@ -50,6 +50,7 @@ var rootCmd = &cobra.Command{
|
||||
},
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
var err error
|
||||
types.SyncConfigFromConfigMap(cmd.Context(), cfgFile)
|
||||
cfg, err = types.Unmarshal(cfgFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("image shim config load error: %w", err)
|
||||
@@ -126,6 +127,7 @@ func watchAuthConfig(ctx context.Context, path string, imgShim shim.Shim, interv
|
||||
}
|
||||
|
||||
lastHash := ""
|
||||
types.SyncConfigFromConfigMap(ctx, path)
|
||||
if data, err := os.ReadFile(path); err == nil {
|
||||
if _, err := types.UnmarshalData(data); err == nil {
|
||||
sum := sha256.Sum256(data)
|
||||
@@ -145,6 +147,7 @@ func watchAuthConfig(ctx context.Context, path string, imgShim shim.Shim, interv
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
case <-ticker.C:
|
||||
types.SyncConfigFromConfigMap(ctx, path)
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
logger.Warn("failed to read shim config %s: %v", path, err)
|
||||
|
||||
@@ -11,7 +11,9 @@ require (
|
||||
github.com/labring/sreg v0.1.7-rc3.0.20250728082818-441302dcb159
|
||||
github.com/pelletier/go-toml v1.9.5
|
||||
google.golang.org/grpc v1.58.3
|
||||
k8s.io/api v0.30.3
|
||||
k8s.io/apimachinery v0.30.3
|
||||
k8s.io/client-go v0.30.3
|
||||
k8s.io/cri-api v0.30.3
|
||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
|
||||
sigs.k8s.io/yaml v1.4.0
|
||||
@@ -22,43 +24,61 @@ require (
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
|
||||
github.com/containers/image/v5 v5.25.1-0.20230605120906-abe51339f34d // indirect
|
||||
github.com/containers/storage v1.50.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/docker/cli v25.0.1+incompatible // indirect
|
||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.7.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||
github.com/go-logr/logr v1.4.1 // 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
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
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/klauspost/compress v1.16.7 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/moby/sys/mountinfo v0.6.2 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.1-0.20220411205349-bde1400a84be // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc6 // indirect
|
||||
github.com/opencontainers/runc v1.1.12 // indirect
|
||||
github.com/opencontainers/runtime-spec v1.1.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
|
||||
github.com/vbatts/tar-split v0.11.5 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.26.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
|
||||
golang.org/x/net v0.25.0 // indirect
|
||||
golang.org/x/oauth2 v0.10.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/sys v0.22.0 // indirect
|
||||
golang.org/x/term v0.22.0 // indirect
|
||||
golang.org/x/text v0.16.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.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
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||
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/hcsshim v0.12.0-rc.0 h1:wX/F5huJxH9APBkhKSEAqaiZsuBvbbDnyBROZAqsSaY=
|
||||
@@ -29,6 +33,7 @@ github.com/containers/ocicrypt v1.1.7 h1:thhNr4fu2ltyGz8aMx8u48Ae0Pnbip3ePP9/mzk
|
||||
github.com/containers/ocicrypt v1.1.7/go.mod h1:7CAhjcj2H8AYp5YvEie7oVSK2AhBY8NscCYRawuDNtw=
|
||||
github.com/containers/storage v1.50.2 h1:Fys4BjFUVNRBEXlO70hFI48VW4EXsgnGisTpk9tTMsE=
|
||||
github.com/containers/storage v1.50.2/go.mod h1:dpspZsUrcKD8SpTofvKWhwPDHD0MkO4Q7VE+oYdWkiA=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyberphone/json-canonicalization v0.0.0-20230514072755-504adb8a8af1 h1:8Pq5UNTC+/UfvcOPKQGZoKCkeF+ZaKa4wJ9OS2gsQQM=
|
||||
github.com/cyberphone/json-canonicalization v0.0.0-20230514072755-504adb8a8af1/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||
@@ -50,6 +55,8 @@ github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj
|
||||
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
||||
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/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
|
||||
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
|
||||
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||
@@ -76,12 +83,17 @@ github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/
|
||||
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU=
|
||||
github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg=
|
||||
github.com/go-task/slim-sprig v2.20.0+incompatible h1:4Xh3bDzO29j4TWNOI+24ubc0vbVFMg2PMnXKxK54/CA=
|
||||
github.com/go-task/slim-sprig v2.20.0+incompatible/go.mod h1:N/mhXZITr/EQAOErEHciKvO1bFei2Lld2Ym6h96pdy0=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
||||
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
|
||||
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/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
@@ -92,6 +104,8 @@ github.com/google/go-intervals v0.0.2/go.mod h1:MkaR3LNRfeKLPmqgJYs4E66z5InYjmCj
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
@@ -101,6 +115,8 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
|
||||
github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
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=
|
||||
@@ -113,8 +129,11 @@ github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGC
|
||||
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
|
||||
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
github.com/kr/pretty v0.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=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/labring/sreg v0.1.7-rc3.0.20250728082818-441302dcb159 h1:3i6hMYgfdrcsi9uOiSs17iUfaiznByX7vwk2bzJhKy4=
|
||||
@@ -142,8 +161,14 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
||||
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/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/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
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.1-0.20220411205349-bde1400a84be h1:f2PlhC9pm5sqpBZFvnAoKj+KzXRzbjFMA+TqXfJdgho=
|
||||
github.com/opencontainers/go-digest v1.0.1-0.20220411205349-bde1400a84be/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc6 h1:XDqvyKsJEbRtATzkgItUqBA7QHk58yxX1Ov9HERHNqU=
|
||||
@@ -181,8 +206,13 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
|
||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 h1:lIOOHPEbXzO3vnmx2gok1Tfs31Q8GQqKLc8vVqyQq/I=
|
||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.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=
|
||||
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.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/sylabs/sif/v2 v2.11.4 h1:4dRvsRFVkyS7e8oD8AEL0HrJocnet05+EFW+DhVb/Ic=
|
||||
@@ -237,11 +267,14 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
|
||||
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
|
||||
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=
|
||||
@@ -257,9 +290,12 @@ golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
|
||||
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
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.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
@@ -270,6 +306,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
|
||||
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=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
|
||||
google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ=
|
||||
@@ -296,12 +334,18 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||
gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY=
|
||||
gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
||||
k8s.io/api v0.30.3 h1:ImHwK9DCsPA9uoU3rVh4QHAHHK5dTSv1nxJUapx8hoQ=
|
||||
k8s.io/api v0.30.3/go.mod h1:GPc8jlzoe5JG3pb0KJCSLX5oAFIW3/qNJITlDj8BH04=
|
||||
k8s.io/apimachinery v0.30.3 h1:q1laaWCmrszyQuSQCfNB8cFgCuDAoPszKY4ucAjDwHc=
|
||||
k8s.io/apimachinery v0.30.3/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
|
||||
k8s.io/client-go v0.30.3 h1:bHrJu3xQZNXIi8/MoxYtZBBWQQXwy16zqJwloXXfD3k=
|
||||
k8s.io/client-go v0.30.3/go.mod h1:8d4pf8vYu665/kUbsxWAQ/JDBNWqfFeZnvFiVdmx89U=
|
||||
k8s.io/cri-api v0.30.3 h1:o7AAGb3645Ik44WkHI0eqUc7JbQVmstlINLlLAtU/rI=
|
||||
k8s.io/cri-api v0.30.3/go.mod h1://4/umPJSW1ISNSNng4OwjpkvswJOQwU8rnkvO8P+xg=
|
||||
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
|
||||
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
|
||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
|
||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
|
||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
// Copyright © 2025 sealos.
|
||||
//
|
||||
// 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 types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
fileutil "github.com/labring/sealos/pkg/utils/file"
|
||||
"github.com/labring/sealos/pkg/utils/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
shimConfigMapNamespace = "kube-system"
|
||||
shimConfigMapName = "image-cri-shim"
|
||||
shimConfigMapDataKey = "registries.yaml"
|
||||
)
|
||||
|
||||
var kubeClientFactory = buildKubeClient
|
||||
|
||||
type registryConfigSpec struct {
|
||||
Version string `yaml:"version"`
|
||||
Sealos sealedConfig `yaml:"sealos"`
|
||||
Registries []registryEntry `yaml:"registries"`
|
||||
ReloadInterval string `yaml:"reloadInterval"`
|
||||
Force *bool `yaml:"force"`
|
||||
Debug *bool `yaml:"debug"`
|
||||
Timeout string `yaml:"timeout"`
|
||||
}
|
||||
|
||||
type sealedConfig struct {
|
||||
Address string `yaml:"address"`
|
||||
Auth registryAuth `yaml:"auth"`
|
||||
}
|
||||
|
||||
type registryEntry struct {
|
||||
Address string `yaml:"address"`
|
||||
Auth registryAuth `yaml:"auth"`
|
||||
}
|
||||
|
||||
type registryAuth struct {
|
||||
Username string `yaml:"username"`
|
||||
Password string `yaml:"password"`
|
||||
}
|
||||
|
||||
// SyncConfigFromConfigMap reads the kube-system/image-cri-shim ConfigMap and, when available,
|
||||
// synchronizes the registries.yaml content into the local shim configuration file. If the cluster
|
||||
// or ConfigMap cannot be reached, the function simply skips the update.
|
||||
func SyncConfigFromConfigMap(ctx context.Context, configPath string) {
|
||||
if strings.TrimSpace(configPath) == "" {
|
||||
return
|
||||
}
|
||||
client, err := kubeClientFactory()
|
||||
if err != nil {
|
||||
logger.Debug("skip syncing image-cri-shim config; unable to create kube client: %v", err)
|
||||
logger.Warn("you can ignore this if you are not running inside a kubernetes cluster")
|
||||
return
|
||||
}
|
||||
cm, err := client.CoreV1().ConfigMaps(shimConfigMapNamespace).Get(ctx, shimConfigMapName, metav1.GetOptions{})
|
||||
if apierrors.IsNotFound(err) {
|
||||
logger.Debug("configmap %s/%s not found; skip syncing", shimConfigMapNamespace, shimConfigMapName)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
logger.Debug("failed to read ConfigMap %s/%s: %v", shimConfigMapNamespace, shimConfigMapName, err)
|
||||
return
|
||||
}
|
||||
if !applyConfigMapToFile(configPath, cm) {
|
||||
logger.Debug("ConfigMap %s/%s produced no updates", shimConfigMapNamespace, shimConfigMapName)
|
||||
return
|
||||
}
|
||||
logger.Info("syncing image-cri-shim config from ConfigMap completed")
|
||||
}
|
||||
|
||||
func buildKubeClient() (kubernetes.Interface, error) {
|
||||
if cfg, err := rest.InClusterConfig(); err == nil {
|
||||
return kubernetes.NewForConfig(cfg)
|
||||
}
|
||||
kubeconfigCandidates := []string{}
|
||||
if env := os.Getenv("KUBECONFIG"); env != "" {
|
||||
kubeconfigCandidates = append(kubeconfigCandidates, env)
|
||||
}
|
||||
kubeconfigCandidates = append(kubeconfigCandidates,
|
||||
"/etc/kubernetes/admin.conf",
|
||||
"/etc/rancher/k3s/k3s.yaml",
|
||||
filepath.Join(os.Getenv("HOME"), ".kube", "config"),
|
||||
)
|
||||
for _, path := range kubeconfigCandidates {
|
||||
if path == "" {
|
||||
continue
|
||||
}
|
||||
if !fileutil.IsExist(path) {
|
||||
continue
|
||||
}
|
||||
cfg, err := clientcmd.BuildConfigFromFlags("", path)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
return kubernetes.NewForConfig(cfg)
|
||||
}
|
||||
rules := clientcmd.NewDefaultClientConfigLoadingRules()
|
||||
cfg, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(rules, &clientcmd.ConfigOverrides{}).ClientConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return kubernetes.NewForConfig(cfg)
|
||||
}
|
||||
|
||||
func applyConfigMapToFile(configPath string, cm *corev1.ConfigMap) bool {
|
||||
raw, ok := cm.Data[shimConfigMapDataKey]
|
||||
if !ok || strings.TrimSpace(raw) == "" {
|
||||
logger.Debug("ConfigMap %s/%s does not contain key %s; skip syncing", shimConfigMapNamespace, shimConfigMapName, shimConfigMapDataKey)
|
||||
return false
|
||||
}
|
||||
spec := new(registryConfigSpec)
|
||||
if err := yaml.Unmarshal([]byte(raw), spec); err != nil {
|
||||
logger.Warn("failed to parse image-cri-shim ConfigMap: %v", err)
|
||||
return false
|
||||
}
|
||||
cfg, err := Unmarshal(configPath)
|
||||
if err != nil {
|
||||
logger.Debug("failed to read local config %s: %v; using defaults", configPath, err)
|
||||
cfg = &Config{ImageShimSocket: SealosShimSock}
|
||||
}
|
||||
original, _ := yaml.Marshal(cfg)
|
||||
mergeShimConfig(cfg, spec)
|
||||
updated, err := yaml.Marshal(cfg)
|
||||
if err != nil {
|
||||
logger.Warn("failed to marshal image-cri-shim config: %v", err)
|
||||
return false
|
||||
}
|
||||
if bytes.Equal(bytes.TrimSpace(original), bytes.TrimSpace(updated)) {
|
||||
return false
|
||||
}
|
||||
if err := os.WriteFile(configPath, updated, 0o600); err != nil {
|
||||
logger.Warn("failed to write image-cri-shim config file: %v", err)
|
||||
return false
|
||||
}
|
||||
logger.Info("synced image-cri-shim config from ConfigMap into %s", configPath)
|
||||
return true
|
||||
}
|
||||
|
||||
func mergeShimConfig(cfg *Config, spec *registryConfigSpec) {
|
||||
if cfg == nil || spec == nil {
|
||||
return
|
||||
}
|
||||
if addr := strings.TrimSpace(spec.Sealos.Address); addr != "" {
|
||||
cfg.Address = addr
|
||||
}
|
||||
username := strings.TrimSpace(spec.Sealos.Auth.Username)
|
||||
password := strings.TrimSpace(spec.Sealos.Auth.Password)
|
||||
if username != "" || password != "" {
|
||||
cfg.Auth = buildAuth(username, password)
|
||||
}
|
||||
registries := make([]Registry, 0)
|
||||
for _, item := range spec.Registries {
|
||||
addr := strings.TrimSpace(item.Address)
|
||||
if addr == "" {
|
||||
continue
|
||||
}
|
||||
reg := Registry{Address: addr}
|
||||
user := strings.TrimSpace(item.Auth.Username)
|
||||
pass := strings.TrimSpace(item.Auth.Password)
|
||||
if user != "" || pass != "" {
|
||||
reg.Auth = buildAuth(user, pass)
|
||||
}
|
||||
registries = append(registries, reg)
|
||||
}
|
||||
cfg.Registries = registries
|
||||
if spec.Force != nil {
|
||||
cfg.Force = *spec.Force
|
||||
}
|
||||
if spec.Debug != nil {
|
||||
cfg.Debug = *spec.Debug
|
||||
}
|
||||
if d := strings.TrimSpace(spec.Timeout); d != "" {
|
||||
if dur, err := time.ParseDuration(d); err != nil {
|
||||
logger.Warn("failed to parse timeout %q: %v", d, err)
|
||||
} else {
|
||||
cfg.Timeout.Duration = dur
|
||||
}
|
||||
}
|
||||
if spec.ReloadInterval != "" {
|
||||
if dur, err := time.ParseDuration(spec.ReloadInterval); err != nil {
|
||||
logger.Warn("failed to parse reloadInterval %q: %v", spec.ReloadInterval, err)
|
||||
} else {
|
||||
cfg.ReloadInterval.Duration = dur
|
||||
}
|
||||
} else {
|
||||
cfg.ReloadInterval.Duration = DefaultReloadInterval
|
||||
}
|
||||
if cfg.Timeout.Duration <= 0 {
|
||||
cfg.Timeout.Duration, _ = time.ParseDuration("15m")
|
||||
}
|
||||
if cfg.ReloadInterval.Duration <= 0 {
|
||||
cfg.ReloadInterval.Duration = DefaultReloadInterval
|
||||
}
|
||||
}
|
||||
|
||||
func buildAuth(username, password string) string {
|
||||
user := strings.TrimSpace(username)
|
||||
pass := strings.TrimSpace(password)
|
||||
if user == "" && pass == "" {
|
||||
return ""
|
||||
}
|
||||
return user + ":" + pass
|
||||
}
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
// Copyright © 2025 sealos.
|
||||
//
|
||||
// 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 types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
const sampleConfigMapData = `version: v1
|
||||
sealos:
|
||||
address: "http://sealos.hub.local:5000"
|
||||
auth:
|
||||
username: "1"
|
||||
password: "2"
|
||||
registries:
|
||||
- address: "https://registry-1.docker.io"
|
||||
auth:
|
||||
username: "3"
|
||||
password: "4"
|
||||
reloadInterval: 5s
|
||||
`
|
||||
|
||||
func TestMergeShimConfig(t *testing.T) {
|
||||
cfg := &Config{}
|
||||
spec := new(registryConfigSpec)
|
||||
if err := yaml.Unmarshal([]byte(sampleConfigMapData), spec); err != nil {
|
||||
t.Fatalf("failed to unmarshal sample config: %v", err)
|
||||
}
|
||||
mergeShimConfig(cfg, spec)
|
||||
|
||||
if cfg.Address != "http://sealos.hub.local:5000" {
|
||||
t.Fatalf("unexpected address: %s", cfg.Address)
|
||||
}
|
||||
if cfg.Auth != "1:2" {
|
||||
t.Fatalf("unexpected auth: %s", cfg.Auth)
|
||||
}
|
||||
if len(cfg.Registries) != 1 {
|
||||
t.Fatalf("expected 1 registry, got %d", len(cfg.Registries))
|
||||
}
|
||||
if entry := cfg.Registries[0]; entry.Address != "https://registry-1.docker.io" || entry.Auth != "3:4" {
|
||||
t.Fatalf("unexpected registry entry: %+v", entry)
|
||||
}
|
||||
if cfg.ReloadInterval.Duration != 5*time.Second {
|
||||
t.Fatalf("expected reload interval 5s, got %s", cfg.ReloadInterval.Duration)
|
||||
}
|
||||
if cfg.Timeout.Duration <= 0 {
|
||||
t.Fatalf("expected timeout to be set, got %s", cfg.Timeout.Duration)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergeShimConfigKeepsDefaults(t *testing.T) {
|
||||
cfg := &Config{Address: "keep", Auth: "keep"}
|
||||
spec := ®istryConfigSpec{}
|
||||
mergeShimConfig(cfg, spec)
|
||||
if cfg.Address != "keep" {
|
||||
t.Fatalf("expected address to stay unchanged")
|
||||
}
|
||||
if cfg.Auth != "keep" {
|
||||
t.Fatalf("expected auth to stay unchanged")
|
||||
}
|
||||
if cfg.ReloadInterval.Duration != DefaultReloadInterval {
|
||||
t.Fatalf("expected default reload interval, got %s", cfg.ReloadInterval.Duration)
|
||||
}
|
||||
if cfg.Timeout.Duration <= 0 {
|
||||
t.Fatalf("expected default timeout, got %s", cfg.Timeout.Duration)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSyncConfigFromConfigMapWritesFile(t *testing.T) {
|
||||
cfg := &corev1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: shimConfigMapName, Namespace: shimConfigMapNamespace},
|
||||
Data: map[string]string{shimConfigMapDataKey: sampleConfigMapData},
|
||||
}
|
||||
tmpDir := t.TempDir()
|
||||
configPath := filepath.Join(tmpDir, "image-cri-shim.yaml")
|
||||
initial := []byte("shim: /var/run/image-cri-shim.sock\ncri: /run/containerd/containerd.sock\n")
|
||||
if err := os.WriteFile(configPath, initial, 0o600); err != nil {
|
||||
t.Fatalf("failed to seed config file: %v", err)
|
||||
}
|
||||
|
||||
originalFactory := kubeClientFactory
|
||||
kubeClientFactory = func() (kubernetes.Interface, error) {
|
||||
return fake.NewSimpleClientset(cfg), nil
|
||||
}
|
||||
t.Cleanup(func() { kubeClientFactory = originalFactory })
|
||||
|
||||
SyncConfigFromConfigMap(context.Background(), configPath)
|
||||
|
||||
merged, err := Unmarshal(configPath)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read merged config: %v", err)
|
||||
}
|
||||
if merged.Address != "http://sealos.hub.local:5000" {
|
||||
t.Fatalf("unexpected address: %s", merged.Address)
|
||||
}
|
||||
if merged.Auth != "1:2" {
|
||||
t.Fatalf("unexpected auth: %s", merged.Auth)
|
||||
}
|
||||
if len(merged.Registries) != 1 || merged.Registries[0].Address != "https://registry-1.docker.io" {
|
||||
t.Fatalf("unexpected registries: %+v", merged.Registries)
|
||||
}
|
||||
if merged.ReloadInterval.Duration != 5*time.Second {
|
||||
t.Fatalf("unexpected reload interval: %s", merged.ReloadInterval.Duration)
|
||||
}
|
||||
if merged.Timeout.Duration != 15*time.Minute {
|
||||
t.Fatalf("unexpected timeout: %s", merged.Timeout.Duration)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSyncConfigFromConfigMapMissingData(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
configPath := filepath.Join(tmpDir, "image-cri-shim.yaml")
|
||||
initial := []byte("shim: /var/run/image-cri-shim.sock\n")
|
||||
if err := os.WriteFile(configPath, initial, 0o600); err != nil {
|
||||
t.Fatalf("failed to seed config file: %v", err)
|
||||
}
|
||||
|
||||
originalFactory := kubeClientFactory
|
||||
kubeClientFactory = func() (kubernetes.Interface, error) {
|
||||
return fake.NewSimpleClientset(), nil
|
||||
}
|
||||
t.Cleanup(func() { kubeClientFactory = originalFactory })
|
||||
|
||||
SyncConfigFromConfigMap(context.Background(), configPath)
|
||||
|
||||
data, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read config file: %v", err)
|
||||
}
|
||||
if string(data) != string(initial) {
|
||||
t.Fatalf("expected config file to remain unchanged")
|
||||
}
|
||||
}
|
||||
@@ -229,6 +229,70 @@ COPY image-cri-shim cri`
|
||||
ginkgo.Context("image-cri-shim registry rewrite", func() {
|
||||
ginkgo.BeforeEach(ensureShimClient)
|
||||
|
||||
ginkgo.It("syncs registry config from ConfigMap", func() {
|
||||
const (
|
||||
sourceImage = "nginx:latest"
|
||||
rewrittenImage = "docker.m.daocloud.io/library/nginx:latest"
|
||||
mirrorAddress = "https://docker.m.daocloud.io"
|
||||
)
|
||||
|
||||
shimConfigRaw := utils.GetFileDataLocally(DefaultImageCRIShimConfig)
|
||||
defer func() {
|
||||
restoreSince := time.Now()
|
||||
writeShimConfig([]byte(shimConfigRaw))
|
||||
waitForShimLog("reloaded shim auth configuration", restoreSince, 60*time.Second)
|
||||
}()
|
||||
|
||||
_, _ = fakeClient.CmdInterface.Exec("kubectl", "-n", "kube-system", "delete", "configmap", "image-cri-shim", "--ignore-not-found=true")
|
||||
|
||||
configMapManifest := fmt.Sprintf(`apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: image-cri-shim
|
||||
namespace: kube-system
|
||||
data:
|
||||
registries.yaml: |
|
||||
version: v1
|
||||
reloadInterval: 2s
|
||||
registries:
|
||||
- address: %s
|
||||
`, mirrorAddress)
|
||||
|
||||
configMapFile := utils.CreateTempFile()
|
||||
defer func() {
|
||||
utils.RemoveTempFile(configMapFile)
|
||||
}()
|
||||
utils.CheckErr(utils.WriteFile(configMapFile, []byte(configMapManifest)), "failed to write ConfigMap manifest")
|
||||
|
||||
_, err := fakeClient.CmdInterface.Exec("kubectl", "apply", "-f", configMapFile)
|
||||
utils.CheckErr(err, "failed to apply image-cri-shim ConfigMap")
|
||||
|
||||
gomega.Eventually(func() string {
|
||||
out, err := exec.RunSimpleCmd(fmt.Sprintf("sudo cat %s", DefaultImageCRIShimConfig))
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return out
|
||||
}, 90*time.Second, 3*time.Second).Should(gomega.ContainSubstring(mirrorAddress))
|
||||
|
||||
gomega.Eventually(func() string {
|
||||
out, err := exec.RunSimpleCmd(fmt.Sprintf("sudo cat %s", DefaultImageCRIShimConfig))
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return out
|
||||
}, 90*time.Second, 3*time.Second).Should(gomega.ContainSubstring("reloadInterval: 2s"))
|
||||
|
||||
_, _ = fakeClient.CmdInterface.Exec("crictl", "rmi", sourceImage)
|
||||
_, _ = fakeClient.CmdInterface.Exec("crictl", "rmi", rewrittenImage)
|
||||
|
||||
pullOut, err := fakeClient.CmdInterface.Exec("crictl", "pull", sourceImage)
|
||||
utils.CheckErr(err, fmt.Sprintf("failed to pull %s: %v", sourceImage, err))
|
||||
logger.Info("crictl pull output: %s", string(pullOut))
|
||||
_, err = fakeClient.CmdInterface.Exec("crictl", "inspecti", rewrittenImage)
|
||||
utils.CheckErr(err, fmt.Sprintf("rewritten image %s not found in cri store", rewrittenImage))
|
||||
})
|
||||
|
||||
ginkgo.It("allows pulling through registry mirror", func() {
|
||||
const (
|
||||
sourceImage = "nginx:latest"
|
||||
@@ -237,6 +301,7 @@ COPY image-cri-shim cri`
|
||||
)
|
||||
|
||||
shimConfigRaw := utils.GetFileDataLocally(DefaultImageCRIShimConfig)
|
||||
logger.Warn(shimConfigRaw)
|
||||
cfg, err := shimType.UnmarshalData([]byte(shimConfigRaw))
|
||||
utils.CheckErr(err, "failed to unmarshal original shim config")
|
||||
|
||||
@@ -252,19 +317,13 @@ COPY image-cri-shim cri`
|
||||
waitForShimLog("reloaded shim auth configuration", restoreSince, 60*time.Second)
|
||||
}(shimConfigRaw)
|
||||
|
||||
since := time.Now()
|
||||
writeShimConfig(payload)
|
||||
waitForShimLog("reloaded shim auth configuration", since, 60*time.Second)
|
||||
|
||||
_, _ = fakeClient.CmdInterface.Exec("crictl", "rmi", sourceImage)
|
||||
_, _ = fakeClient.CmdInterface.Exec("crictl", "rmi", rewrittenImage)
|
||||
|
||||
pullOut, err := fakeClient.CmdInterface.Exec("crictl", "pull", sourceImage)
|
||||
utils.CheckErr(err, fmt.Sprintf("failed to pull %s: %v", sourceImage, err))
|
||||
logger.Info("crictl pull output: %s", string(pullOut))
|
||||
|
||||
waitForShimLog(fmt.Sprintf("image: %s, newImage: %s, action: PullImage", sourceImage, rewrittenImage), since, 60*time.Second)
|
||||
|
||||
_, err = fakeClient.CmdInterface.Exec("crictl", "inspecti", rewrittenImage)
|
||||
utils.CheckErr(err, fmt.Sprintf("rewritten image %s not found in cri store", rewrittenImage))
|
||||
})
|
||||
@@ -281,7 +340,7 @@ func writeShimConfig(data []byte) {
|
||||
|
||||
func waitForShimLog(fragment string, since time.Time, timeout time.Duration) {
|
||||
gomega.Eventually(func() string {
|
||||
cmd := fmt.Sprintf("sudo journalctl -u image-cri-shim --since \"%s\" --no-pager", since.Add(-5*time.Second).Format(shimJournalTimeLayout))
|
||||
cmd := fmt.Sprintf("sudo journalctl -u image-cri-shim --since \"%s\" --no-pager", since.Add(-60*time.Second).Format(shimJournalTimeLayout))
|
||||
out, err := exec.RunSimpleCmd(cmd)
|
||||
if err != nil {
|
||||
return ""
|
||||
|
||||
Reference in New Issue
Block a user