Skip to content
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
6 changes: 5 additions & 1 deletion .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ linters-settings:
disabled: true
- name: exported
disabled: false
goconst:
goconst:
min-len: 2
min-occurrences: 10
match-constant: true
Expand All @@ -39,3 +39,7 @@ issues:
- ^*\.yaml$
- ^*\.yml$
exclude-generated-strict: true
exclude-rules:
- path: extensions/kubeconfig/podlogs.go
linters:
- forbidigo
6 changes: 3 additions & 3 deletions clients/dynamic/dynamic.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type Client struct {
}

// NewForConfig creates a new dynamic client or returns an error.
func NewForConfig(ts *session.Session, inConfig *rest.Config) (dynamic.Interface, error) {
func NewForConfig(ts *session.Session, inConfig *rest.Config) (*Client, error) {
logrus.Debugf("Dynamic Client Host:%s", inConfig.Host)

dynamicClient, err := dynamic.NewForConfig(inConfig)
Expand All @@ -44,7 +44,7 @@ func NewForConfig(ts *session.Session, inConfig *rest.Config) (dynamic.Interface
// Version: "v3",
// Resource: "users",
// }
func (d *Client) Resource(resource schema.GroupVersionResource) dynamic.NamespaceableResourceInterface {
func (d *Client) Resource(resource schema.GroupVersionResource) *NamespaceableResourceClient {
return &NamespaceableResourceClient{
NamespaceableResourceInterface: d.Interface.Resource(resource),
ts: d.ts,
Expand All @@ -59,7 +59,7 @@ type NamespaceableResourceClient struct {
}

// Namespace returns a dynamic.ResourceInterface that is embedded in ResourceClient, so ultimately its Create is overwritten.
func (d *NamespaceableResourceClient) Namespace(s string) dynamic.ResourceInterface {
func (d *NamespaceableResourceClient) Namespace(s string) *ResourceClient {
return &ResourceClient{
ResourceInterface: d.NamespaceableResourceInterface.Namespace(s),
ts: d.ts,
Expand Down
68 changes: 49 additions & 19 deletions clients/helm/helm.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,19 @@ import (
"github.com/rancher/shepherd/pkg/session"
)

var helmCmd = "helm_v3"
var helmCmd = ""

func SetHelmCmd(command string) error {
helmCmd = "helm_v3"
if command != "" {
msg, err := exec.Command(command).CombinedOutput()
if err != nil {
return errors.Wrapf(err, "SetHelmCmd: errored while running `%s` %s", command, string(msg))
}
helmCmd = command
}
return nil
}

// InstallChart installs a helm chart using helm CLI.
// Send the helm set command strings such as "--set", "installCRDs=true"
Expand All @@ -34,12 +46,8 @@ func InstallChart(ts *session.Session, releaseName, helmRepo, namespace, version
commandArgs = append(commandArgs, "--version", version)
}

msg, err := exec.Command(helmCmd, commandArgs...).CombinedOutput()
if err != nil {
return errors.Wrap(err, "InstallChart: "+string(msg))
}

return nil
_, err := execCommand("InstallChart: ", commandArgs)
return err
}

// UpgradeChart upgrades a helm chart using helm CLI.
Expand Down Expand Up @@ -67,12 +75,24 @@ func UpgradeChart(ts *session.Session, releaseName, helmRepo, namespace, version
commandArgs = append(commandArgs, "--version", version)
}

msg, err := exec.Command(helmCmd, commandArgs...).CombinedOutput()
if err != nil {
return errors.Wrap(err, "UpgradeChart: "+string(msg))
_, err := execCommand("UpgradeChart: ", commandArgs)
return err

}

func GetValues(releaseName, namespace string, args ...string) (string, error) {
// Default helm upgrade command
commandArgs := []string{
"get",
"values",
releaseName,
"--namespace",
namespace,
}

return nil
commandArgs = append(commandArgs, args...)

return execCommand("GetValues: ", commandArgs)
}

// UninstallChart uninstalls a helm chart using helm CLI in a given namespace
Expand All @@ -87,20 +107,30 @@ func UninstallChart(releaseName, namespace string, args ...string) error {
"--wait",
}

msg, err := exec.Command(helmCmd, commandArgs...).CombinedOutput()
if err != nil {
return errors.Wrap(err, "UninstallChart: "+string(msg))
}
commandArgs = append(commandArgs, args...)

return nil
_, err := execCommand("UninstallChart: ", commandArgs)
return err
}

// AddHelmRepo adds the specified helm repository using the helm repo add command.
func AddHelmRepo(name, url string) error {
msg, err := exec.Command(helmCmd, "repo", "add", name, url).CombinedOutput()
commandArgs := []string{
"repo",
"add",
name,
url,
}

_, err := execCommand("AddHelmRepo: ", commandArgs)
return err
}

func execCommand(errMsg string, commandArgs []string) (string, error) {
msg, err := exec.Command(helmCmd, commandArgs...).CombinedOutput()
if err != nil {
return errors.Wrap(err, "AddHelmRepo: "+string(msg))
return "", errors.Wrap(err, errMsg+string(msg))
}

return nil
return string(msg), nil
}
8 changes: 4 additions & 4 deletions clients/rancher/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
management "github.com/rancher/shepherd/clients/rancher/generated/management/v3"
v1 "github.com/rancher/shepherd/clients/rancher/v1"

rancherDynamic "github.com/rancher/shepherd/clients/dynamic"
kubeProvisioning "github.com/rancher/shepherd/clients/provisioning"
"github.com/rancher/shepherd/clients/ranchercli"
kubeRKE "github.com/rancher/shepherd/clients/rke"
Expand All @@ -27,7 +28,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)
Expand Down Expand Up @@ -222,7 +222,7 @@ func (c *Client) GetClusterCatalogClient(clusterID string) (*catalog.Client, err
}

// GetRancherDynamicClient is a helper function that instantiates a dynamic client to communicate with the rancher host.
func (c *Client) GetRancherDynamicClient() (dynamic.Interface, error) {
func (c *Client) GetRancherDynamicClient() (*rancherDynamic.Client, error) {
dynamic, err := frameworkDynamic.NewForConfig(c.Session, c.restConfig)
if err != nil {
return nil, err
Expand Down Expand Up @@ -251,7 +251,7 @@ func (c *Client) GetKubeAPIRKEClient() (*kubeRKE.Client, error) {
}

// GetDownStreamClusterClient is a helper function that instantiates a dynamic client to communicate with a specific cluster.
func (c *Client) GetDownStreamClusterClient(clusterID string) (dynamic.Interface, error) {
func (c *Client) GetDownStreamClusterClient(clusterID string) (*rancherDynamic.Client, error) {
restConfig := *c.restConfig
restConfig.Host = fmt.Sprintf("https://%s/k8s/clusters/%s", c.restConfig.Host, clusterID)

Expand All @@ -263,7 +263,7 @@ func (c *Client) GetDownStreamClusterClient(clusterID string) (dynamic.Interface
}

// SwitchContext is a helper function that changes the current context to `context` and instantiates a dynamic client
func (c *Client) SwitchContext(context string, clientConfig *clientcmd.ClientConfig) (dynamic.Interface, error) {
func (c *Client) SwitchContext(context string, clientConfig *clientcmd.ClientConfig) (*rancherDynamic.Client, error) {
overrides := clientcmd.ConfigOverrides{CurrentContext: context}

rawConfig, err := (*clientConfig).RawConfig()
Expand Down
58 changes: 58 additions & 0 deletions extensions/clusters/clusters.go
Original file line number Diff line number Diff line change
Expand Up @@ -1278,6 +1278,43 @@ func WatchAndWaitForCluster(client *rancher.Client, steveID string) error {
return err
}

// WatchAndWaitForCluster is function that waits for a cluster to go unactive before checking its active state.
func WatchAndWaitForClusterWithTimeout(client *rancher.Client, steveID string, timeoutSeconds *int64) error {
var clusterResp *v1.SteveAPIObject
err := kwait.Poll(500*time.Millisecond, 2*time.Minute, func() (done bool, err error) {
clusterResp, err = client.Steve.SteveType(ProvisioningSteveResourceType).ByID(steveID)
if err != nil {
return false, err
}
state := clusterResp.ObjectMeta.State.Name
return state != "active", nil
})
if err != nil {
return err
}
logrus.Infof("waiting for cluster to be up.............")

adminClient, err := rancher.NewClient(client.RancherConfig.AdminToken, client.Session)
if err != nil {
return err
}
kubeProvisioningClient, err := adminClient.GetKubeAPIProvisioningClient()
if err != nil {
return err
}

result, err := kubeProvisioningClient.Clusters(clusterResp.ObjectMeta.Namespace).Watch(context.TODO(), metav1.ListOptions{
FieldSelector: "metadata.name=" + clusterResp.Name,
TimeoutSeconds: timeoutSeconds,
})
if err != nil {
return err
}

err = wait.WatchWait(result, IsProvisioningClusterReady)
return err
}

// GetProvisioningClusterByName is a helper function to get cluster object with the cluster name
func GetProvisioningClusterByName(client *rancher.Client, clusterName string, namespace string) (*apisV1.Cluster, *v1.SteveAPIObject, error) {
clusterObj, err := client.Steve.SteveType(ProvisioningSteveResourceType).ByID(namespace + "/" + clusterName)
Expand Down Expand Up @@ -1317,6 +1354,27 @@ func WaitForActiveRKE1Cluster(client *rancher.Client, clusterID string) error {
return nil
}

func WaitForActiveRKE1ClusterWithTimeout(client *rancher.Client, clusterID string, timeoutMinutes int) error {
err := kwait.Poll(500*time.Millisecond, 30*time.Minute, func() (done bool, err error) {
client, err = client.ReLogin()
if err != nil {
return false, err
}
clusterResp, err := client.Management.Cluster.ByID(clusterID)
if err != nil {
return false, err
}
if clusterResp.State == active {
return true, nil
}
return false, nil
})
if err != nil {
return err
}
return nil
}

// ListDownstreamClusters is a helper function to get the name of the downstream clusters
func ListDownstreamClusters(client *rancher.Client) (clusterNames []string, err error) {
clusterList, err := client.Steve.SteveType(ProvisioningSteveResourceType).ListAll(nil)
Expand Down
8 changes: 4 additions & 4 deletions extensions/codecoverage/codecoverage.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"time"

apiv1 "github.com/rancher/rancher/pkg/apis/provisioning.cattle.io/v1"
rancherDynamic "github.com/rancher/shepherd/clients/dynamic"
"github.com/rancher/shepherd/clients/rancher"
v1 "github.com/rancher/shepherd/clients/rancher/v1"
"github.com/rancher/shepherd/extensions/clusters"
Expand All @@ -17,7 +18,6 @@ import (
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kwait "k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/dynamic"
)

var podGroupVersionResource = corev1.SchemeGroupVersion.WithResource("pods")
Expand All @@ -30,7 +30,7 @@ const (
outputDir = "cover"
)

func checkServiceIsRunning(dynamicClient dynamic.Interface) error {
func checkServiceIsRunning(dynamicClient rancherDynamic.Client) error {
return kwait.Poll(500*time.Millisecond, 2*time.Minute, func() (done bool, err error) {
_, err = dynamicClient.Resource(podGroupVersionResource).Namespace(cattleSystemNameSpace).List(context.Background(), metav1.ListOptions{})
if k8sErrors.IsInternalError(err) || k8sErrors.IsServiceUnavailable(err) {
Expand Down Expand Up @@ -120,7 +120,7 @@ func KillRancherTestServicesRetrieveCoverage(client *rancher.Client) error {
return err
}

err = checkServiceIsRunning(dynamicClient)
err = checkServiceIsRunning(*dynamicClient)
if err != nil {
return err
}
Expand Down Expand Up @@ -169,7 +169,7 @@ func KillAgentTestServicesRetrieveCoverage(client *rancher.Client) error {
return err
}

err = checkServiceIsRunning(dynamicClient)
err = checkServiceIsRunning(*dynamicClient)
if err != nil {
return err
}
Expand Down
34 changes: 34 additions & 0 deletions extensions/kubeapi/cluster/operations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package cluster

import (
"context"

"github.com/rancher/shepherd/clients/rancher"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
)

const ManagementGroupName = "management.cattle.io"

func ManagementClusterGVR() schema.GroupVersionResource {
return schema.GroupVersionResource{Group: ManagementGroupName, Version: "v3", Resource: "clusters"}
}

// ListAll is a helper function that uses the dynamic client to return a list of all clusters.management.cattle.io.
func ListAll(client *rancher.Client, opts *metav1.ListOptions) (list *unstructured.UnstructuredList, err error) {
if opts == nil {
opts = &metav1.ListOptions{}
}

dynamic, err := client.GetRancherDynamicClient()
if err != nil {
return
}

unstructuredClusterList, err := dynamic.Resource(ManagementClusterGVR()).List(context.TODO(), *opts)
if err != nil {
return
}
return unstructuredClusterList, err
}
3 changes: 1 addition & 2 deletions extensions/kubeapi/cluster/summary.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"github.com/rancher/shepherd/clients/rancher"
"github.com/rancher/wrangler/pkg/summary"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
)

// IsClusterActive is a helper function that uses the dynamic client to return cluster's ready state.
Expand All @@ -16,7 +15,7 @@ func IsClusterActive(client *rancher.Client, clusterID string) (ready bool, err
return
}

unstructuredCluster, err := dynamic.Resource(schema.GroupVersionResource{Group: "management.cattle.io", Version: "v3", Resource: "clusters"}).Get(context.TODO(), clusterID, metav1.GetOptions{})
unstructuredCluster, err := dynamic.Resource(ManagementClusterGVR()).Get(context.TODO(), clusterID, metav1.GetOptions{})
if err != nil {
return
}
Expand Down
Loading