diff --git a/build/docker/tools/tke-installer/init_installer.sh b/build/docker/tools/tke-installer/init_installer.sh index d720eb040..9a137a554 100755 --- a/build/docker/tools/tke-installer/init_installer.sh +++ b/build/docker/tools/tke-installer/init_installer.sh @@ -49,7 +49,7 @@ tailNum=$((tailNum +1)) tail -n +${tailNum} "${me}" >package.tgz || die tar -zxf package.tgz || die -./install.sh || die +./install.sh $@ || die cd "${cwd}" || die exit 0 diff --git a/build/docker/tools/tke-installer/install.sh b/build/docker/tools/tke-installer/install.sh index 1b7695dc9..1d9f24dd3 100755 --- a/build/docker/tools/tke-installer/install.sh +++ b/build/docker/tools/tke-installer/install.sh @@ -142,7 +142,7 @@ function clean_old_data() { function start_installer() { echo "Step.5 start tke-installer [doing]" - docker run $OPTIONS "tkestack/tke-installer-${ARCH}:$VERSION" + docker run $OPTIONS "tkestack/tke-installer-${ARCH}:$VERSION" $@ echo "Step.5 start tke-installer [ok]" } diff --git a/cmd/tke-installer/app/config/config.go b/cmd/tke-installer/app/config/config.go index f62dd8a59..ec121643b 100644 --- a/cmd/tke-installer/app/config/config.go +++ b/cmd/tke-installer/app/config/config.go @@ -33,6 +33,12 @@ type Config struct { Force bool SyncProjectsWithNamespaces bool Replicas int + Upgrade bool + Kubeconfig string + RegistryUsername string + RegistryPassword string + RegistryDomain string + RegistryNamespace string } // CreateConfigFromOptions creates a running configuration instance based @@ -48,5 +54,11 @@ func CreateConfigFromOptions(serverName string, opts *options.Options) (*Config, Force: *opts.Force, SyncProjectsWithNamespaces: *opts.SyncProjectsWithNamespaces, Replicas: *opts.Replicas, + Upgrade: *opts.Upgrade, + Kubeconfig: *opts.Kubeconfig, + RegistryUsername: *opts.RegistryUsername, + RegistryPassword: *opts.RegistryPassword, + RegistryDomain: *opts.RegistryDomain, + RegistryNamespace: *opts.RegistryNamespace, }, nil } diff --git a/cmd/tke-installer/app/installer/installer.go b/cmd/tke-installer/app/installer/installer.go index 413c9e8b7..5f8b6ff97 100644 --- a/cmd/tke-installer/app/installer/installer.go +++ b/cmd/tke-installer/app/installer/installer.go @@ -141,14 +141,8 @@ func New(config *config.Config) *TKE { c.docker.Stderr = c.log if !config.Force { - data, err := ioutil.ReadFile(constants.ClusterFile) + err = c.loadTKEData() if err == nil { - log.Infof("read %q success", constants.ClusterFile) - err = json.Unmarshal(data, c) - if err != nil { - log.Warnf("load tke data error:%s", err) - } - log.Infof("load tke data success") c.isFromRestore = true c.progress.Status = types.StatusDoing } @@ -157,6 +151,20 @@ func New(config *config.Config) *TKE { return c } +func (t *TKE) loadTKEData() error { + data, err := ioutil.ReadFile(constants.ClusterFile) + if err == nil { + t.log.Infof("read %q success", constants.ClusterFile) + err = json.Unmarshal(data, t) + if err != nil { + t.log.Infof("load tke data error:%s", err) + } else { + log.Infof("load tke data success") + } + } + return err +} + func (t *TKE) initSteps() { t.steps = append(t.steps, []types.Handler{ { @@ -208,8 +216,8 @@ func (t *TKE) initSteps() { Func: t.createGlobalCluster, }, { - Name: "Patch k8s version in cluster info", - Func: t.patchK8sValidVersions, + Name: "Patch platform versions in cluster info", + Func: t.patchPlatformVersion, }, { Name: "Write kubeconfig", @@ -464,6 +472,15 @@ func (t *TKE) runWithUI() error { restful.Filter(globalLogging) + if t.Config.Upgrade { + err := t.prepareForUpgrade(context.Background()) + if err != nil { + return err + } + t.do() + return nil + } + if t.isFromRestore { go t.do() } @@ -953,15 +970,22 @@ func (t *TKE) do() { start := time.Now() ctx := t.log.WithContext(context.Background()) - containerregistry.Init(t.Para.Config.Registry.Domain(), t.Para.Config.Registry.Namespace()) - t.initSteps() + var taskType string + if t.Config.Upgrade { + taskType = "upgrade" + t.upgradeSteps() + } else { + taskType = "install" + containerregistry.Init(t.Para.Config.Registry.Domain(), t.Para.Config.Registry.Namespace()) + t.initSteps() + } if t.Step == 0 { - t.log.Info("===>starting install task") + t.log.Infof("===>starting %s task", taskType) t.progress.Status = types.StatusDoing } - if t.runAfterClusterReady() { + if !t.Config.Upgrade && t.runAfterClusterReady() { t.initDataForDeployTKE() } @@ -1020,7 +1044,7 @@ func (t *TKE) do() { } t.progress.Servers = append(t.progress.Servers, t.servers...) - t.log.Infof("===>install task [Sucesss] [%fs]", time.Since(start).Seconds()) + t.log.Infof("===>%s task [Sucesss] [%fs]", taskType, time.Since(start).Seconds()) } func (t *TKE) runAfterClusterReady() bool { @@ -2425,7 +2449,7 @@ func (t *TKE) writeKubeconfig(ctx context.Context) error { return ioutil.WriteFile("/root/.kube/config", data, 0644) } -func (t *TKE) patchK8sValidVersions(ctx context.Context) error { +func (t *TKE) patchPlatformVersion(ctx context.Context) error { versionsByte, err := json.Marshal(spec.K8sValidVersions) if err != nil { return err @@ -2433,6 +2457,7 @@ func (t *TKE) patchK8sValidVersions(ctx context.Context) error { patchData := map[string]interface{}{ "data": map[string]interface{}{ "k8sValidVersions": string(versionsByte), + "tkeVersion": spec.TKEVersion, }, } patchByte, err := json.Marshal(patchData) diff --git a/cmd/tke-installer/app/installer/types/types.go b/cmd/tke-installer/app/installer/types/types.go index d222bd473..ebf6d6777 100644 --- a/cmd/tke-installer/app/installer/types/types.go +++ b/cmd/tke-installer/app/installer/types/types.go @@ -73,6 +73,7 @@ type OIDCAuth struct { type Registry struct { TKERegistry *TKERegistry `json:"tke,omitempty"` ThirdPartyRegistry *ThirdPartyRegistry `json:"thirdParty,omitempty"` + UserInputRegistry UserInputRegistry `json:"userInputRegistry,omitempty"` } type Audit struct { @@ -87,6 +88,9 @@ type ElasticSearch struct { } func (r *Registry) Domain() string { + if r.UserInputRegistry.Domain != "" { + return r.UserInputRegistry.Domain + } if r.ThirdPartyRegistry != nil { // first use third party when both set return r.ThirdPartyRegistry.Domain } @@ -94,6 +98,9 @@ func (r *Registry) Domain() string { } func (r *Registry) Namespace() string { + if r.UserInputRegistry.Namespace != "" { + return r.UserInputRegistry.Namespace + } if r.ThirdPartyRegistry != nil { return r.ThirdPartyRegistry.Namespace } @@ -101,6 +108,9 @@ func (r *Registry) Namespace() string { } func (r *Registry) Username() string { + if r.UserInputRegistry.Username != "" { + return r.UserInputRegistry.Username + } if r.ThirdPartyRegistry != nil { return r.ThirdPartyRegistry.Username } @@ -108,6 +118,9 @@ func (r *Registry) Username() string { } func (r *Registry) Password() []byte { + if len(r.UserInputRegistry.Password) != 0 { + return r.UserInputRegistry.Password + } if r.ThirdPartyRegistry != nil { return r.ThirdPartyRegistry.Password } @@ -138,6 +151,13 @@ type ThirdPartyRegistry struct { Password []byte `json:"password"` } +type UserInputRegistry struct { + Domain string `json:"domain"` + Namespace string `json:"namespace"` + Username string `json:"username"` + Password []byte `json:"password"` +} + type Business struct { } diff --git a/cmd/tke-installer/app/installer/upgrader.go b/cmd/tke-installer/app/installer/upgrader.go new file mode 100644 index 000000000..4894d3431 --- /dev/null +++ b/cmd/tke-installer/app/installer/upgrader.go @@ -0,0 +1,236 @@ +/* + * Tencent is pleased to support the open source community by making TKEStack + * available. + * + * Copyright (C) 2012-2019 Tencent. All Rights Reserved. + * + * 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 + * + * https://opensource.org/licenses/Apache-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 OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package installer + +import ( + "context" + "fmt" + "os/exec" + "time" + + "github.com/pkg/errors" + "github.com/thoas/go-funk" + "gopkg.in/yaml.v2" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/clientcmd" + platformv1 "tkestack.io/tke/api/client/clientset/versioned/typed/platform/v1" + "tkestack.io/tke/cmd/tke-installer/app/installer/images" + "tkestack.io/tke/cmd/tke-installer/app/installer/types" + typesv1 "tkestack.io/tke/pkg/platform/types/v1" + configv1 "tkestack.io/tke/pkg/registry/apis/config/v1" + "tkestack.io/tke/pkg/util/apiclient" + "tkestack.io/tke/pkg/util/containerregistry" + "tkestack.io/tke/pkg/util/file" + + // import platform schema + _ "tkestack.io/tke/api/platform/install" +) + +const ( + registryCmName = "tke-registry-api" + registryCmKey = "tke-registry-config.yaml" +) + +func (t *TKE) upgradeSteps() { + if !t.Para.Config.Registry.IsOfficial() { + t.steps = append(t.steps, []types.Handler{ + { + Name: "Login registry", + Func: t.loginRegistryForUpgrade, + }, + { + Name: "Load images", + Func: t.loadImages, + }, + { + Name: "Push images", + Func: t.pushImages, + }, + }...) + } + + t.steps = append(t.steps, []types.Handler{ + { + Name: "Update tke-platform-api", + Func: t.updateTKEPlatformAPI, + }, + { + Name: "Update tke-platform-controller", + Func: t.updateTKEPlatformController, + }, + }...) + + t.steps = append(t.steps, []types.Handler{ + { + Name: "Patch platform versions in cluster info", + Func: t.patchPlatformVersion, + }, + }...) + + t.steps = funk.Filter(t.steps, func(step types.Handler) bool { + return !funk.ContainsString(t.Para.Config.SkipSteps, step.Name) + }).([]types.Handler) + + t.log.Info("Steps:") + for i, step := range t.steps { + t.log.Infof("%d %s", i, step.Name) + } +} + +func (t *TKE) updateTKEPlatformAPI(ctx context.Context) error { + com := "tke-platform-api" + depl, err := t.globalClient.AppsV1().Deployments(t.namespace).Get(ctx, com, metav1.GetOptions{}) + if err != nil { + return err + } + + if len(depl.Spec.Template.Spec.Containers) == 0 { + return fmt.Errorf("%s has no containers", com) + } + depl.Spec.Template.Spec.Containers[0].Image = images.Get().TKEPlatformAPI.FullName() + + _, err = t.globalClient.AppsV1().Deployments(t.namespace).Update(ctx, depl, metav1.UpdateOptions{}) + if err != nil { + return err + } + + return wait.PollImmediate(5*time.Second, 10*time.Minute, func() (bool, error) { + ok, err := apiclient.CheckDeployment(ctx, t.globalClient, t.namespace, com) + if err != nil { + return false, nil + } + return ok, nil + }) +} + +func (t *TKE) updateTKEPlatformController(ctx context.Context) error { + com := "tke-platform-controller" + depl, err := t.globalClient.AppsV1().Deployments(t.namespace).Get(ctx, com, metav1.GetOptions{}) + if err != nil { + return err + } + + if len(depl.Spec.Template.Spec.Containers) == 0 { + return fmt.Errorf("%s has no containers", com) + } + depl.Spec.Template.Spec.Containers[0].Image = images.Get().TKEPlatformController.FullName() + + if len(depl.Spec.Template.Spec.InitContainers) == 0 { + return fmt.Errorf("%s has no initContainers", com) + } + depl.Spec.Template.Spec.InitContainers[0].Image = images.Get().ProviderRes.FullName() + + _, err = t.globalClient.AppsV1().Deployments(t.namespace).Update(ctx, depl, metav1.UpdateOptions{}) + if err != nil { + return err + } + + return wait.PollImmediate(5*time.Second, 10*time.Minute, func() (bool, error) { + ok, err := apiclient.CheckDeployment(ctx, t.globalClient, t.namespace, com) + if err != nil { + return false, nil + } + return ok, nil + }) +} + +func (t *TKE) prepareForUpgrade(ctx context.Context) error { + t.namespace = namespace + + _ = t.loadTKEData() + + if !file.Exists(t.Config.Kubeconfig) || !file.IsFile(t.Config.Kubeconfig) { + return fmt.Errorf("kubeconfig %s doesn't exist", t.Config.Kubeconfig) + } + config, err := clientcmd.BuildConfigFromFlags("", t.Config.Kubeconfig) + if err != nil { + return err + } + t.globalClient, err = kubernetes.NewForConfig(config) + if err != nil { + return err + } + platformClient, err := platformv1.NewForConfig(config) + if err != nil { + return err + } + t.Cluster, err = typesv1.GetClusterByName(ctx, platformClient, "global") + if err != nil { + return err + } + t.Para.Cluster = *t.Cluster.Cluster + t.Para.Config.Registry.UserInputRegistry.Domain = t.Config.RegistryDomain + t.Para.Config.Registry.UserInputRegistry.Username = t.Config.RegistryUsername + t.Para.Config.Registry.UserInputRegistry.Password = []byte(t.Config.RegistryPassword) + t.Para.Config.Registry.UserInputRegistry.Namespace = t.Config.RegistryNamespace + err = t.loadRegistry(ctx) + if err != nil { + if apierrors.IsNotFound(err) { + t.log.Infof("Not found %s", registryCmName) + if t.Para.Config.Registry.ThirdPartyRegistry == nil { + t.log.Infof("Not found third party registry") + t.Para.Config.Registry.ThirdPartyRegistry = &types.ThirdPartyRegistry{} + } + } else { + return err + } + } + return nil +} + +func (t *TKE) loadRegistry(ctx context.Context) error { + registryCm, err := t.globalClient.CoreV1().ConfigMaps(t.namespace).Get(ctx, registryCmName, metav1.GetOptions{}) + if err != nil { + return err + } + registryConfig := &configv1.RegistryConfiguration{} + err = yaml.Unmarshal([]byte(registryCm.Data[registryCmKey]), registryConfig) + if err != nil { + return err + } + t.Para.Config.Registry.TKERegistry = &types.TKERegistry{ + Domain: registryConfig.DomainSuffix, + HarborEnabled: registryConfig.HarborEnabled, + HarborCAFile: registryConfig.HarborCAFile, + Namespace: "library", + Username: registryConfig.Security.AdminUsername, + Password: []byte(registryConfig.Security.AdminPassword), + } + return nil +} + +func (t *TKE) loginRegistryForUpgrade(ctx context.Context) error { + containerregistry.Init(t.Para.Config.Registry.Domain(), t.Para.Config.Registry.Namespace()) + cmd := exec.Command("docker", "login", + "--username", t.Para.Config.Registry.Username(), + "--password", string(t.Para.Config.Registry.Password()), + t.Para.Config.Registry.Domain(), + ) + out, err := cmd.CombinedOutput() + if err != nil { + if _, ok := err.(*exec.ExitError); ok { + return errors.New(string(out)) + } + return err + } + return nil +} diff --git a/cmd/tke-installer/app/options/options.go b/cmd/tke-installer/app/options/options.go index 86673229e..e543eebe4 100644 --- a/cmd/tke-installer/app/options/options.go +++ b/cmd/tke-installer/app/options/options.go @@ -32,6 +32,12 @@ type Options struct { Force *bool SyncProjectsWithNamespaces *bool Replicas *int + Upgrade *bool + Kubeconfig *string + RegistryUsername *string + RegistryPassword *string + RegistryDomain *string + RegistryNamespace *string } // NewOptions creates a new Options with a default config. @@ -51,6 +57,12 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) { o.Force = fs.Bool("force", false, "force run as clean") o.SyncProjectsWithNamespaces = fs.Bool("sync-projects-with-namespaces", false, "Enable creating/deleting the corresponding namespace when creating/deleting a project.") o.Replicas = fs.Int("replicas", 2, "tke components replicas") + o.Upgrade = fs.Bool("upgrade", false, "upgrade") + o.Kubeconfig = fs.String("kubeconfig", "conf/kubeconfig", "specify kubeconfig for upgrade") + o.RegistryUsername = fs.String("username", "", "specify registry username for upgrade") + o.RegistryPassword = fs.String("password", "", "specify registry password for upgrade") + o.RegistryDomain = fs.String("domain", "", "specify registry domain for upgrade") + o.RegistryNamespace = fs.String("namespace", "", "specify registry namespace for upgrade") } // ApplyFlags parsing parameters from the command line or configuration file diff --git a/pkg/registry/apis/config/v1/types.go b/pkg/registry/apis/config/v1/types.go index 6104620f1..a3eb6c124 100644 --- a/pkg/registry/apis/config/v1/types.go +++ b/pkg/registry/apis/config/v1/types.go @@ -28,32 +28,32 @@ import ( type RegistryConfiguration struct { metav1.TypeMeta - Storage Storage `json:"storage"` - Security Security `json:"security"` + Storage Storage `json:"storage" yaml:"storage"` + Security Security `json:"security" yaml:"security"` // +optional - Redis *Redis `json:"redis,omitempty"` - DefaultTenant string `json:"defaultTenant"` + Redis *Redis `json:"redis,omitempty" yaml:"redis,omitempty"` + DefaultTenant string `json:"defaultTenant" yaml:"defaultTenant"` // +optional - DomainSuffix string `json:"domainSuffix,omitempty"` - HarborEnabled bool `json:"harborEnabled,omitempty"` - HarborCAFile string `json:"harborCAFile,omitempty"` + DomainSuffix string `json:"domainSuffix,omitempty" yaml:"domainSuffix,omitempty"` + HarborEnabled bool `json:"harborEnabled,omitempty" yaml:"harborEnabled,omitempty"` + HarborCAFile string `json:"harborCAFile,omitempty" yaml:"harborCAFile,omitempty"` } type Storage struct { // +optional - FileSystem *FileSystemStorage `json:"fileSystem,omitempty"` + FileSystem *FileSystemStorage `json:"fileSystem,omitempty" yaml:"fileSystem,omitempty"` // +optional - InMemory *InMemoryStorage `json:"inMemory,omitempty"` + InMemory *InMemoryStorage `json:"inMemory,omitempty" yaml:"inMemory,omitempty"` // +optional - S3 *S3Storage `json:"s3,omitempty"` + S3 *S3Storage `json:"s3,omitempty" yaml:"s3,omitempty"` // +optional - Delete *Delete `json:"delete,omitempty"` + Delete *Delete `json:"delete,omitempty" yaml:"delete,omitempty"` } type FileSystemStorage struct { - RootDirectory string `json:"rootDirectory"` + RootDirectory string `json:"rootDirectory" yaml:"rootDirectory"` // +optional - MaxThreads *int64 `json:"maxThreads,omitempty"` + MaxThreads *int64 `json:"maxThreads,omitempty" yaml:"maxThreads,omitempty"` } type InMemoryStorage struct{} @@ -67,82 +67,82 @@ const ( ) type S3Storage struct { - Bucket string `json:"bucket"` - Region string `json:"region"` + Bucket string `json:"bucket" yaml:"bucket"` + Region string `json:"region" yaml:"region"` // +optional - AccessKey *string `json:"accessKey,omitempty"` + AccessKey *string `json:"accessKey,omitempty" yaml:"accessKey,omitempty"` // +optional - SecretKey *string `json:"secretKey,omitempty"` + SecretKey *string `json:"secretKey,omitempty" yaml:"secretKey,omitempty"` // +optional - RegionEndpoint *string `json:"regionEndpoint,omitempty"` + RegionEndpoint *string `json:"regionEndpoint,omitempty" yaml:"regionEndpoint,omitempty"` // +optional - Encrypt *bool `json:"encrypt,omitempty"` + Encrypt *bool `json:"encrypt,omitempty" yaml:"encrypt,omitempty"` // +optional - KeyID *string `json:"keyID,omitempty"` + KeyID *string `json:"keyID,omitempty" yaml:"keyID,omitempty"` // +optional - Secure *bool `json:"secure,omitempty"` + Secure *bool `json:"secure,omitempty" yaml:"secure,omitempty"` // +optional - SkipVerify *bool `json:"skipVerify,omitempty"` + SkipVerify *bool `json:"skipVerify,omitempty" yaml:"skipVerify,omitempty"` // +optional - V4Auth *bool `json:"v4Auth,omitempty"` + V4Auth *bool `json:"v4Auth,omitempty" yaml:"v4Auth,omitempty"` // +optional - ChunkSize *int64 `json:"chunkSize,omitempty"` + ChunkSize *int64 `json:"chunkSize,omitempty" yaml:"chunkSize,omitempty"` // +optional - MultipartCopyChunkSize *int64 `json:"multipartCopyChunkSize,omitempty"` + MultipartCopyChunkSize *int64 `json:"multipartCopyChunkSize,omitempty" yaml:"multipartCopyChunkSize,omitempty"` // +optional - MultipartCopyMaxConcurrency *int64 `json:"multipartCopyMaxConcurrency,omitempty"` + MultipartCopyMaxConcurrency *int64 `json:"multipartCopyMaxConcurrency,omitempty" yaml:"multipartCopyMaxConcurrency,omitempty"` // +optional - MultipartCopyThresholdSize *int64 `json:"multipartCopyThresholdSize,omitempty"` + MultipartCopyThresholdSize *int64 `json:"multipartCopyThresholdSize,omitempty" yaml:"multipartCopyThresholdSize,omitempty"` // +optional - RootDirectory *string `json:"rootDirectory,omitempty"` + RootDirectory *string `json:"rootDirectory,omitempty" yaml:"rootDirectory,omitempty"` // +optional - StorageClass *S3StorageClass `json:"storageClass,omitempty"` + StorageClass *S3StorageClass `json:"storageClass,omitempty" yaml:"storageClass,omitempty"` // +optional - UserAgent *string `json:"userAgent,omitempty"` + UserAgent *string `json:"userAgent,omitempty" yaml:"userAgent,omitempty"` // +optional - ObjectACL *string `json:"objectACL,omitempty"` + ObjectACL *string `json:"objectACL,omitempty" yaml:"objectACL,omitempty"` } // Delete cloud enable the deletion of image blobs and manifests by digest. type Delete struct { - Enabled bool `json:"enabled"` + Enabled bool `json:"enabled" yaml:"enabled"` } type Security struct { - TokenPrivateKeyFile string `json:"tokenPrivateKeyFile"` - TokenPublicKeyFile string `json:"tokenPublicKeyFile"` + TokenPrivateKeyFile string `json:"tokenPrivateKeyFile" yaml:"tokenPrivateKeyFile"` + TokenPublicKeyFile string `json:"tokenPublicKeyFile" yaml:"tokenPublicKeyFile"` // +optional - TokenExpiredHours *int64 `json:"tokenExpiredHours,omitempty"` - HTTPSecret string `json:"httpSecret"` - AdminUsername string `json:"adminUsername"` - AdminPassword string `json:"adminPassword"` + TokenExpiredHours *int64 `json:"tokenExpiredHours,omitempty" yaml:"tokenExpiredHours,omitempty"` + HTTPSecret string `json:"httpSecret" yaml:"httpSecret"` + AdminUsername string `json:"adminUsername" yaml:"adminUsername"` + AdminPassword string `json:"adminPassword" yaml:"adminPassword"` // +optional - EnableAnonymous *bool `json:"enableAnonymous"` + EnableAnonymous *bool `json:"enableAnonymous" yaml:"enableAnonymous"` } // Redis configures the redis pool available to the registry cache. type Redis struct { // Addr specifies the the redis instance available to the registry API server. - Addr string `json:"addr"` + Addr string `json:"addr" yaml:"addr"` // Password string to use when making a connection. - Password string `json:"password"` + Password string `json:"password" yaml:"password"` // DB specifies the database to connect to on the redis instance. - DB int32 `json:"db"` + DB int32 `json:"db" yaml:"db"` // +optional - ReadTimeoutMillisecond *int64 `json:"readTimeoutMillisecond,omitempty"` + ReadTimeoutMillisecond *int64 `json:"readTimeoutMillisecond,omitempty" yaml:"readTimeoutMillisecond,omitempty"` // +optional - DialTimeoutMillisecond *int64 `json:"dialTimeoutMillisecond,omitempty"` + DialTimeoutMillisecond *int64 `json:"dialTimeoutMillisecond,omitempty" yaml:"dialTimeoutMillisecond,omitempty"` // +optional - WriteTimeoutMillisecond *int64 `json:"writeTimeoutMillisecond,omitempty"` + WriteTimeoutMillisecond *int64 `json:"writeTimeoutMillisecond,omitempty" yaml:"writeTimeoutMillisecond,omitempty"` // PoolMaxIdle sets the maximum number of idle connections. // +optional - PoolMaxIdle *int32 `json:"poolMaxIdle,omitempty"` + PoolMaxIdle *int32 `json:"poolMaxIdle,omitempty" yaml:"poolMaxIdle,omitempty"` // PoolMaxActive sets the maximum number of connections that should be opened before // blocking a connection request. // +optional - PoolMaxActive *int32 `json:"poolMaxActive,omitempty"` + PoolMaxActive *int32 `json:"poolMaxActive,omitempty" yaml:"poolMaxActive,omitempty"` // PoolIdleTimeoutSeconds sets the amount time to wait before closing inactive connections. // +optional - PoolIdleTimeoutSeconds *int64 `json:"poolIdleTimeoutSeconds,omitempty"` + PoolIdleTimeoutSeconds *int64 `json:"poolIdleTimeoutSeconds,omitempty" yaml:"poolIdleTimeoutSeconds,omitempty"` } diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index eef5b1066..9c1e3a0b3 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -23,6 +23,7 @@ import ( ) var ( + TKEVersion = "1.5.0" Archs = []string{"amd64", "arm64"} Arm64 = "arm64" Arm64Variants = []string{"v8", "unknown"}