Skip to content

Commit

Permalink
Stackstate P0 checks (rancher#47623)
Browse files Browse the repository at this point in the history
* Initial PR

* Stack state p0 cases automation

* Adding the rbac tests for stackstate

* New changes to accomodate node driver cleanup

* Updates from PR reviews

* Updates from PR reviews

* Adding REadme

* More updates after pr reviews

* Additional updates based on the offline discussion

* Latest review updates

* Debug

* Last few PR comment updates

* Skipping namespace creation if it exists
  • Loading branch information
anupama2501 authored Nov 12, 2024
1 parent 30b0b06 commit 186958f
Show file tree
Hide file tree
Showing 9 changed files with 1,318 additions and 3 deletions.
7 changes: 4 additions & 3 deletions tests/v2/actions/charts/charts.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ const (
// defaultRegistrySettingID is a private constant string that contains the ID of system default registry setting.
defaultRegistrySettingID = "system-default-registry"
// serverURLSettingID is a private constant string that contains the ID of server URL setting.
serverURLSettingID = "server-url"
rancherChartsName = "rancher-charts"
active = "active"
serverURLSettingID = "server-url"
rancherChartsName = "rancher-charts"
rancherPartnerCharts = "rancher-partner-charts"
active = "active"
)

// InstallOptions is a struct of the required options to install a chart.
Expand Down
287 changes: 287 additions & 0 deletions tests/v2/actions/charts/stackstate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,287 @@
package charts

import (
"context"
"fmt"

catalogv1 "github.com/rancher/rancher/pkg/apis/catalog.cattle.io/v1"
kubenamespaces "github.com/rancher/rancher/tests/v2/actions/kubeapi/namespaces"
"github.com/rancher/rancher/tests/v2/actions/namespaces"
"github.com/rancher/rancher/tests/v2/actions/observability"
"github.com/rancher/shepherd/clients/rancher"
"github.com/rancher/shepherd/extensions/defaults"
"github.com/rancher/shepherd/pkg/api/steve/catalog/types"
"github.com/rancher/shepherd/pkg/wait"
log "github.com/sirupsen/logrus"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/watch"
)

const (
// Public constants
StackstateExtensionNamespace = "cattle-ui-plugin-system"
StackstateExtensionsName = "observability"
UIPluginName = "rancher-ui-plugins"
StackstateK8sAgent = "stackstate-k8s-agent"
StackstateNamespace = "stackstate"
StackstateCRD = "observability.rancher.io.configuration"
RancherPartnerChartRepo = "rancher-partner-charts"
)

var (
timeoutSeconds = int64(defaults.TwoMinuteTimeout)
)

// InstallStackstateAgentChart is a private helper function that returns chart install action with stack state agent and payload options.
func InstallStackstateAgentChart(client *rancher.Client, installOptions *InstallOptions, stackstateConfigs *observability.StackStateConfig, systemProjectID string) error {
serverSetting, err := client.Management.Setting.ByID(serverURLSettingID)
if err != nil {
log.Info("Error getting server setting.")
return err
}

stackstateAgentChartInstallActionPayload := &payloadOpts{
InstallOptions: *installOptions,
Name: StackstateK8sAgent,
Namespace: StackstateNamespace,
Host: serverSetting.Value,
}

chartInstallAction := newStackstateAgentChartInstallAction(stackstateAgentChartInstallActionPayload, stackstateConfigs, systemProjectID)

catalogClient, err := client.GetClusterCatalogClient(installOptions.Cluster.ID)
if err != nil {
log.Info("Error getting catalogClient")
return err
}

// register uninstall stackstate agent as a cleanup function
client.Session.RegisterCleanupFunc(func() error {
defaultChartUninstallAction := newChartUninstallAction()

err := catalogClient.UninstallChart(StackstateK8sAgent, StackstateNamespace, defaultChartUninstallAction)
if err != nil {
return err
}

watchAppInterface, err := catalogClient.Apps(StackstateNamespace).Watch(context.TODO(), metav1.ListOptions{
FieldSelector: "metadata.name=" + StackstateK8sAgent,
TimeoutSeconds: &timeoutSeconds,
})
if err != nil {
return err
}

err = wait.WatchWait(watchAppInterface, func(event watch.Event) (ready bool, err error) {
chart := event.Object.(*catalogv1.App)
if event.Type == watch.Error {
return false, fmt.Errorf("there was an error uninstalling stackstate agent chart")
} else if event.Type == watch.Deleted {
return true, nil
} else if chart == nil {
return true, nil
}
return false, nil
})
if err != nil {
return err
}

steveclient, err := client.Steve.ProxyDownstream(installOptions.Cluster.ID)
if err != nil {
return err
}
namespaceClient := steveclient.SteveType(namespaces.NamespaceSteveType)

namespace, err := namespaceClient.ByID(StackstateNamespace)
if err != nil {
return err
}

err = namespaceClient.Delete(namespace)
if err != nil {
return err
}

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

adminDynamicClient, err := adminClient.GetDownStreamClusterClient(installOptions.Cluster.ID)
if err != nil {
return err
}

adminNamespaceResource := adminDynamicClient.Resource(kubenamespaces.NamespaceGroupVersionResource).Namespace("")

watchNamespaceInterface, err := adminNamespaceResource.Watch(context.TODO(), metav1.ListOptions{
FieldSelector: "metadata.name=" + StackstateNamespace,
TimeoutSeconds: &timeoutSeconds,
})
if err != nil {
return err
}

return wait.WatchWait(watchNamespaceInterface, func(event watch.Event) (ready bool, err error) {
if event.Type == watch.Deleted {
return true, nil
}
return false, nil
})
})

err = catalogClient.InstallChart(chartInstallAction, RancherPartnerChartRepo)
if err != nil {
log.Info("Errored installing the chart")
return err
}

// wait for chart to be fully deployed
watchAppInterface, err := catalogClient.Apps(StackstateNamespace).Watch(context.TODO(), metav1.ListOptions{
FieldSelector: "metadata.name=" + StackstateK8sAgent,
TimeoutSeconds: &defaults.WatchTimeoutSeconds,
})
if err != nil {
log.Info("Unable to obtain the installed app ")
return err
}

err = wait.WatchWait(watchAppInterface, func(event watch.Event) (ready bool, err error) {
app := event.Object.(*catalogv1.App)

state := app.Status.Summary.State
if state == string(catalogv1.StatusDeployed) {
return true, nil
}
return false, nil
})

if err != nil {
log.Info("Unable to obtain the status of the installed app ")
return err
}
return nil
}

// newStackstateAgentChartInstallAction is a helper function that returns an array of newChartInstallActions for installing the stackstate agent charts
func newStackstateAgentChartInstallAction(p *payloadOpts, stackstateConfigs *observability.StackStateConfig, systemProjectID string) *types.ChartInstallAction {
stackstateValues := map[string]interface{}{
"stackstate": map[string]interface{}{
"cluster": map[string]interface{}{
"name": p.Cluster.Name,
},
"apiKey": stackstateConfigs.ClusterApiKey,
"url": stackstateConfigs.Url,
},
}

chartInstall := newChartInstall(p.Name, p.Version, p.Cluster.ID, p.Cluster.Name, p.Host, rancherPartnerCharts, systemProjectID, p.DefaultRegistry, stackstateValues)

chartInstalls := []types.ChartInstall{*chartInstall}
chartInstallAction := newChartInstallAction(p.Namespace, p.ProjectID, chartInstalls)

return chartInstallAction
}

// UpgradeStackstateAgentChart is a helper function that upgrades the stackstate agent chart.
func UpgradeStackstateAgentChart(client *rancher.Client, installOptions *InstallOptions, stackstateConfigs *observability.StackStateConfig, systemProjectID string) error {
serverSetting, err := client.Management.Setting.ByID(serverURLSettingID)
if err != nil {
return err
}

stackstateAgentChartUpgradeActionPayload := &payloadOpts{
InstallOptions: *installOptions,
Name: StackstateK8sAgent,
Namespace: StackstateNamespace,
Host: serverSetting.Value,
}

chartUpgradeAction := newStackstateAgentChartUpgradeAction(stackstateAgentChartUpgradeActionPayload, stackstateConfigs)

catalogClient, err := client.GetClusterCatalogClient(installOptions.Cluster.ID)
if err != nil {
return err
}

err = catalogClient.UpgradeChart(chartUpgradeAction, RancherPartnerChartRepo)
if err != nil {
return err
}

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

adminCatalogClient, err := adminClient.GetClusterCatalogClient(installOptions.Cluster.ID)
if err != nil {
return err
}

// wait for chart to be in status pending upgrade
watchAppInterface, err := adminCatalogClient.Apps(StackstateNamespace).Watch(context.TODO(), metav1.ListOptions{
FieldSelector: "metadata.name=" + StackstateK8sAgent,
TimeoutSeconds: &defaults.WatchTimeoutSeconds,
})
if err != nil {
return err
}

err = wait.WatchWait(watchAppInterface, func(event watch.Event) (ready bool, err error) {
app := event.Object.(*catalogv1.App)

state := app.Status.Summary.State
if state == string(catalogv1.StatusPendingUpgrade) {
return true, nil
}
return false, nil
})
if err != nil {
return err
}

watchAppInterface, err = adminCatalogClient.Apps(StackstateNamespace).Watch(context.TODO(), metav1.ListOptions{
FieldSelector: "metadata.name=" + StackstateK8sAgent,
TimeoutSeconds: &defaults.WatchTimeoutSeconds,
})
if err != nil {
return err
}

err = wait.WatchWait(watchAppInterface, func(event watch.Event) (ready bool, err error) {
app := event.Object.(*catalogv1.App)

state := app.Status.Summary.State
if state == string(catalogv1.StatusDeployed) {
return true, nil
}
return false, nil
})
if err != nil {
return err
}

return nil
}

// newStackstateAgentChartUpgradeAction is a private helper function that returns chart upgrade action.
func newStackstateAgentChartUpgradeAction(p *payloadOpts, stackstateConfigs *observability.StackStateConfig) *types.ChartUpgradeAction {

stackstateValues := map[string]interface{}{
"stackstate": map[string]interface{}{
"cluster": map[string]interface{}{
"name": p.Cluster.Name,
},
"apiKey": stackstateConfigs.ClusterApiKey,
"url": stackstateConfigs.Url,
},
}

chartUpgrade := newChartUpgrade(p.Name, p.Name, p.Version, p.Cluster.ID, p.Cluster.Name, p.Host, p.DefaultRegistry, stackstateValues)
chartUpgrades := []types.ChartUpgrade{*chartUpgrade}
chartUpgradeAction := newChartUpgradeAction(p.Namespace, chartUpgrades)

return chartUpgradeAction
}
8 changes: 8 additions & 0 deletions tests/v2/actions/observability/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package observability

type StackStateConfig struct {
ServiceToken string `json:"serviceToken" yaml:"serviceToken"`
Url string `json:"url" yaml:"url"`
ClusterApiKey string `json:"clusterApiKey" yaml:"clusterApiKey"`
UpgradeVersion string `json:"upgradeVersion" yaml:"upgradeVersion"`
}
Loading

0 comments on commit 186958f

Please sign in to comment.