Feat: vela cluster join support overwrite (#5784)

Signed-off-by: Somefive <yd219913@alibaba-inc.com>
This commit is contained in:
Somefive
2023-04-03 10:12:44 +08:00
committed by GitHub
parent 1a04121894
commit d8f92e0b44
3 changed files with 60 additions and 22 deletions

View File

@@ -24,6 +24,7 @@ import (
"time"
"github.com/briandowns/spinner"
"github.com/kubevela/pkg/util/k8s"
prismclusterv1alpha1 "github.com/kubevela/prism/pkg/apis/cluster/v1alpha1"
clusterv1alpha1 "github.com/oam-dev/cluster-gateway/pkg/apis/cluster/v1alpha1"
clustercommon "github.com/oam-dev/cluster-gateway/pkg/common"
@@ -63,6 +64,10 @@ type KubeClusterConfig struct {
*clientcmdapi.Cluster
*clientcmdapi.AuthInfo
// ClusterAlreadyExistCallback callback for handling cluster already exist,
// if no error returned, the logic will pass through
ClusterAlreadyExistCallback func(string) bool
// Logs records intermediate logs (which do not return error) during running
Logs bytes.Buffer
}
@@ -115,7 +120,7 @@ func (clusterConfig *KubeClusterConfig) PostRegistration(ctx context.Context, cl
return nil
}
func (clusterConfig *KubeClusterConfig) createClusterSecret(ctx context.Context, cli client.Client, withEndpoint bool) error {
func (clusterConfig *KubeClusterConfig) createOrUpdateClusterSecret(ctx context.Context, cli client.Client, withEndpoint bool) error {
var credentialType clusterv1alpha1.CredentialType
data := map[string][]byte{}
if withEndpoint {
@@ -132,26 +137,40 @@ func (clusterConfig *KubeClusterConfig) createClusterSecret(ctx context.Context,
data["tls.crt"] = clusterConfig.AuthInfo.ClientCertificateData
data["tls.key"] = clusterConfig.AuthInfo.ClientKeyData
}
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: clusterConfig.ClusterName,
Namespace: ClusterGatewaySecretNamespace,
Labels: map[string]string{
clustercommon.LabelKeyClusterCredentialType: string(credentialType),
},
},
Type: corev1.SecretTypeOpaque,
Data: data,
secret := &corev1.Secret{}
if err := cli.Get(ctx, apitypes.NamespacedName{Name: clusterConfig.ClusterName, Namespace: ClusterGatewaySecretNamespace}, secret); client.IgnoreNotFound(err) != nil {
return err
}
return cli.Create(ctx, secret)
secret.Name = clusterConfig.ClusterName
secret.Namespace = ClusterGatewaySecretNamespace
secret.Type = corev1.SecretTypeOpaque
_ = k8s.AddLabel(secret, clustercommon.LabelKeyClusterCredentialType, string(credentialType))
secret.Data = data
if secret.ResourceVersion == "" {
return cli.Create(ctx, secret)
}
return cli.Update(ctx, secret)
}
// RegisterByVelaSecret create cluster secrets for KubeVela to use
func (clusterConfig *KubeClusterConfig) RegisterByVelaSecret(ctx context.Context, cli client.Client) error {
if err := ensureClusterNotExists(ctx, cli, clusterConfig.ClusterName); err != nil {
return errors.Wrapf(err, "cannot use cluster name %s", clusterConfig.ClusterName)
cluster, err := prismclusterv1alpha1.NewClusterClient(cli).Get(ctx, clusterConfig.ClusterName)
if client.IgnoreNotFound(err) != nil {
return err
}
if err := clusterConfig.createClusterSecret(ctx, cli, true); err != nil {
if cluster != nil {
if clusterConfig.ClusterAlreadyExistCallback == nil {
return fmt.Errorf("cluster %s already exists", cluster.Name)
}
if !clusterConfig.ClusterAlreadyExistCallback(clusterConfig.ClusterName) {
return nil
}
if cluster.Spec.CredentialType == prismclusterv1alpha1.CredentialTypeInternal || cluster.Spec.CredentialType == prismclusterv1alpha1.CredentialTypeOCMManagedCluster {
return fmt.Errorf("cannot override %s typed cluster", cluster.Spec.CredentialType)
}
}
if err := clusterConfig.createOrUpdateClusterSecret(ctx, cli, true); err != nil {
return errors.Wrapf(err, "failed to add cluster to kubernetes")
}
return clusterConfig.PostRegistration(ctx, cli)
@@ -330,12 +349,13 @@ const (
// JoinClusterArgs args for join cluster
type JoinClusterArgs struct {
engine string
createNamespace string
ioStreams cmdutil.IOStreams
hubConfig *rest.Config
inClusterBootstrap *bool
trackingSpinnerFactory func(string) *spinner.Spinner
engine string
createNamespace string
ioStreams cmdutil.IOStreams
hubConfig *rest.Config
inClusterBootstrap *bool
trackingSpinnerFactory func(string) *spinner.Spinner
clusterAlreadyExistCallback func(string) bool
}
func newJoinClusterArgs(options ...JoinClusterOption) *JoinClusterArgs {
@@ -369,6 +389,14 @@ func (op JoinClusterEngineOption) ApplyToArgs(args *JoinClusterArgs) {
args.engine = string(op)
}
// JoinClusterAlreadyExistCallback configure the callback when cluster already exist
type JoinClusterAlreadyExistCallback func(string) bool
// ApplyToArgs apply to args
func (op JoinClusterAlreadyExistCallback) ApplyToArgs(args *JoinClusterArgs) {
args.clusterAlreadyExistCallback = op
}
// JoinClusterOCMOptions options used when joining clusters by ocm, only support cli for now
type JoinClusterOCMOptions struct {
IoStreams cmdutil.IOStreams
@@ -395,6 +423,7 @@ func JoinClusterByKubeConfig(ctx context.Context, cli client.Client, kubeconfigP
if err := clusterConfig.SetClusterName(clusterName).SetCreateNamespace(args.createNamespace).Validate(); err != nil {
return nil, err
}
clusterConfig.ClusterAlreadyExistCallback = args.clusterAlreadyExistCallback
switch args.engine {
case ClusterGateWayEngine:
if err = clusterConfig.RegisterByVelaSecret(ctx, cli); err != nil {

View File

@@ -201,7 +201,14 @@ func NewClusterJoinCommand(c *common.Args, ioStreams cmdutil.IOStreams) *cobra.C
IoStreams: ioStreams,
HubConfig: restConfig,
TrackingSpinnerFactory: newTrackingSpinner,
})
},
multicluster.JoinClusterAlreadyExistCallback(func(name string) bool {
if !NewUserInput().AskBool(fmt.Sprintf("Cluster %s already exists, do you want to overwrite it?", name), &UserInputOptions{AssumeYes: assumeYes}) {
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "Terminated.\n")
return false
}
return true
}))
if err != nil {
return err
}

View File

@@ -86,6 +86,8 @@ var _ = Describe("Test multicluster scenario", func() {
Expect(err).Should(Succeed())
_, err = execCommand("cluster", "join", "/tmp/worker.kubeconfig", "--name", oldClusterName)
Expect(err).Should(Succeed())
_, err = execCommand("cluster", "join", "/tmp/worker.kubeconfig", "--name", oldClusterName, "-y")
Expect(err).Should(Succeed())
out, err := execCommand("cluster", "list")
Expect(err).Should(Succeed())
Expect(out).Should(ContainSubstring(oldClusterName))