Skip to content

Commit ac85f89

Browse files
committed
feat(namespace): make namespace delete idempotent
- add namespace exists command
1 parent 013e18d commit ac85f89

File tree

6 files changed

+92
-25
lines changed

6 files changed

+92
-25
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ copsctl - the Conplement AG Kubernetes developer tooling
77
[![Build Status](https://cpgithub.visualstudio.com/GitHubPipelines/_apis/build/status/conplementAG.copsctl?branchName=master)](https://cpgithub.visualstudio.com/GitHubPipelines/_build/latest?definitionId=9&branchName=master)
88

99
## Requirements
10-
- [kubectl >= 1.23.9](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
10+
- [kubectl >= 1.29.9](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
1111

1212
## Installation
1313

cmd/copsctl/namespace.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ func createNamespaceCommand(hq hq.HQ) {
1616
createNamespaceListCommand(namespaceOrchestrator, namespaceCmdGroup)
1717
createNamespaceCreateCommand(namespaceOrchestrator, namespaceCmdGroup)
1818
createNamespaceDeleteCommand(namespaceOrchestrator, namespaceCmdGroup)
19+
createNamespaceExistsCommand(namespaceOrchestrator, namespaceCmdGroup)
1920
createNamespaceUsersCommand(namespaceOrchestrator, namespaceCmdGroup)
2021
createNamespaceServiceAccountsCommand(namespaceOrchestrator, namespaceCmdGroup)
2122
}
@@ -49,6 +50,15 @@ func createNamespaceDeleteCommand(o *namespace.Orchestrator, cmd cli.Command) {
4950
addNameParam(namespaceDeleteCmd)
5051
}
5152

53+
func createNamespaceExistsCommand(o *namespace.Orchestrator, cmd cli.Command) {
54+
namespaceExistsCmd := cmd.AddCommand("exists", "Checks existence of a namespace",
55+
"Use this command to check existence of a namespace.", func() {
56+
o.Exists()
57+
})
58+
59+
addNameParam(namespaceExistsCmd)
60+
}
61+
5262
func createNamespaceUsersCommand(o *namespace.Orchestrator, cmd cli.Command) {
5363
namespaceUserCmd := cmd.AddCommand("users", "Manage users of a namespace",
5464
"Use this command to manage the users in an existing k8s namespace.",

internal/adapters/kubernetes/commands.go

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,42 +9,53 @@ import (
99
"strings"
1010
)
1111

12-
func GetCurrentConfig(executor commands.Executor) (*ConfigResponse, error) {
13-
command := "kubectl config view -o json"
12+
func PrintAllCopsNamespaces(executor commands.Executor) error {
13+
command := "kubectl get cns"
1414
out, err := executor.Execute(command)
1515

1616
if err != nil {
17-
return nil, err
17+
return err
1818
}
1919

20-
config := &ConfigResponse{}
21-
json.Unmarshal([]byte(out), &config)
22-
return config, nil
20+
logrus.Info("\nNamespaces:\n" + out)
21+
return nil
2322
}
2423

25-
func PrintAllCopsNamespaces(executor commands.Executor) error {
26-
command := "kubectl get copsnamespaces"
27-
out, err := executor.Execute(command)
24+
func ExistsCopsNamespace(executor commands.Executor, namespace string) (bool, error) {
25+
response, err := GetCopsNamespace(executor, namespace)
2826

2927
if err != nil {
30-
return err
28+
return false, err
3129
}
3230

33-
logrus.Info("\nNamespaces:\n" + out)
34-
return nil
31+
if response != nil {
32+
return true, nil
33+
} else {
34+
return false, nil
35+
}
3536
}
3637

3738
func GetCopsNamespace(executor commands.Executor, namespace string) (*CopsNamespaceResponse, error) {
38-
command := "kubectl get CopsNamespace " + namespace + " -o json"
39+
// ignore-not-found flag needed to avoid command to fail with hard panic mode (because of globally set PanicOnAnyError=true)
40+
command := "kubectl get cns " + namespace + " -o json --ignore-not-found"
3941
out, err := executor.Execute(command)
4042

4143
if err != nil {
4244
return nil, err
4345
}
4446

45-
response := &CopsNamespaceResponse{}
46-
json.Unmarshal([]byte(out), &response)
47-
return response, nil
47+
out = strings.TrimSuffix(out, "\n")
48+
49+
if out == "" {
50+
return nil, nil
51+
} else {
52+
response := &CopsNamespaceResponse{}
53+
err := json.Unmarshal([]byte(out), &response)
54+
if err != nil {
55+
return nil, err
56+
}
57+
return response, nil
58+
}
4859
}
4960

5061
func Apply(executor commands.Executor, filepath string) (string, error) {

internal/namespace/namespace.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package namespace
22

33
import (
4+
"fmt"
45
"github.com/conplementAG/copsctl/internal/cmd/flags"
56
"github.com/conplementag/cops-hq/v2/pkg/commands"
67
"github.com/conplementag/cops-hq/v2/pkg/hq"
@@ -27,6 +28,21 @@ func (o *Orchestrator) List() {
2728
kubernetes.PrintAllCopsNamespaces(o.executor)
2829
}
2930

31+
func (o *Orchestrator) Exists() {
32+
namespaceName := viper.GetString(flags.Name)
33+
result, err := kubernetes.ExistsCopsNamespace(o.executor, namespaceName)
34+
35+
if err != nil {
36+
panic("Get Cops namespace failed: " + err.Error())
37+
}
38+
39+
if result {
40+
fmt.Println("yes")
41+
} else {
42+
fmt.Println("no")
43+
}
44+
}
45+
3046
func (o *Orchestrator) Create() {
3147
namespaceName := viper.GetString(flags.Name)
3248

@@ -51,7 +67,11 @@ func (o *Orchestrator) Delete() {
5167
namespace, err := kubernetes.GetCopsNamespace(o.executor, namespaceName)
5268

5369
if err != nil {
54-
logrus.Infof("Cops namespace %s does not exist", namespaceName)
70+
panic("Get Cops namespace failed: " + err.Error())
71+
}
72+
73+
if namespace == nil {
74+
logrus.Infof("Cops namespace '%s' does not exist", namespaceName)
5575
return
5676
}
5777

@@ -60,7 +80,7 @@ func (o *Orchestrator) Delete() {
6080
_, err = kubernetes.DeleteString(o.executor, copsNamespace)
6181

6282
if err != nil {
63-
panic("Deleting copsnamespace failed: " + err.Error())
83+
panic("Deleting Cops namespace failed: " + err.Error())
6484
}
6585

6686
logrus.Infof("Cops namespace %s successfully deleted", namespaceName)

internal/namespace/serviceaccounts.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package namespace
22

33
import (
4+
"fmt"
45
"github.com/conplementAG/copsctl/internal/cmd/flags"
56
"github.com/sirupsen/logrus"
67
"strings"
@@ -45,7 +46,11 @@ func (o *Orchestrator) AddServiceAccounts() {
4546
namespace, err := kubernetes.GetCopsNamespace(o.executor, namespaceName)
4647

4748
if err != nil {
48-
panic("Could not get the cops namespace " + err.Error())
49+
panic("Get Cops namespace failed: " + err.Error())
50+
}
51+
52+
if namespace == nil {
53+
panic(fmt.Sprintf("Cops namespace '%s' does not exist", namespaceName))
4954
}
5055

5156
existingUsers := namespace.Spec.NamespaceAdminUsers
@@ -88,7 +93,11 @@ func (o *Orchestrator) RemoveServiceAccounts() {
8893
namespace, err := kubernetes.GetCopsNamespace(o.executor, namespaceName)
8994

9095
if err != nil {
91-
panic("Could not get the cops namespace " + err.Error())
96+
panic("Get Cops namespace failed: " + err.Error())
97+
}
98+
99+
if namespace == nil {
100+
panic(fmt.Sprintf("Cops namespace '%s' does not exist", namespaceName))
92101
}
93102

94103
existingUsers := namespace.Spec.NamespaceAdminUsers
@@ -129,7 +138,11 @@ func (o *Orchestrator) ListServiceAccounts() {
129138
namespace, err := kubernetes.GetCopsNamespace(o.executor, namespaceName)
130139

131140
if err != nil {
132-
panic("Could not get the cops namespace " + err.Error())
141+
panic("Get Cops namespace failed: " + err.Error())
142+
}
143+
144+
if namespace == nil {
145+
panic(fmt.Sprintf("Cops namespace '%s' does not exist", namespaceName))
133146
}
134147

135148
serviceAccounts := namespace.Spec.NamespaceAdminServiceAccounts

internal/namespace/users.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package namespace
22

33
import (
4+
"fmt"
45
"github.com/conplementAG/copsctl/internal/cmd/flags"
56
"github.com/sirupsen/logrus"
67
"strings"
@@ -28,7 +29,11 @@ func (o *Orchestrator) AddUsers() {
2829
namespace, err := kubernetes.GetCopsNamespace(o.executor, namespaceName)
2930

3031
if err != nil {
31-
panic("Could not get the cops namespace " + err.Error())
32+
panic("Get Cops namespace failed: " + err.Error())
33+
}
34+
35+
if namespace == nil {
36+
panic(fmt.Sprintf("Cops namespace '%s' does not exist", namespaceName))
3237
}
3338

3439
relevantUsers := namespace.Spec.NamespaceAdminUsers
@@ -71,7 +76,11 @@ func (o *Orchestrator) RemoveUsers() {
7176
namespace, err := kubernetes.GetCopsNamespace(o.executor, namespaceName)
7277

7378
if err != nil {
74-
panic("Could not get the cops namespace " + err.Error())
79+
panic("Get Cops namespace failed: " + err.Error())
80+
}
81+
82+
if namespace == nil {
83+
panic(fmt.Sprintf("Cops namespace '%s' does not exist", namespaceName))
7584
}
7685

7786
existingUsers := namespace.Spec.NamespaceAdminUsers
@@ -112,7 +121,11 @@ func (o *Orchestrator) ListUsers() {
112121
namespace, err := kubernetes.GetCopsNamespace(o.executor, namespaceName)
113122

114123
if err != nil {
115-
panic("Could not get the cops namespace " + err.Error())
124+
panic("Get Cops namespace failed: " + err.Error())
125+
}
126+
127+
if namespace == nil {
128+
panic(fmt.Sprintf("Cops namespace '%s' does not exist", namespaceName))
116129
}
117130

118131
users := namespace.Spec.NamespaceAdminUsers

0 commit comments

Comments
 (0)