Skip to content

Commit 8760afd

Browse files
authored
Added --namespace flag to k3kcli policy create (#564)
* added --namespace flag to policy create to actually bind the new policy to existing namespaces * fix lint * fix tests * added overwrite flag * updated cli docs * fix tests 2 * moved double quotes to single quote * fix test
1 parent 2773030 commit 8760afd

File tree

6 files changed

+87
-15
lines changed

6 files changed

+87
-15
lines changed

cli/cmds/cluster_create.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ func createAction(appCtx *AppContext, config *CreateConfig) func(cmd *cobra.Comm
115115
}
116116
}
117117

118-
logrus.Infof("Creating cluster [%s] in namespace [%s]", name, namespace)
118+
logrus.Infof("Creating cluster '%s' in namespace '%s'", name, namespace)
119119

120120
cluster := newCluster(name, namespace, config)
121121

@@ -138,7 +138,7 @@ func createAction(appCtx *AppContext, config *CreateConfig) func(cmd *cobra.Comm
138138

139139
if err := client.Create(ctx, cluster); err != nil {
140140
if apierrors.IsAlreadyExists(err) {
141-
logrus.Infof("Cluster [%s] already exists", name)
141+
logrus.Infof("Cluster '%s' already exists", name)
142142
} else {
143143
return err
144144
}
@@ -161,7 +161,7 @@ func createAction(appCtx *AppContext, config *CreateConfig) func(cmd *cobra.Comm
161161
return fmt.Errorf("failed to wait for cluster to become ready (status: %s): %w", cluster.Status.Phase, err)
162162
}
163163

164-
logrus.Infof("Extracting Kubeconfig for [%s] cluster", name)
164+
logrus.Infof("Extracting Kubeconfig for '%s' cluster", name)
165165

166166
// retry every 5s for at most 2m, or 25 times
167167
availableBackoff := wait.Backoff{

cli/cmds/cluster_delete.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func delete(appCtx *AppContext) func(cmd *cobra.Command, args []string) error {
4848

4949
namespace := appCtx.Namespace(name)
5050

51-
logrus.Infof("Deleting [%s] cluster in namespace [%s]", name, namespace)
51+
logrus.Infof("Deleting '%s' cluster in namespace '%s'", name, namespace)
5252

5353
cluster := v1beta1.Cluster{
5454
ObjectMeta: metav1.ObjectMeta{

cli/cmds/policy_create.go

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ type VirtualClusterPolicyCreateConfig struct {
2121
mode string
2222
labels []string
2323
annotations []string
24+
namespaces []string
25+
overwrite bool
2426
}
2527

2628
func NewPolicyCreateCmd(appCtx *AppContext) *cobra.Command {
@@ -45,6 +47,8 @@ func NewPolicyCreateCmd(appCtx *AppContext) *cobra.Command {
4547
cmd.Flags().StringVar(&config.mode, "mode", "shared", "The allowed mode type of the policy")
4648
cmd.Flags().StringArrayVar(&config.labels, "labels", []string{}, "Labels to add to the policy object (e.g. key=value)")
4749
cmd.Flags().StringArrayVar(&config.annotations, "annotations", []string{}, "Annotations to add to the policy object (e.g. key=value)")
50+
cmd.Flags().StringSliceVar(&config.namespaces, "namespace", []string{}, "The namespaces where to bind the policy")
51+
cmd.Flags().BoolVar(&config.overwrite, "overwrite", false, "Overwrite namespace binding of existing policy")
4852

4953
return cmd
5054
}
@@ -56,8 +60,11 @@ func policyCreateAction(appCtx *AppContext, config *VirtualClusterPolicyCreateCo
5660
policyName := args[0]
5761

5862
_, err := createPolicy(ctx, client, config, policyName)
63+
if err != nil {
64+
return err
65+
}
5966

60-
return err
67+
return bindPolicyToNamespaces(ctx, client, config, policyName)
6168
}
6269
}
6370

@@ -75,7 +82,7 @@ func createNamespace(ctx context.Context, client client.Client, name, policyName
7582
return err
7683
}
7784

78-
logrus.Infof(`Creating namespace [%s]`, name)
85+
logrus.Infof(`Creating namespace '%s'`, name)
7986

8087
if err := client.Create(ctx, ns); err != nil {
8188
return err
@@ -86,7 +93,7 @@ func createNamespace(ctx context.Context, client client.Client, name, policyName
8693
}
8794

8895
func createPolicy(ctx context.Context, client client.Client, config *VirtualClusterPolicyCreateConfig, policyName string) (*v1beta1.VirtualClusterPolicy, error) {
89-
logrus.Infof("Creating policy [%s]", policyName)
96+
logrus.Infof("Creating policy '%s'", policyName)
9097

9198
policy := &v1beta1.VirtualClusterPolicy{
9299
ObjectMeta: metav1.ObjectMeta{
@@ -108,8 +115,67 @@ func createPolicy(ctx context.Context, client client.Client, config *VirtualClus
108115
return nil, err
109116
}
110117

111-
logrus.Infof("Policy [%s] already exists", policyName)
118+
logrus.Infof("Policy '%s' already exists", policyName)
112119
}
113120

114121
return policy, nil
115122
}
123+
124+
func bindPolicyToNamespaces(ctx context.Context, client client.Client, config *VirtualClusterPolicyCreateConfig, policyName string) error {
125+
var errs []error
126+
127+
for _, namespace := range config.namespaces {
128+
var ns v1.Namespace
129+
if err := client.Get(ctx, types.NamespacedName{Name: namespace}, &ns); err != nil {
130+
if apierrors.IsNotFound(err) {
131+
logrus.Warnf(`Namespace '%s' not found, skipping`, namespace)
132+
} else {
133+
errs = append(errs, err)
134+
}
135+
136+
continue
137+
}
138+
139+
if ns.Labels == nil {
140+
ns.Labels = map[string]string{}
141+
}
142+
143+
oldPolicy := ns.Labels[policy.PolicyNameLabelKey]
144+
145+
// same policy found, no need to update
146+
if oldPolicy == policyName {
147+
logrus.Debugf(`Policy '%s' already bound to namespace '%s'`, policyName, namespace)
148+
continue
149+
}
150+
151+
// no old policy, safe to update
152+
if oldPolicy == "" {
153+
if err := client.Update(ctx, &ns); err != nil {
154+
errs = append(errs, err)
155+
} else {
156+
logrus.Infof(`Added policy '%s' to namespace '%s'`, policyName, namespace)
157+
}
158+
159+
continue
160+
}
161+
162+
// different policy, warn or check for overwrite flag
163+
if oldPolicy != policyName {
164+
if config.overwrite {
165+
logrus.Infof(`Found policy '%s' bound to namespace '%s'. Overwriting it with '%s'`, oldPolicy, namespace, policyName)
166+
167+
ns.Labels[policy.PolicyNameLabelKey] = policyName
168+
169+
if err := client.Update(ctx, &ns); err != nil {
170+
errs = append(errs, err)
171+
} else {
172+
logrus.Infof(`Added policy '%s' to namespace '%s'`, policyName, namespace)
173+
}
174+
} else {
175+
logrus.Warnf(`Found policy '%s' bound to namespace '%s'. Skipping. To overwrite it use the --overwrite flag`, oldPolicy, namespace)
176+
}
177+
}
178+
}
179+
180+
return errors.Join(errs...)
181+
}

cli/cmds/policy_delete.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,17 @@ func policyDeleteAction(appCtx *AppContext) func(cmd *cobra.Command, args []stri
3131
policy.Name = name
3232

3333
if err := client.Delete(ctx, policy); err != nil {
34-
if apierrors.IsNotFound(err) {
35-
logrus.Warnf("Policy not found")
36-
} else {
34+
if !apierrors.IsNotFound(err) {
3735
return err
3836
}
37+
38+
logrus.Warnf("Policy '%s' not found", name)
39+
40+
return nil
3941
}
4042

43+
logrus.Infof("Policy '%s' deleted", name)
44+
4145
return nil
4246
}
4347
}

docs/cli/k3kcli_policy_create.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ k3kcli policy create [command options] NAME
1919
-h, --help help for create
2020
--labels stringArray Labels to add to the policy object (e.g. key=value)
2121
--mode string The allowed mode type of the policy (default "shared")
22+
--namespace strings The namespaces where to bind the policy
23+
--overwrite Overwrite namespace binding of existing policy
2224
```
2325

2426
### Options inherited from parent commands

tests/cli_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ var _ = When("using the k3kcli", Label("cli"), func() {
6666

6767
_, stderr, err = K3kcli("cluster", "delete", clusterName)
6868
Expect(err).To(Not(HaveOccurred()), string(stderr))
69-
Expect(stderr).To(ContainSubstring("Deleting [%s] cluster in namespace [%s]", clusterName, clusterNamespace))
69+
Expect(stderr).To(ContainSubstring(`Deleting '%s' cluster in namespace '%s'`, clusterName, clusterNamespace))
7070

7171
// The deletion could take a bit
7272
Eventually(func() string {
@@ -92,7 +92,7 @@ var _ = When("using the k3kcli", Label("cli"), func() {
9292

9393
_, stderr, err = K3kcli("policy", "create", policyName)
9494
Expect(err).To(Not(HaveOccurred()), string(stderr))
95-
Expect(stderr).To(ContainSubstring("Creating policy [%s]", policyName))
95+
Expect(stderr).To(ContainSubstring(`Creating policy '%s'`, policyName))
9696

9797
stdout, stderr, err = K3kcli("policy", "list")
9898
Expect(err).To(Not(HaveOccurred()), string(stderr))
@@ -102,7 +102,7 @@ var _ = When("using the k3kcli", Label("cli"), func() {
102102
stdout, stderr, err = K3kcli("policy", "delete", policyName)
103103
Expect(err).To(Not(HaveOccurred()), string(stderr))
104104
Expect(stdout).To(BeEmpty())
105-
Expect(stderr).To(BeEmpty())
105+
Expect(stderr).To(ContainSubstring(`Policy '%s' deleted`, policyName))
106106

107107
stdout, stderr, err = K3kcli("policy", "list")
108108
Expect(err).To(Not(HaveOccurred()), string(stderr))
@@ -140,7 +140,7 @@ var _ = When("using the k3kcli", Label("cli"), func() {
140140

141141
_, stderr, err = K3kcli("cluster", "delete", clusterName)
142142
Expect(err).To(Not(HaveOccurred()), string(stderr))
143-
Expect(stderr).To(ContainSubstring("Deleting [%s] cluster in namespace [%s]", clusterName, clusterNamespace))
143+
Expect(stderr).To(ContainSubstring(`Deleting '%s' cluster in namespace '%s'`, clusterName, clusterNamespace))
144144
})
145145
})
146146
})

0 commit comments

Comments
 (0)