diff --git a/README.md b/README.md index 032a01dd..b97009cb 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,7 @@ Crashd utilizes the concept of a provider to enumerate compute resources. Each i * *Kubernetes Nodes Provider* - extracts host information from a Kubernetes API node objects * *CAPV Provider* - uses Cluster-API to discover machines in vSphere cluster * *CAPA Provider* - uses Cluster-API to discover machines running on AWS +* *KCP Provider* - generates kubeconfig with all contexts for all KCP workspaces. * More providers coming! diff --git a/examples/kcp_provider.crsh b/examples/kcp_provider.crsh new file mode 100644 index 00000000..b0d79dad --- /dev/null +++ b/examples/kcp_provider.crsh @@ -0,0 +1,36 @@ +## @copyright Copyright Broadcom. All Rights Reserved. +## The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. +## @license For licensing, see LICENSE.md. + +# object kinds to capture +kinds = [ +"space", +"configmap" +] + +def configure_work_dir(context): + work_dir = args.workdir if hasattr(args, "workdir") else fail("Error: workdir argument is required but not provided.") + context_dir = work_dir + "/" + context + conf = crashd_config(workdir=context_dir) + +def capture_kcp_objects(): + kcp_provider_result = kcp_provider( + kcp_admin_secret_namespace="", + kcp_admin_secret_name="" + ) + + # capture kubernetes objects from all kcp workspaces + for context in kcp_provider_result.contexts: + print("Capturing kcp objects for", context) + + # set kubeconfig path and context in threadlocal + set_defaults(kube_config(capi_provider=kcp_provider_result, cluster_context=context)) + + # configure work directory based on context name - context-name should use "/" + configure_work_dir(context) + kube_capture(what="objects", kinds=kinds, namespaces=["default"]) + +def main(): + capture_kcp_objects() + +main() diff --git a/starlark/kcp_provider.go b/starlark/kcp_provider.go new file mode 100644 index 00000000..da144cec --- /dev/null +++ b/starlark/kcp_provider.go @@ -0,0 +1,51 @@ +// Copyright (c) 2020 VMware, Inc. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package starlark + +import ( + "context" + "fmt" + + "github.com/pkg/errors" + "go.starlark.net/starlark" + "go.starlark.net/starlarkstruct" +) + +// KcpProviderFn is a built-in starlark function that create a kubeconfig with all contexts for all KCP logical clusters +// Starlark format: kcp_provider(ucp_admin_secret_name= ucp_admin_secret_namespace=) +func KcpProviderFn(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { + + var ( + kcp_admin_secret_name, kcp_admin_secret_namespace string + ) + + err := starlark.UnpackArgs("kcp_provider", args, kwargs, + "kcp_admin_secret_namespace", &kcp_admin_secret_namespace, + "kcp_admin_secret_name", &kcp_admin_secret_name) + if err != nil { + return starlark.None, errors.Wrap(err, "failed to unpack input arguments") + } + + ctx, ok := thread.Local(identifiers.scriptCtx).(context.Context) + if !ok || ctx == nil { + return starlark.None, fmt.Errorf("script context not found") + } + + var kcpKubeConfigPath = "/Users/tatanas/dev.kubeconfig" + //TODO Generate a KCP admin kubeconfig + + // dictionary for capa provider struct + kcpProviderDict := starlark.StringDict{ + "kind": starlark.String(identifiers.kcpProvider), + "kube_config": starlark.String(kcpKubeConfigPath), + } + + var contexts []starlark.Value + contexts = append(contexts, starlark.String("tanzu-cli-Falcons_GCP_New-staging-5a2f0150:project-ashindov")) + contexts = append(contexts, starlark.String("tanzu-cli-Falcons_GCP_New-staging-5a2f0150:project-ashindov:services-space")) + + kcpProviderDict["contexts"] = starlark.NewList(contexts) + + return starlarkstruct.FromStringDict(starlark.String(identifiers.kcpProvider), kcpProviderDict), nil +} diff --git a/starlark/kube_config.go b/starlark/kube_config.go index 8b424b10..ee2719d6 100644 --- a/starlark/kube_config.go +++ b/starlark/kube_config.go @@ -37,7 +37,7 @@ func KubeConfigFn(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, val := provider.Constructor() if constructor, ok := val.(starlark.String); ok { constStr := constructor.GoString() - if constStr != identifiers.capvProvider && constStr != identifiers.capaProvider { + if constStr != identifiers.capvProvider && constStr != identifiers.capaProvider && constStr != identifiers.kcpProvider { return starlark.None, errors.New("unknown capi provider") } } diff --git a/starlark/starlark_exec.go b/starlark/starlark_exec.go index 2120ce9b..f8668266 100644 --- a/starlark/starlark_exec.go +++ b/starlark/starlark_exec.go @@ -138,6 +138,7 @@ func newPredeclareds() starlark.StringDict { identifiers.kubeNodesProvider: starlark.NewBuiltin(identifiers.kubeNodesProvider, KubeNodesProviderFn), identifiers.capvProvider: starlark.NewBuiltin(identifiers.capvProvider, CapvProviderFn), identifiers.capaProvider: starlark.NewBuiltin(identifiers.capaProvider, CapaProviderFn), + identifiers.kcpProvider: starlark.NewBuiltin(identifiers.kcpProvider, KcpProviderFn), identifiers.setDefaults: starlark.NewBuiltin(identifiers.setDefaults, SetDefaultsFunc), identifiers.log: starlark.NewBuiltin(identifiers.log, logFunc), } diff --git a/starlark/support.go b/starlark/support.go index 6f3f3237..95991e3c 100644 --- a/starlark/support.go +++ b/starlark/support.go @@ -54,6 +54,7 @@ var ( kubeNodesProvider string capvProvider string capaProvider string + kcpProvider string sshAgent string }{ @@ -91,6 +92,7 @@ var ( kubeNodesProvider: "kube_nodes_provider", capvProvider: "capv_provider", capaProvider: "capa_provider", + kcpProvider: "kcp_provider", sshAgent: "crashd_ssh_agent", }