Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add antcl mc commands to get/delete member token #4254

Merged
merged 1 commit into from
Oct 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions docs/multicluster/antctl.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ prints all ResourceExports, a specified ResourceExport, or ResourceExports in a
specified Namespace.
- `antctl mc get joinconfig` command prints member cluster join parameters of
the ClusterSet in a specified leader cluster Namespace.
- `antctl mc get membertoken` (or `get membertokens`) command prints all member tokens,
a specified token, or member tokens in a specified Namespace. The command is supported
only on a leader cluster.

Using the `json` or `yaml` antctl output format can print more information of
ClusterSet, ResourceImport, and ResourceExport than using the default table
Expand All @@ -33,6 +36,7 @@ antctl mc get clusterset [NAME] [-n NAMESPACE] [-o json|yaml] [-A]
antctl mc get resourceimport [NAME] [-n NAMESPACE] [-o json|yaml] [-A]
antctl mc get resourceexport [NAME] [-n NAMESPACE] [-clusterid CLUSTERID] [-o json|yaml] [-A]
antctl mc get joinconfig [-n NAMESPACE]
antctl mc get membertoken [NAME] [-n NAMESPACE] [-o json|yaml] [-A]
```

To see the usage examples of these commands, you may also run `antctl mc get [subcommand] --help`.
Expand All @@ -49,6 +53,17 @@ anctcl mc create membertoken NAME -n NAMESPACE [-o OUTPUT_FILE]

To see the usage examples of these commands, you may also run `antctl mc create [subcommand] --help`.

## antctl mc delete

`antctl mc delete` command deletes a member token of a ClusterSet. The command will delete the
corresponding Secret, ServiceAccount and RoleBinding if they exist.

```bash
anctcl mc delete membertoken NAME -n NAMESPACE
```

To see the usage examples of these commands, you may also run `antctl mc delete [subcommand] --help`.

## antctl mc deploy

`antctl mc deploy` command deploys Antrea Multi-cluster Controller to a leader or member cluster.
Expand Down
6 changes: 6 additions & 0 deletions pkg/antctl/antctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,12 @@ $ antctl get podmulticaststats pod -n namespace`,
supportController: false,
commandGroup: mc,
},
{
cobraCommand: multicluster.DeleteCmd,
supportAgent: false,
supportController: false,
commandGroup: mc,
},
{
cobraCommand: set.SetCmd,
supportAgent: false,
Expand Down
12 changes: 10 additions & 2 deletions pkg/antctl/raw/multicluster/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/spf13/cobra"

"antrea.io/antrea/pkg/antctl/raw/multicluster/create"
"antrea.io/antrea/pkg/antctl/raw/multicluster/delete"
"antrea.io/antrea/pkg/antctl/raw/multicluster/deploy"
"antrea.io/antrea/pkg/antctl/raw/multicluster/get"
)
Expand All @@ -29,14 +30,19 @@ var GetCmd = &cobra.Command{

var CreateCmd = &cobra.Command{
Use: "create",
Short: "Create multi-cluster resources",
Short: "Create a member token for a ClusterSet",
}

var DeployCmd = &cobra.Command{
Use: "deploy",
Short: "Deploy Antrea Multi-cluster Controller to a leader or member cluster",
}

var DeleteCmd = &cobra.Command{
bangqipropel marked this conversation as resolved.
Show resolved Hide resolved
Use: "delete",
Short: "Delete a member token",
}

var JoinCmd = NewJoinCommand()
var LeaveCmd = NewLeaveCommand()
var InitCmd = NewInitCommand()
Expand All @@ -47,7 +53,9 @@ func init() {
GetCmd.AddCommand(get.NewResourceImportCommand())
GetCmd.AddCommand(get.NewResourceExportCommand())
GetCmd.AddCommand(get.NewJoinConfigCommand())
CreateCmd.AddCommand(create.NewAccessTokenCmd())
GetCmd.AddCommand(get.NewMemberTokenCommand())
CreateCmd.AddCommand(create.NewMemberTokenCmd())
DeployCmd.AddCommand(deploy.NewLeaderClusterCmd())
DeployCmd.AddCommand(deploy.NewMemberClusterCmd())
DeleteCmd.AddCommand(delete.NewMemberTokenCmd())
}
108 changes: 96 additions & 12 deletions pkg/antctl/raw/multicluster/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ func CreateClusterClaim(cmd *cobra.Command, k8sClient client.Client, namespace s
if !apierrors.IsAlreadyExists(createErr) {
fmt.Fprintf(cmd.OutOrStdout(), "Failed to create ClusterClaim \"%s\": %v\n", multiclusterv1alpha2.WellKnownClusterClaimID, createErr)
return createErr

}
fmt.Fprintf(cmd.OutOrStdout(), "ClusterClaim \"%s\" already exists in Namespace %s\n", multiclusterv1alpha2.WellKnownClusterClaimID, namespace)
createErr = nil
Expand Down Expand Up @@ -231,6 +230,23 @@ func deleteServiceAccounts(cmd *cobra.Command, k8sClient client.Client, namespac
}
}

// ConvertMemberTokenSecret generates a token Secret manifest for creating the input Secret in a member cluster.
func ConvertMemberTokenSecret(secret corev1.Secret) corev1.Secret {
bangqipropel marked this conversation as resolved.
Show resolved Hide resolved
s := corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: secret.Name,
Namespace: secret.Namespace,
},
Data: secret.Data,
Type: corev1.SecretTypeOpaque,
}
return s
}

func CreateMemberToken(cmd *cobra.Command, k8sClient client.Client, name string, namespace string, file *os.File, createdRes *[]map[string]interface{}) error {
var createErr error
serviceAccount := newServiceAccount(name, namespace)
Expand Down Expand Up @@ -291,17 +307,8 @@ func CreateMemberToken(cmd *cobra.Command, k8sClient client.Client, name string,
if err := k8sClient.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: namespace}, secret); err != nil {
return err
}
s := &corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Data: secret.Data,
Type: corev1.SecretTypeOpaque,
}

s := ConvertMemberTokenSecret(*secret)

b, err := k8syaml.Marshal(s)
if err != nil {
Expand All @@ -321,6 +328,83 @@ func CreateMemberToken(cmd *cobra.Command, k8sClient client.Client, name string,
return nil
}

func DeleteMemberToken(cmd *cobra.Command, k8sClient client.Client, name string, namespace string) error {
errFunc := func(kind string, act string, err error) error {
if apierrors.IsNotFound(err) {
fmt.Fprintf(cmd.OutOrStdout(), "%s %s not found in Namespace %s\n", kind, name, namespace)
return nil
}
if err != nil {
return err
}
if act == "delete" {
fmt.Fprintf(cmd.OutOrStdout(), "%s %s deleted\n", kind, name)
}
return nil
}

bangqipropel marked this conversation as resolved.
Show resolved Hide resolved
secret := &corev1.Secret{}
getErr := k8sClient.Get(context.TODO(), types.NamespacedName{Namespace: namespace, Name: name}, secret)
bangqipropel marked this conversation as resolved.
Show resolved Hide resolved
err := errFunc("Secret", "get", getErr)
if err != nil {
return err
}
if secret.Annotations[CreateByAntctlAnnotation] == "true" {
bangqipropel marked this conversation as resolved.
Show resolved Hide resolved
jianjuns marked this conversation as resolved.
Show resolved Hide resolved
deleteErr := k8sClient.Delete(context.TODO(), &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Namespace: namespace,
Name: name,
}}, &client.DeleteOptions{})
err = errFunc("Secret", "delete", deleteErr)
if err != nil {
return err
}
} else {
fmt.Fprintf(cmd.OutOrStdout(), "Secret %s is not created by antctl, ignoring it", name)
}

roleBinding := &rbacv1.RoleBinding{}
getErr = k8sClient.Get(context.TODO(), types.NamespacedName{Namespace: namespace, Name: name}, roleBinding)
err = errFunc("RoleBinding", "get", getErr)
if err != nil {
return err
}
if roleBinding.Annotations[CreateByAntctlAnnotation] == "true" {
deleteErr := k8sClient.Delete(context.TODO(), &rbacv1.RoleBinding{
ObjectMeta: metav1.ObjectMeta{
Namespace: namespace,
Name: name,
}}, &client.DeleteOptions{})
err = errFunc("RoleBinding", "delete", deleteErr)
if err != nil {
return err
}
} else {
fmt.Fprintf(cmd.OutOrStdout(), "RoleBinding %s is not created by antctl , ignoring it", name)
}

serviceAccount := &corev1.ServiceAccount{}
getErr = k8sClient.Get(context.TODO(), types.NamespacedName{Namespace: namespace, Name: name}, serviceAccount)
err = errFunc("ServiceAccount", "get", getErr)
if err != nil {
return err
}
if serviceAccount.Annotations[CreateByAntctlAnnotation] == "true" {
deleteErr := k8sClient.Delete(context.TODO(), &corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Namespace: namespace,
Name: name,
}}, &client.DeleteOptions{})
err = errFunc("ServiceAccount", "delete", deleteErr)
if err != nil {
return err
}
} else {
fmt.Fprintf(cmd.OutOrStdout(), "ServiceAccount %s is not created by antctl, ignoring it", name)
}
return nil
}

func waitForSecretReady(client client.Client, secretName string, namespace string) error {
return wait.PollImmediate(
1*time.Second,
Expand Down
Loading