mirror of
https://github.com/kubevela/kubevela.git
synced 2026-02-14 10:00:06 +00:00
Feat: vela cluster join support overwrite (#5784)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user