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 Initial support for CAPG Provider #243

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
* *CAPG Provider* - uses Cluster-API to discover machines running on Google Cloud
* More providers coming!


Expand Down
40 changes: 40 additions & 0 deletions examples/capg_provider.crsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
ssh_conf = ssh_config(username=args.username, jump_user=args.username, jump_host=args.jump_host, private_key_path=args.private_key_path)
kube_conf = kube_config(path=args.mc_config)

#list out management and workload cluster nodes
wc_provider=capg_provider(
workload_cluster=args.cluster_name,
namespace=args.cluster_ns,
ssh_config=ssh_conf,
mgmt_kube_config=kube_conf
)
# This is broken. I need to look in to why.
# nodes = resources(provider=wc_provider)
print("BEFORE IT BREAKS")
print(wc_provider)
print("THIS IS BROKEN")
print(resources(provider=wc_provider))
print("THIS IS NOT BROKEN")
nodes = resources(provider = host_list_provider(hosts=wc_provider.hosts, ssh_config=ssh_conf))
print(nodes)

capture(cmd="sudo df -i", resources=nodes)
capture(cmd="sudo crictl info", resources=nodes)
capture(cmd="df -h /var/lib/containerd", resources=nodes)
capture(cmd="sudo systemctl status kubelet", resources=nodes)
capture(cmd="sudo systemctl status containerd", resources=nodes)
capture(cmd="sudo journalctl -xeu kubelet", resources=nodes)

capture(cmd="sudo cat /var/log/cloud-init-output.log", resources=nodes)
capture(cmd="sudo cat /var/log/cloud-init.log", resources=nodes)

#add code to collect pod info from cluster
set_defaults(kube_config(capi_provider = wc_provider))

pod_ns=["default", "kube-system"]

kube_capture(what="logs", namespaces=pod_ns)
kube_capture(what="objects", kinds=["pods", "services"], namespaces=pod_ns)
kube_capture(what="objects", kinds=["deployments", "replicasets"], groups=["apps"], namespaces=pod_ns)

# archive(output_file="diagnostics.tar.gz", source_paths=[conf.workdir])
2 changes: 1 addition & 1 deletion examples/capv_provider.crsh
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ kube_capture(what="logs", namespaces=pod_ns)
kube_capture(what="objects", kinds=["pods", "services"], namespaces=pod_ns)
kube_capture(what="objects", kinds=["deployments", "replicasets"], groups=["apps"], namespaces=pod_ns)

archive(output_file="diagnostics.tar.gz", source_paths=[conf.workdir])
archive(output_file="diagnostics.tar.gz", source_paths=[conf.workdir])
3 changes: 1 addition & 2 deletions examples/kind-api-objects.crsh
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@ nspaces=[
"cert-manager", "tkg-system",
]

set_defaults(kube_config(path=args.kubecfg))

# capture Kubernetes API object and store in files (under working dir)
kube_capture(what="objects", kinds=["services", "pods"], namespaces=nspaces)
kube_capture(what="objects", kinds=["deployments", "replicasets"], namespaces=nspaces)
kube_capture(what="objects", kinds=["clusters", "machines", "machinesets", "machinedeployments"], namespaces=["tkg-system"])

# bundle files stored in working dir
archive(output_file="/tmp/crashobjs.tar.gz", source_paths=[conf.workdir])
archive(output_file="/tmp/crashobjs.tar.gz", source_paths=[conf.workdir])
12 changes: 6 additions & 6 deletions k8s/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,11 @@ func (k8sc *Client) Search(ctx context.Context, params SearchParams) ([]SearchRe
}

// Search does a drill-down search from group, version, resourceList, to resources. The following rules are applied
// 1) Legacy core group can be specified as "core" instead of empty string.
// 2) All specified search params will use AND operator for match (i.e. groups=core AND kinds=pods AND versions=v1 AND ... etc)
// 3) kinds (resources) will match resource.Kind or resource.Name
// 4) All search params are passed as comma- or space-separated sets that are matched using OR (i.e. kinds=pods services
// will match resouces of type pods or services)
// 1. Legacy core group can be specified as "core" instead of empty string.
// 2. All specified search params will use AND operator for match (i.e. groups=core AND kinds=pods AND versions=v1 AND ... etc)
// 3. kinds (resources) will match resource.Kind or resource.Name
// 4. All search params are passed as comma- or space-separated sets that are matched using OR (i.e. kinds=pods services
// will match resouces of type pods or services)
func (k8sc *Client) _search(ctx context.Context, groups, categories, kinds, namespaces, versions, names, labels, containers string) ([]SearchResult, error) {

// normalize params
Expand Down Expand Up @@ -277,7 +277,7 @@ func (k8sc *Client) _search(ctx context.Context, groups, categories, kinds, name
results = append(results, result)
}
} else {
logrus.Debugf("searching for %s objects in [group=%s; non-namespced; labels=%v]",
logrus.Debugf("searching for %s objects in [group=%s; non-namespaced; labels=%v]",
resource.Name, groupVer, listOptions.LabelSelector,
)

Expand Down
99 changes: 99 additions & 0 deletions starlark/capg_provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright (c) 2020 VMware, Inc. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package starlark

import (
"context"
"fmt"

"github.com/pkg/errors"
"github.com/vmware-tanzu/crash-diagnostics/k8s"
"github.com/vmware-tanzu/crash-diagnostics/provider"
"go.starlark.net/starlark"
"go.starlark.net/starlarkstruct"
)

// CapaProviderFn is a built-in starlark function that collects compute resources from a k8s cluster
// Starlark format: capg_provider(kube_config=kube_config(), ssh_config=ssh_config()[workload_cluster=<name>, namespace=<namespace>, nodes=["foo", "bar], labels=["bar", "baz"]])
func CapgProviderFn(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {

var (
workloadCluster, namespace string
names, labels *starlark.List
sshConfig, mgmtKubeConfig *starlarkstruct.Struct
)

err := starlark.UnpackArgs("capg_provider", args, kwargs,
"ssh_config", &sshConfig,
"mgmt_kube_config", &mgmtKubeConfig,
"workload_cluster?", &workloadCluster,
"namespace?", &namespace,
"labels?", &labels,
"nodes?", &names)
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")
}

if sshConfig == nil || mgmtKubeConfig == nil {
return starlark.None, errors.New("capg_provider requires the name of the management cluster, the ssh configuration and the management cluster kubeconfig")
}

if mgmtKubeConfig == nil {
mgmtKubeConfig = thread.Local(identifiers.kubeCfg).(*starlarkstruct.Struct)
}
mgmtKubeConfigPath, err := getKubeConfigPathFromStruct(mgmtKubeConfig)
if err != nil {
return starlark.None, errors.Wrap(err, "failed to extract management kubeconfig")
}

// if workload cluster is not supplied, then the resources for the management cluster
// should be enumerated
clusterName := workloadCluster
if clusterName == "" {
config, err := k8s.LoadKubeCfg(mgmtKubeConfigPath)
if err != nil {
return starlark.None, errors.Wrap(err, "failed to load kube config")
}
clusterName, err = config.GetClusterName()
if err != nil {
return starlark.None, errors.Wrap(err, "cannot find cluster with name "+workloadCluster)
}
}

providerConfigPath, err := provider.KubeConfig(mgmtKubeConfigPath, clusterName, namespace)
if err != nil {
return starlark.None, err
}

nodeAddresses, err := k8s.GetNodeAddresses(ctx, providerConfigPath, toSlice(names), toSlice(labels))
if err != nil {
return starlark.None, errors.Wrap(err, "could not fetch host addresses")
}

// dictionary for capg provider struct
capgProviderDict := starlark.StringDict{
"kind": starlark.String(identifiers.capgProvider),
"transport": starlark.String("ssh"),
"kube_config": starlark.String(providerConfigPath),
}

// add node info to dictionary
var nodeIps []starlark.Value
for _, node := range nodeAddresses {
nodeIps = append(nodeIps, starlark.String(node))
}
capgProviderDict["hosts"] = starlark.NewList(nodeIps)

sshConfigDict := starlark.StringDict{}
sshConfig.ToStringDict(sshConfigDict)

capgProviderDict[identifiers.sshCfg] = starlarkstruct.FromStringDict(starlark.String(identifiers.sshCfg), sshConfigDict)

return starlarkstruct.FromStringDict(starlark.String(identifiers.capgProvider), capgProviderDict), nil
}
2 changes: 1 addition & 1 deletion starlark/kube_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.capgProvider && constStr != identifiers.capaProvider {
return starlark.None, errors.New("unknown capi provider")
}
}
Expand Down
1 change: 1 addition & 0 deletions starlark/starlark_exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.capgProvider: starlark.NewBuiltin(identifiers.capgProvider, CapgProviderFn),
identifiers.setDefaults: starlark.NewBuiltin(identifiers.setDefaults, SetDefaultsFunc),
identifiers.log: starlark.NewBuiltin(identifiers.log, logFunc),
}
Expand Down
2 changes: 2 additions & 0 deletions starlark/support.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ var (
kubeNodesProvider string
capvProvider string
capaProvider string
capgProvider string

sshAgent string
}{
Expand Down Expand Up @@ -91,6 +92,7 @@ var (
kubeNodesProvider: "kube_nodes_provider",
capvProvider: "capv_provider",
capaProvider: "capa_provider",
capgProvider: "capg_provider",

sshAgent: "crashd_ssh_agent",
}
Expand Down