Skip to content

Commit

Permalink
added support for labeling namespaces
Browse files Browse the repository at this point in the history
  • Loading branch information
clubanderson committed Apr 7, 2024
1 parent 9650f74 commit 983475a
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 81 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
��Y�|t��C ��a�L�͹��9���u�HTTP/2.0 200 OK
R�[�˸=�ݭ�-y��k']�Hev�$| ��HTTP/2.0 200 OK
Connection: close
Audit-Id: 3fe64d5b-7abc-400a-b558-6572c2e28f30
Audit-Id: d23dc7ed-d256-4f20-b097-dfac6b592a73
Cache-Control: public
Content-Type: application/json;g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList
Date: Sun, 07 Apr 2024 18:25:24 GMT
Date: Sun, 07 Apr 2024 19:23:16 GMT
Etag: "7E2E4FBD8CDC884130EBFEF64757F6BC507A8EA6A2EA8F94E05F1B6F207B4E183C63D6D6EA5513FDDC10FC16233248F933DC787C288493D52745A3FAFD68CCD8"
Vary: Accept
X-From-Cache: 1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
��~sL�w�n!���^>�fg/�O��u�HTTP/2.0 200 OK
��ɋ �ҖD��H���Ll����ft>Mb��7�HTTP/2.0 200 OK
Connection: close
Audit-Id: b2beda8e-9b5b-4350-aadf-5c0908c7453d
Audit-Id: 3fe7273a-09c4-4574-b1e8-fffd4cb29be7
Cache-Control: public
Content-Type: application/json;g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList
Date: Sun, 07 Apr 2024 18:25:24 GMT
Date: Sun, 07 Apr 2024 19:23:16 GMT
Etag: "1A5B2A0B15DD3BDDAB4EC731846720A10D6516FC00B2F8FD5F2EE3B4FAAF0026D6A7F3CD05601E1D677E5323E883FBAC7097179E1ED34B5DD0D99C67A1856EE0"
Vary: Accept
X-From-Cache: 1
Expand Down
118 changes: 56 additions & 62 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,94 +226,88 @@ run kl with any kubectl command line arguments, and labeler will label all appli

kl apply -f examples/kubectl/pass -l app.kubernetes.io/part-of=sample --context=kind-kind --namespace=default --overwrite

invoked as alias

args: [kubectl apply -f examples/kubectl/pass -l app.kubernetes.io/part-of=sample --context=kind-kind --namespace=default --overwrite]
context: --context=kind-kind
p.namespace: default
labelCmd: [-n default label deployment/my-app-deployment2 app.kubernetes.io/part-of=sample --overwrite --context=kind-kind]
running command: kubectl -n default label deployment/my-app-deployment2 app.kubernetes.io/part-of=sample --overwrite --context=kind-kind
deployment.apps/my-app-deployment2 already has label
labelCmd: [-n default label service/my-app-service2 app.kubernetes.io/part-of=sample --overwrite --context=kind-kind]
running command: kubectl -n default label service/my-app-service2 app.kubernetes.io/part-of=sample --overwrite --context=kind-kind
service/my-app-service2 already has label
deployment.apps/my-app-deployment2 unchanged
service/my-app-service2 unchanged

kustomize

kl apply -k examples/kustomize -l app.kubernetes.io/part-of=sample --context=kind-kind --namespace=default --overwrite
kustomize with "" or "default" namespace (object were previously created and labeled)

invoked as alias
kl apply -k examples/kustomize -l app.kubernetes.io/part-of=sample-app --context=kind-kind --namespace=default --overwrite
service/my-app-service already has label app.kubernetes.io/part-of=sample-app
deployment.apps/my-app-deployment already has label app.kubernetes.io/part-of=sample-app

args: [kubectl apply -k examples/kustomize -l app.kubernetes.io/part-of=sample --context=kind-kind --namespace=default --overwrite]
context: --context=kind-kind
p.namespace: default
labelCmd: [-n default label service/my-app-service app.kubernetes.io/part-of=sample --overwrite --context=kind-kind]
running command: kubectl -n default label service/my-app-service app.kubernetes.io/part-of=sample --overwrite --context=kind-kind
labelCmd: [-n default label deployment/my-app-deployment app.kubernetes.io/part-of=sample --overwrite --context=kind-kind]
running command: kubectl -n default label deployment/my-app-deployment app.kubernetes.io/part-of=sample --overwrite --context=kind-kind
service/my-app-service unchanged
deployment.apps/my-app-deployment unchanged
kustomize with "" or "default" namespace (object were previously created and but new label value provided)

kl apply -k examples/kustomize -l app.kubernetes.io/part-of=sample --context=kind-kind --namespace=default --overwrite
🏷️ created and labeled object "my-app-service" in namespace "default" with app.kubernetes.io/part-of=sample
🏷️ created and labeled object "my-app-deployment" in namespace "default" with app.kubernetes.io/part-of=sample

kustomize with a namespace other than "" or "default" (objects were previously created and labeled)

kl apply -k examples/kustomize -l app.kubernetes.io/part-of=sample-app --context=kind-kind --namespace=temp --overwrite
service/my-app-service already has label app.kubernetes.io/part-of=sample-app
deployment.apps/my-app-deployment already has label app.kubernetes.io/part-of=sample-app
🏷️ labeled object /v1/namespaces "temp" with app.kubernetes.io/part-of=sample-app

kustomize with a namespace other than "" or "default" (objects were previously created but new label value provided)

kl apply -k examples/kustomize -l app.kubernetes.io/part-of=sample --context=kind-kind --namespace=temp --overwrite
🏷️ created and labeled object "my-app-service" in namespace "temp" with app.kubernetes.io/part-of=sample
🏷️ created and labeled object "my-app-deployment" in namespace "temp" with app.kubernetes.io/part-of=sample
🏷️ labeled object /v1/namespaces "temp" with app.kubernetes.io/part-of=sample

run hl with any helm command line arguments, and labeler will label all installed resources, or give output on how to do so

helm (template)

hl --kube-context=kind-kind template sealed-secrets sealed-secrets/sealed-secrets -n sealed-secrets --create-namespace --label=app.kubernetes.io/part-of=sample-app --dry-run; helm --kube-context=kind-kind uninstall sealed-secrets -n sealed-secrets

invoked as alias:
🏷️ labeled object /v1/namespaces "sealed-secrets" with app.kubernetes.io/part-of=sample-app

The following resources do not exist and can be labeled at a later time:

kubectl label serviceaccounts sealed-secrets app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label clusterroles secrets-unsealer app.kubernetes.io/part-of=sample-app
kubectl label clusterrolebindings sealed-secrets app.kubernetes.io/part-of=sample-app
kubectl label roles sealed-secrets-key-admin app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label roles sealed-secrets-service-proxier app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label rolebindings sealed-secrets-key-admin app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label rolebindings sealed-secrets-service-proxier app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label services sealed-secrets app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label services sealed-secrets-metrics app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label deployments sealed-secrets app.kubernetes.io/part-of=sample-app -n sealed-secrets
The following resources do not exist and can be labeled at a later time:

Error: uninstall: Release not loaded: sealed-secrets: release: not found
kubectl label serviceaccounts sealed-secrets app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label clusterroles secrets-unsealer app.kubernetes.io/part-of=sample-app
kubectl label clusterrolebindings sealed-secrets app.kubernetes.io/part-of=sample-app
kubectl label roles sealed-secrets-key-admin app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label roles sealed-secrets-service-proxier app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label rolebindings sealed-secrets-key-admin app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label rolebindings sealed-secrets-service-proxier app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label services sealed-secrets app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label services sealed-secrets-metrics app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label deployments sealed-secrets app.kubernetes.io/part-of=sample-app -n sealed-secrets

helm (install with dry-run)

hl --kube-context=kind-kind install sealed-secrets sealed-secrets/sealed-secrets -n sealed-secrets --create-namespace --label=app.kubernetes.io/part-of=sample-app --dry-run; helm --kube-context=kind-kind uninstall sealed-secrets -n sealed-secrets

invoked as alias:

The following resources do not exist and can be labeled at a later time:

kubectl label serviceaccounts sealed-secrets app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label clusterroles secrets-unsealer app.kubernetes.io/part-of=sample-app
kubectl label clusterrolebindings sealed-secrets app.kubernetes.io/part-of=sample-app
kubectl label roles sealed-secrets-key-admin app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label roles sealed-secrets-service-proxier app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label rolebindings sealed-secrets-key-admin app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label rolebindings sealed-secrets-service-proxier app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label services sealed-secrets app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label services sealed-secrets-metrics app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label deployments sealed-secrets app.kubernetes.io/part-of=sample-app -n sealed-secrets

Error: uninstall: Release not loaded: sealed-secrets: release: not found
kubectl label serviceaccounts sealed-secrets app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label clusterroles secrets-unsealer app.kubernetes.io/part-of=sample-app
kubectl label clusterrolebindings sealed-secrets app.kubernetes.io/part-of=sample-app
kubectl label roles sealed-secrets-key-admin app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label roles sealed-secrets-service-proxier app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label rolebindings sealed-secrets-key-admin app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label rolebindings sealed-secrets-service-proxier app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label services sealed-secrets app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label services sealed-secrets-metrics app.kubernetes.io/part-of=sample-app -n sealed-secrets
kubectl label deployments sealed-secrets app.kubernetes.io/part-of=sample-app -n sealed-secrets

helm (install)

hl --kube-context=kind-kind install sealed-secrets sealed-secrets/sealed-secrets -n sealed-secrets --create-namespace --label=app.kubernetes.io/part-of=sample-app; helm --kube-context=kind-kind uninstall sealed-secrets -n sealed-secrets

invoked as alias:
🏷️ labeled object /v1/serviceaccounts "sealed-secrets" in namespace "sealed-secrets" with app.kubernetes.io/part-of=sample-app
🏷️ labeled object rbac.authorization.k8s.io/v1/clusterroles "secrets-unsealer" in namespace "" with app.kubernetes.io/part-of=sample-app
🏷️ labeled object rbac.authorization.k8s.io/v1/clusterrolebindings "sealed-secrets" in namespace "" with app.kubernetes.io/part-of=sample-app
🏷️ labeled object rbac.authorization.k8s.io/v1/roles "sealed-secrets-key-admin" in namespace "sealed-secrets" with app.kubernetes.io/part-of=sample-app
🏷️ labeled object rbac.authorization.k8s.io/v1/roles "sealed-secrets-service-proxier" in namespace "sealed-secrets" with app.kubernetes.io/part-of=sample-app
🏷️ labeled object rbac.authorization.k8s.io/v1/rolebindings "sealed-secrets-key-admin" in namespace "sealed-secrets" with app.kubernetes.io/part-of=sample-app
🏷️ labeled object rbac.authorization.k8s.io/v1/rolebindings "sealed-secrets-service-proxier" in namespace "sealed-secrets" with app.kubernetes.io/part-of=sample-app
🏷️ labeled object /v1/services "sealed-secrets" in namespace "sealed-secrets" with app.kubernetes.io/part-of=sample-app
🏷️ labeled object /v1/services "sealed-secrets-metrics" in namespace "sealed-secrets" with app.kubernetes.io/part-of=sample-app
🏷️ labeled object apps/v1/deployments "sealed-secrets" in namespace "sealed-secrets" with app.kubernetes.io/part-of=sample-app

🏷️ labeled object /v1/serviceaccounts "sealed-secrets" in namespace "sealed-secrets" with app.kubernetes.io/part-of=sample-app
🏷️ labeled object rbac.authorization.k8s.io/v1/clusterroles "secrets-unsealer" in namespace "" with app.kubernetes.io/part-of=sample-app
🏷️ labeled object rbac.authorization.k8s.io/v1/clusterrolebindings "sealed-secrets" in namespace "" with app.kubernetes.io/part-of=sample-app
🏷️ labeled object rbac.authorization.k8s.io/v1/roles "sealed-secrets-key-admin" in namespace "sealed-secrets" with app.kubernetes.io/part-of=sample-app
🏷️ labeled object rbac.authorization.k8s.io/v1/roles "sealed-secrets-service-proxier" in namespace "sealed-secrets" with app.kubernetes.io/part-of=sample-app
🏷️ labeled object rbac.authorization.k8s.io/v1/rolebindings "sealed-secrets-key-admin" in namespace "sealed-secrets" with app.kubernetes.io/part-of=sample-app
🏷️ labeled object rbac.authorization.k8s.io/v1/rolebindings "sealed-secrets-service-proxier" in namespace "sealed-secrets" with app.kubernetes.io/part-of=sample-app
🏷️ labeled object /v1/services "sealed-secrets" in namespace "sealed-secrets" with app.kubernetes.io/part-of=sample-app
🏷️ labeled object /v1/services "sealed-secrets-metrics" in namespace "sealed-secrets" with app.kubernetes.io/part-of=sample-app
🏷️ labeled object apps/v1/deployments "sealed-secrets" in namespace "sealed-secrets" with app.kubernetes.io/part-of=sample-app
🏷️ labeled object /v1/namespaces "sealed-secrets" with app.kubernetes.io/part-of=sample-app

82 changes: 69 additions & 13 deletions labeler.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type ParamsStruct struct {
dryrunMode bool
debugMode bool
templateMode bool
installMode bool
}

type resultsStruct struct {
Expand Down Expand Up @@ -98,6 +99,7 @@ func (p ParamsStruct) aliasRun(args []string) error {
p.debugMode = false
p.dryrunMode = false
p.templateMode = false
p.namespace = ""
if args[0] == "k" || args[0] == "kubectl" || args[0] == "helm" {
for i := 0; i < len(args); i++ {
// log.Printf("arg: %v\n", args[i])
Expand All @@ -119,6 +121,8 @@ func (p ParamsStruct) aliasRun(args []string) error {
p.dryrunMode = true
} else if args[i] == "template" {
p.templateMode = true
} else if args[i] == "install" {
p.installMode = true
}
}
// log.Println("before args: ", args)
Expand Down Expand Up @@ -147,10 +151,21 @@ func (p ParamsStruct) aliasRun(args []string) error {
os.Exit(1)
}

p.labelerClientSet, p.labelerRestConfig, p.labelerDynamicClient = p.switchContext()

// Format the output
output := strings.TrimSpace(string(out))
lines := strings.Split(output, "\n")
p.setLabelKubectl(lines)

if p.namespace != "" && p.namespace != "default" {
err = p.setLabelNamespace()
if err != nil {
log.Println("Error (set label namespace):", err)
return err
}
}

} else if args[0] == "helm" {
// run the original helm command without the extra labeler flags
output, err := p.runCmd("helm", args[1:])
Expand All @@ -177,20 +192,63 @@ func (p ParamsStruct) aliasRun(args []string) error {
log.Println("Error (to traverseInput):", err)
return err
}
if len(runResults.didNotLabel) > 0 {
log.Printf("\nThe following resources do not exist and can be labeled at a later time:\n\n")
for _, cmd := range runResults.didNotLabel {
log.Printf(cmd)
if p.namespace != "" && p.namespace != "default" {
err = p.setLabelNamespace()
if err != nil {
log.Println("Error (set label namespace):", err)
return err
}
}
log.Println()

}

if len(runResults.didNotLabel) > 0 {
log.Printf("\nThe following resources do not exist and can be labeled at a later time:\n\n")
for _, cmd := range runResults.didNotLabel {
log.Printf(cmd)
}
}
}
return nil
}

func (p ParamsStruct) setLabelNamespace() error {
gvr := schema.GroupVersionResource{
Group: "",
Version: "v1",
Resource: "namespaces",
}
labels := map[string]string{
p.labelKey: p.labelVal,
}
// serialize labels to JSON
patch, err := json.Marshal(map[string]interface{}{
"metadata": map[string]interface{}{
"labels": labels,
},
})
if err != nil {
return err
}

// todo - this logic is not working right. should only label the namespace if installmode is true and dryrunmode is false - I am not doing something right in the following if statement
// because it is always true - and I am not sure why
// log.Printf("dryrunMode: %v, templateMode: %v, installMode: %v\n", p.dryrunMode, p.templateMode, p.installMode)
if p.installMode && !p.dryrunMode {
// log.Printf(" 🟡 patching namespace %q with %v=%v %q %q %q %v\n", p.namespace, p.labelKey, p.labelVal, gvr.Resource, gvr.Version, gvr.Group, string(patch))
_, err = p.labelerDynamicClient.Resource(gvr).Patch(context.TODO(), p.namespace, types.MergePatchType, patch, metav1.PatchOptions{})
}
if err != nil {
if p.installMode && !p.dryrunMode {
labelCmd := fmt.Sprintf("kubectl label %v %v %v=%v\n", gvr.Resource, p.namespace, p.labelKey, p.labelVal)
runResults.didNotLabel = append(runResults.didNotLabel, labelCmd)
}
} else {
log.Printf(" 🏷️ labeled object %v/%v/%v %q with %v=%v\n", gvr.Group, gvr.Version, gvr.Resource, p.namespace, p.labelKey, p.labelVal)
}
return nil
}

// Stub function for traversing each line of output and applying labels if matched by regex
func traverseLine(line, namespace, context, kubeconfig string) {
// Implement your traversal logic here
// Example: Apply label if the line contains "pattern"
Expand Down Expand Up @@ -299,10 +357,7 @@ func (p ParamsStruct) detectInput() error {
log.Printf(cmd)
}
}
log.Println()

return nil

}

func getFile() (*os.File, error) {
Expand Down Expand Up @@ -471,9 +526,9 @@ func (p ParamsStruct) setLabelKubectl(input []string) {
log.Printf("label did not apply due to error: %v", err)
} else {
if strings.Contains(string(output), "not labeled") {
log.Printf(" " + strings.Split(string(output), " ")[0] + " already has label")
log.Printf(" %v already has label %v=%v", strings.Split(string(output), " ")[0], p.labelKey, p.labelVal)
} else {
log.Printf(" 🏷️ created and labeled object %q in namespace %q with %v=%v\n", objectName, namespace, p.labelKey, p.labelVal)
log.Printf(" 🏷️ created and labeled object %q in namespace %q with %v=%v\n", objectName, namespace, p.labelKey, p.labelVal)
}
}
}
Expand Down Expand Up @@ -524,7 +579,8 @@ func (p ParamsStruct) setLabel(namespace, objectName string, gvr schema.GroupVer
}
return err
}
log.Printf(" 🏷️ labeled object %v/%v/%v %q in namespace %q with %v=%v\n", gvr.Group, gvr.Version, gvr.Resource, objectName, namespace, p.labelKey, p.labelVal)

log.Printf(" 🏷️ labeled object %v/%v/%v %q in namespace %q with %v=%v\n", gvr.Group, gvr.Version, gvr.Resource, objectName, namespace, p.labelKey, p.labelVal)
return nil
}

Expand Down Expand Up @@ -633,7 +689,7 @@ func main() {
args := os.Args[1:]
if len(args) > 0 {
if args[0] == "k" || args[0] == "h" || args[0] == "kubectl" || args[0] == "helm" {
log.Println("invoked as alias: ")
// log.Println("invoked as alias: ")
p.aliasRun(args)
}
}
Expand Down

0 comments on commit 983475a

Please sign in to comment.