diff --git a/tests/v2/actions/clustertemplates/clustertemplates.go b/tests/v2/actions/clustertemplates/clustertemplates.go new file mode 100644 index 00000000000..04a56829409 --- /dev/null +++ b/tests/v2/actions/clustertemplates/clustertemplates.go @@ -0,0 +1,75 @@ +package clustertemplates + +import ( + "context" + "time" + + "github.com/rancher/shepherd/clients/rancher" + mgmt "github.com/rancher/shepherd/clients/rancher/generated/management/v3" + "github.com/rancher/shepherd/extensions/defaults" + namegen "github.com/rancher/shepherd/pkg/namegenerator" + kwait "k8s.io/apimachinery/pkg/util/wait" +) + +const ( + CniCalico = "calico" + ClusterEnforcementSetting = "cluster-template-enforcement" + EnabledClusterEnforcementSetting = "true" + DisabledClusterEnforcementSetting = "false" + IsRequiredQuestion = true + UserPrincipalID = "local://" +) + +// NewRKE1ClusterTemplateRevisionTemplate is a constructor that creates and returns config required to create cluster template revisions +func NewRKE1ClusterTemplateRevisionTemplate(templateRevisionConfig mgmt.ClusterTemplateRevision, templateId string) mgmt.ClusterTemplateRevision { + clusterConfig := mgmt.ClusterSpecBase{ + RancherKubernetesEngineConfig: &mgmt.RancherKubernetesEngineConfig{ + Version: templateRevisionConfig.ClusterConfig.RancherKubernetesEngineConfig.Version, + Network: &mgmt.NetworkConfig{ + Plugin: templateRevisionConfig.ClusterConfig.RancherKubernetesEngineConfig.Network.Plugin, + }, + }, + } + + var rkeTemplateConfig = mgmt.ClusterTemplateRevision{ + Name: namegen.AppendRandomString("rketemplate-revision-"), + ClusterTemplateID: templateId, + ClusterConfig: &clusterConfig, + Questions: templateRevisionConfig.Questions, + } + return rkeTemplateConfig +} + +// CreateRkeTemplate is a helper that creates an rke1 template in the rancher server +func CreateRkeTemplate(client *rancher.Client, members []mgmt.Member) (*mgmt.ClusterTemplate, error) { + rkeTemplateName := mgmt.ClusterTemplate{ + Name: namegen.AppendRandomString("rketemplate-"), + Members: members, + } + createTemplate, err := client.Management.ClusterTemplate.Create(&rkeTemplateName) + + return createTemplate, err +} + +// CreateRkeTemplateRevision is a helper that takes an rke1 template revision config and create an rke1 template revision config. +func CreateRkeTemplateRevision(client *rancher.Client, templateRevisionConfig mgmt.ClusterTemplateRevision, templateId string) (*mgmt.ClusterTemplateRevision, error) { + rkeTemplateConfig := NewRKE1ClusterTemplateRevisionTemplate(templateRevisionConfig, templateId) + + clusterTemplateRevision, err := client.Management.ClusterTemplateRevision.Create(&rkeTemplateConfig) + if err != nil { + return nil, err + } + err = kwait.PollUntilContextTimeout(context.TODO(), 500*time.Millisecond, defaults.ThirtyMinuteTimeout, true, func(ctx context.Context) (done bool, err error) { + clusterTemplateRevision, err := client.Management.ClusterTemplateRevision.ByID(clusterTemplateRevision.ID) + if err != nil { + return false, err + } + + return clusterTemplateRevision.State == "active", nil + }) + if err != nil { + return nil, err + } + + return clusterTemplateRevision, nil +} diff --git a/tests/v2/actions/provisioning/creates.go b/tests/v2/actions/provisioning/creates.go index b26cec4cb71..a0fe847883c 100644 --- a/tests/v2/actions/provisioning/creates.go +++ b/tests/v2/actions/provisioning/creates.go @@ -1066,3 +1066,37 @@ func DisableUpdateConfig(client *rancher.Client) { return nil }) } + +// CreateProvisioningRKE1ClusterWithClusterTemplate provisions an rke1 cluster by using the rke1 template and revision ID and other values from the template. +func CreateProvisioningRKE1ClusterWithClusterTemplate(client *rancher.Client, templateID, revisionID string, nodesAndRoles []provisioninginput.NodePools, nodeTemplate *nodetemplates.NodeTemplate, answers *management.Answer) (*management.Cluster, error) { + clusterName := namegen.AppendRandomString("rke1cluster-template-") + + rke1Cluster := &management.Cluster{ + DockerRootDir: "/var/lib/docker", + Name: namegen.AppendRandomString("rketemplate-cluster-"), + ClusterTemplateID: templateID, + ClusterTemplateRevisionID: revisionID, + ClusterTemplateAnswers: answers, + RancherKubernetesEngineConfig: nil, + } + clusterResp, err := shepherdclusters.CreateRKE1Cluster(client, rke1Cluster) + if err != nil { + return nil, err + } + + if client.Flags.GetValue(environmentflag.UpdateClusterName) { + pipeline.UpdateConfigClusterName(clusterName) + } + + var nodeRoles []nodepools.NodeRoles + for _, nodes := range nodesAndRoles { + nodeRoles = append(nodeRoles, nodes.NodeRoles) + } + _, err = nodepools.NodePoolSetup(client, nodeRoles, clusterResp.ID, nodeTemplate.ID) + if err != nil { + return nil, err + } + + createdCluster, err := client.Management.Cluster.ByID(clusterResp.ID) + return createdCluster, err +} diff --git a/tests/v2/validation/clustertemplates/provisioning/README.md b/tests/v2/validation/clustertemplates/provisioning/README.md new file mode 100644 index 00000000000..9bfb87c1ac1 --- /dev/null +++ b/tests/v2/validation/clustertemplates/provisioning/README.md @@ -0,0 +1,67 @@ +## Cluster template Provisioning Config + +For your config, you will need everything in the with and at least one [Cloud Credential](../../provisioning/rke1/README.md#cloud-credentials). + +Your GO test_package should be set to `provisioning/clustertemplates`. +Your GO suite should be set to `-run ^TestClusterTemplateRKE1ProvisioningTestSuite$`. +Please see below for more details for your config. Please note that the config can be in either JSON or YAML (all examples are illustrated in YAML). + +## Note: +Test uses node drivers provisioning. This is an example config. we can make use of other node drivers like, Linode, DO etc. For reference, please check [RKE1 Node Drivers Config](../../provisioning/rke1/README.md#nodetemplateconfigs) + +## Table of Contents +1. [Getting Started](#Getting-Started) + +## Getting Started +See below a sample config file to run this test: +```yaml +rancher: + host: "" #required + adminToken: "" #required + clusterName: "" + +provisioningInput: + RKE1KubernetesVersions: [""] #optional. if empty, latest version is considered. + cni: ["calico"] #optional, if empty, calico is considered. + providers: ["aws"] #required (at least 1) + +amazonec2Config: + accessKey: "" + secretKey: "" + ami: "ami-0e6577a75723c81f8" + blockDurationMinutes: "0" + encryptEbsVolume: false + endpoint: "" + httpEndpoint: "enabled" + httpTokens: "optional" + iamInstanceProfile: "" + insecureTransport: false + instanceType: "t3.xlarge" + keypairName: "" + kmsKey: "" + monitoring: false + privateAddressOnly: false + region: "us-east-2" + requestSpotInstance: false + retries: "5" + rootSize: "100" + securityGroup: [] + securityGroupReadonly: false + sessionToken: "" + spotPrice: "0.50" + sshKeyContents: "" + sshUser: "ubuntu" + subnetId: "" + tags: "" + type: "amazonec2Config" + useEbsOptimizedInstance: false + usePrivateAddress: false + userdata: "" + volumeType: "gp2" + vpcId: "vpc-bfccf4d7" + zone: "a" +``` + +These tests utilize Go build tags. Due to this, see the below example on how to run the test: + +`gotestsum --format standard-verbose --packages=github.com/rancher/rancher/tests/v2/validation/provisioning/clustertemplates --junitfile results.xml -- -timeout=120m -tags=validation -v -run "TestClusterTemplateRKE1ProvisioningTestSuite/TestProvisioningRKE1ClusterWithClusterTemplate"` \ No newline at end of file diff --git a/tests/v2/validation/clustertemplates/provisioning/clustertemplate_export_test.go b/tests/v2/validation/clustertemplates/provisioning/clustertemplate_export_test.go new file mode 100644 index 00000000000..edfeae1500e --- /dev/null +++ b/tests/v2/validation/clustertemplates/provisioning/clustertemplate_export_test.go @@ -0,0 +1,128 @@ +package clustertemplates + +import ( + "testing" + + "github.com/rancher/rancher/tests/v2/actions/clusters" + "github.com/rancher/rancher/tests/v2/actions/clustertemplates" + "github.com/rancher/rancher/tests/v2/actions/provisioning" + "github.com/rancher/rancher/tests/v2/actions/provisioninginput" + "github.com/rancher/shepherd/clients/rancher" + mgmt "github.com/rancher/shepherd/clients/rancher/generated/management/v3" + "github.com/rancher/shepherd/extensions/clusters/kubernetesversions" + "github.com/rancher/shepherd/extensions/users" + "github.com/rancher/shepherd/pkg/config" + "github.com/rancher/shepherd/pkg/namegenerator" + "github.com/rancher/shepherd/pkg/session" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + + log "github.com/sirupsen/logrus" +) + +type ClusterTemplateExportTestSuite struct { + suite.Suite + client *rancher.Client + session *session.Session + provisioningConfig *provisioninginput.Config + cluster *mgmt.Cluster +} + +func (ct *ClusterTemplateExportTestSuite) TearDownSuite() { + ct.session.Cleanup() +} + +func (ct *ClusterTemplateExportTestSuite) SetupSuite() { + testSession := session.NewSession() + ct.session = testSession + + ct.provisioningConfig = new(provisioninginput.Config) + config.LoadConfig(provisioninginput.ConfigurationFileKey, ct.provisioningConfig) + + client, err := rancher.NewClient("", testSession) + require.NoError(ct.T(), err) + + ct.client = client + + if ct.provisioningConfig.RKE1KubernetesVersions == nil { + rke1Versions, err := kubernetesversions.ListRKE1AllVersions(ct.client) + require.NoError(ct.T(), err) + + ct.provisioningConfig.RKE1KubernetesVersions = []string{rke1Versions[len(rke1Versions)-1]} + } + + if ct.provisioningConfig.CNIs == nil { + ct.provisioningConfig.CNIs = []string{clustertemplates.CniCalico} + } + + log.Info("Create a standard user.") + user, err := users.CreateUserWithRole(ct.client, users.UserConfig(), "user") + require.NoError(ct.T(), err) + standardClient, err := ct.client.AsUser(user) + require.NoError(ct.T(), err) + + log.Info("Creating an rke1 cluster") + + rke1Provider := provisioning.CreateRKE1Provider(ct.provisioningConfig.Providers[0]) + nodeTemplate, err := rke1Provider.NodeTemplateFunc(standardClient) + require.NoError(ct.T(), err) + + clusterConfig := clusters.ConvertConfigToClusterConfig(ct.provisioningConfig) + + nodeAndRoles := []provisioninginput.NodePools{ + provisioninginput.AllRolesNodePool, + } + clusterConfig.NodePools = nodeAndRoles + + clusterConfig.CNI = ct.provisioningConfig.CNIs[0] + clusterConfig.KubernetesVersion = ct.provisioningConfig.RKE1KubernetesVersions[0] + + cluster, err := provisioning.CreateProvisioningRKE1Cluster(standardClient, rke1Provider, clusterConfig, nodeTemplate) + require.NoError(ct.T(), err) + + ct.cluster, err = ct.client.Management.Cluster.ByID(cluster.ID) + require.NoError(ct.T(), err) + + provisioning.VerifyRKE1Cluster(ct.T(), standardClient, clusterConfig, ct.cluster) +} + +func (ct *ClusterTemplateExportTestSuite) TestExportClusterTemplate() { + + log.Info("Exporting the newly cluster after its provisioned as a cluster template.") + rkeTemplateExport, err := ct.client.Management.Cluster.ActionSaveAsTemplate(ct.cluster, + &mgmt.SaveAsTemplateInput{ClusterTemplateName: namegenerator.AppendRandomString("template"), + ClusterTemplateRevisionName: namegenerator.AppendRandomString("revision")}) + require.NoError(ct.T(), err) + + template, err := ct.client.Management.ClusterTemplateRevision.ByID(rkeTemplateExport.ClusterTemplateRevisionName) + require.NoError(ct.T(), err) + require.Equal(ct.T(), template.ClusterConfig.RancherKubernetesEngineConfig.Version, ct.cluster.RancherKubernetesEngineConfig.Version) + + log.Info("Create an rke1 cluster with template revision1") + + rke1Provider := provisioning.CreateRKE1Provider(ct.provisioningConfig.Providers[0]) + nodeTemplate, err := rke1Provider.NodeTemplateFunc(ct.client) + require.NoError(ct.T(), err) + + nodeAndRoles := []provisioninginput.NodePools{ + provisioninginput.AllRolesNodePool, + } + + log.Info("Create a downstream cluster with the rke1 template") + + clusterObj, err := provisioning.CreateProvisioningRKE1ClusterWithClusterTemplate(ct.client, template.ID, rkeTemplateExport.ClusterTemplateRevisionName, + nodeAndRoles, nodeTemplate, nil) + require.NoError(ct.T(), err) + + log.Info("Verifying the rke1 cluster comes up active.") + + clusterConfig := clusters.ConvertConfigToClusterConfig(ct.provisioningConfig) + clusterConfig.KubernetesVersion = ct.provisioningConfig.RKE1KubernetesVersions[0] + provisioning.VerifyRKE1Cluster(ct.T(), ct.client, clusterConfig, clusterObj) +} + +// In order for 'go test' to run this suite, we need to create +// a normal test function and pass our suite to suite.Run +func TestExportClusterTemplateTestSuite(t *testing.T) { + suite.Run(t, new(ClusterTemplateExportTestSuite)) +} diff --git a/tests/v2/validation/clustertemplates/provisioning/provisioning_clustertemplate_test.go b/tests/v2/validation/clustertemplates/provisioning/provisioning_clustertemplate_test.go new file mode 100644 index 00000000000..dfc6458ae70 --- /dev/null +++ b/tests/v2/validation/clustertemplates/provisioning/provisioning_clustertemplate_test.go @@ -0,0 +1,305 @@ +//go:build (validation || sanity) && !infra.any && !infra.aks && !infra.eks && !infra.rke2k3s && !infra.gke && !infra.rke1 && !cluster.any && !cluster.custom && !cluster.nodedriver && !extended && !stress + +package clustertemplates + +import ( + "strconv" + "testing" + + "github.com/rancher/rancher/tests/v2/actions/clusters" + "github.com/rancher/rancher/tests/v2/actions/clustertemplates" + "github.com/rancher/rancher/tests/v2/actions/provisioning" + "github.com/rancher/rancher/tests/v2/actions/provisioninginput" + "github.com/rancher/shepherd/clients/rancher" + mgmt "github.com/rancher/shepherd/clients/rancher/generated/management/v3" + extensionscluster "github.com/rancher/shepherd/extensions/clusters" + "github.com/rancher/shepherd/extensions/clusters/kubernetesversions" + "github.com/rancher/shepherd/extensions/settings" + "github.com/rancher/shepherd/extensions/users" + "github.com/rancher/shepherd/pkg/config" + "github.com/rancher/shepherd/pkg/namegenerator" + + "github.com/rancher/shepherd/pkg/session" + log "github.com/sirupsen/logrus" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +var ( + Questions = []mgmt.Question{ + 0: { + Variable: "rancherKubernetesEngineConfig.kubernetesVersion", + Default: "", + Required: clustertemplates.IsRequiredQuestion, + Type: "string", + }, + 1: { + Variable: "rancherKubernetesEngineConfig.network.plugin", + Default: "", + Required: clustertemplates.IsRequiredQuestion, + Type: "string", + }, + 2: { + Variable: "rancherKubernetesEngineConfig.services.etcd.backupConfig.intervalHours", + Default: "", + Required: clustertemplates.IsRequiredQuestion, + Type: "int", + }, + } +) + +type ClusterTemplateProvisioningTestSuite struct { + suite.Suite + client *rancher.Client + standardClient *rancher.Client + session *session.Session + provisioningConfig *provisioninginput.Config +} + +func (ct *ClusterTemplateProvisioningTestSuite) TearDownSuite() { + ct.session.Cleanup() +} + +func (ct *ClusterTemplateProvisioningTestSuite) SetupSuite() { + testSession := session.NewSession() + ct.session = testSession + + ct.provisioningConfig = new(provisioninginput.Config) + config.LoadConfig(provisioninginput.ConfigurationFileKey, ct.provisioningConfig) + + client, err := rancher.NewClient("", testSession) //ct.client + require.NoError(ct.T(), err) + + ct.client = client + + if ct.provisioningConfig.RKE1KubernetesVersions == nil { + rke1Versions, err := kubernetesversions.ListRKE1AllVersions(ct.client) + require.NoError(ct.T(), err) + + ct.provisioningConfig.RKE1KubernetesVersions = []string{rke1Versions[len(rke1Versions)-1]} + } + + if ct.provisioningConfig.CNIs == nil { + ct.provisioningConfig.CNIs = []string{clustertemplates.CniCalico} + } + + user, err := users.CreateUserWithRole(ct.client, users.UserConfig(), "user") + require.NoError(ct.T(), err) + ct.standardClient, err := ct.client.AsUser(user) + require.NoError(ct.T(), err) +} + +func (ct *ClusterTemplateProvisioningTestSuite) TestProvisioningRKE1ClusterWithClusterTemplate() { + log.Info("Create an rke template and creating a downstream node driver with the rke template.") + + clusterTemplate, err := clustertemplates.CreateRkeTemplate(ct.client, nil) + require.NoError(ct.T(), err) + + templateRevisonConfig := mgmt.ClusterTemplateRevision{ + ClusterConfig: &mgmt.ClusterSpecBase{ + RancherKubernetesEngineConfig: &mgmt.RancherKubernetesEngineConfig{ + Network: &mgmt.NetworkConfig{Plugin: ct.provisioningConfig.CNIs[0]}, + Version: ct.provisioningConfig.RKE1KubernetesVersions[0], + }, + }, + } + + clusterTemplateRevision, err := clustertemplates.CreateRkeTemplateRevision(ct.client, templateRevisonConfig, clusterTemplate.ID) + require.NoError(ct.T(), err) + + rke1Provider := provisioning.CreateRKE1Provider(ct.provisioningConfig.Providers[0]) + nodeTemplate, err := rke1Provider.NodeTemplateFunc(ct.client) + require.NoError(ct.T(), err) + + nodeAndRoles := []provisioninginput.NodePools{ + provisioninginput.AllRolesNodePool, + } + + clusterObj, err := provisioning.CreateProvisioningRKE1ClusterWithClusterTemplate(ct.client, clusterTemplate.ID, clusterTemplateRevision.ID, + nodeAndRoles, nodeTemplate, nil) + require.NoError(ct.T(), err) + + log.Info("Verifying the rke1 cluster comes up active.") + + clusterConfig := clusters.ConvertConfigToClusterConfig(ct.provisioningConfig) + clusterConfig.KubernetesVersion = ct.provisioningConfig.RKE1KubernetesVersions[0] + provisioning.VerifyRKE1Cluster(ct.T(), ct.client, clusterConfig, clusterObj) +} + +func (ct *ClusterTemplateProvisioningTestSuite) TestClusterTemplateEnforcementAsAdmin() { + log.Info("Enforcing cluster template while provisioning rke1 clusters") + + clusterEnforcement, err := ct.client.Steve.SteveType(settings.ManagementSetting).ByID(clustertemplates.ClusterEnforcementSetting) + require.NoError(ct.T(), err) + _, err = settings.UpdateGlobalSettings(ct.client.Steve, clusterEnforcement, clustertemplates.EnabledClusterEnforcementSetting) + require.NoError(ct.T(), err) + + verifySetting, err := ct.client.Steve.SteveType(settings.ManagementSetting).ByID(clustertemplates.ClusterEnforcementSetting) + require.NoError(ct.T(), err) + require.Equal(ct.T(), verifySetting.JSONResp["value"], clustertemplates.EnabledClusterEnforcementSetting) + + log.Info("Creating a cluster template and verifying the user is not able to create the cluster without the required permissions.") + clusterTemplate, err := clustertemplates.CreateRkeTemplate(ct.client, nil) + require.NoError(ct.T(), err) + + templateRevisonConfig := mgmt.ClusterTemplateRevision{ + ClusterConfig: &mgmt.ClusterSpecBase{ + RancherKubernetesEngineConfig: &mgmt.RancherKubernetesEngineConfig{ + Network: &mgmt.NetworkConfig{Plugin: ct.provisioningConfig.CNIs[0]}, + Version: ct.provisioningConfig.RKE1KubernetesVersions[0], + }, + }, + } + + clusterTemplateRevision, err := clustertemplates.CreateRkeTemplateRevision(ct.client, templateRevisonConfig, clusterTemplate.ID) + require.NoError(ct.T(), err) + + log.Info("Create a downstream cluster as an admin.") + + rke1Provider := provisioning.CreateRKE1Provider(ct.provisioningConfig.Providers[0]) + nodeTemplate, err := rke1Provider.NodeTemplateFunc(ct.client) + require.NoError(ct.T(), err) + + nodeAndRoles := []provisioninginput.NodePools{ + provisioninginput.AllRolesNodePool, + } + + log.Info("Verifying admin can create the cluster with the cluster template even when rke cluster template is enforced.") + clusterObj, err := provisioning.CreateProvisioningRKE1ClusterWithClusterTemplate(ct.client, clusterTemplate.ID, clusterTemplateRevision.ID, + nodeAndRoles, nodeTemplate, nil) + require.NoError(ct.T(), err) + + log.Info("Verifying the rke1 cluster comes up active.") + clusterConfig := clusters.ConvertConfigToClusterConfig(ct.provisioningConfig) + clusterConfig.KubernetesVersion = ct.provisioningConfig.RKE1KubernetesVersions[0] + provisioning.VerifyRKE1Cluster(ct.T(), ct.client, clusterConfig, clusterObj) + + log.Info("Update the global setting to enforce rke templates back to false.") + clusterEnforcement, err = ct.client.Steve.SteveType(settings.ManagementSetting).ByID(clustertemplates.ClusterEnforcementSetting) + require.NoError(ct.T(), err) + _, err = settings.UpdateGlobalSettings(ct.client.Steve, clusterEnforcement, clustertemplates.DisabledClusterEnforcementSetting) + require.NoError(ct.T(), err) + + verifySetting, err = ct.client.Steve.SteveType(settings.ManagementSetting).ByID(clustertemplates.ClusterEnforcementSetting) + require.NoError(ct.T(), err) + require.Equal(ct.T(), verifySetting.JSONResp["value"], clustertemplates.DisabledClusterEnforcementSetting) +} + +func (ct *ClusterTemplateProvisioningTestSuite) TestClusterTemplateWithQuestionsAndAnswers() { + log.Info("Creating an rke template with questions") + + clusterTemplate, err := clustertemplates.CreateRkeTemplate(ct.client, nil) + require.NoError(ct.T(), err) + + answers := &mgmt.Answer{Values: map[string]string{ + "rancherKubernetesEngineConfig.kubernetesVersion": ct.provisioningConfig.RKE1KubernetesVersions[0], + "rancherKubernetesEngineConfig.network.plugin": ct.provisioningConfig.CNIs[0], + "rancherKubernetesEngineConfig.services.etcd.backupConfig.intervalHours": "10", + }} + + templateRevisonConfig := mgmt.ClusterTemplateRevision{ + ClusterConfig: &mgmt.ClusterSpecBase{RancherKubernetesEngineConfig: &mgmt.RancherKubernetesEngineConfig{ + Network: &mgmt.NetworkConfig{Plugin: ct.provisioningConfig.CNIs[0]}, + Version: ct.provisioningConfig.RKE1KubernetesVersions[0], + }, + }, + Questions: Questions, + } + + clusterTemplateRevision, err := clustertemplates.CreateRkeTemplateRevision(ct.client, templateRevisonConfig, clusterTemplate.ID) + require.NoError(ct.T(), err) + + rke1Provider := provisioning.CreateRKE1Provider(ct.provisioningConfig.Providers[0]) + nodeTemplate, err := rke1Provider.NodeTemplateFunc(ct.client) + require.NoError(ct.T(), err) + + nodeAndRoles := []provisioninginput.NodePools{ + provisioninginput.AllRolesNodePool, + } + + clusterObj, err := provisioning.CreateProvisioningRKE1ClusterWithClusterTemplate(ct.client, clusterTemplate.ID, clusterTemplateRevision.ID, + nodeAndRoles, nodeTemplate, answers) + require.NoError(ct.T(), err) + + log.Info("Verifying the rke1 cluster comes up active and the cluster object has the same answer values provided.") + + expectedHours := answers.Values["rancherKubernetesEngineConfig.services.etcd.backupConfig.intervalHours"] + actualIntervalHoursAnswers := strconv.FormatInt(clusterObj.RancherKubernetesEngineConfig.Services.Etcd.BackupConfig.IntervalHours, 10) + require.Equal(ct.T(), actualIntervalHoursAnswers, expectedHours) + + clusterConfig := clusters.ConvertConfigToClusterConfig(ct.provisioningConfig) + clusterConfig.KubernetesVersion = ct.provisioningConfig.RKE1KubernetesVersions[0] + provisioning.VerifyRKE1Cluster(ct.T(), ct.client, clusterConfig, clusterObj) +} + +func (ct *ClusterTemplateProvisioningTestSuite) TestClusterTemplateEditAsAdmin() { + log.Info("Creating an rke template with two revisions") + + clusterTemplate, err := clustertemplates.CreateRkeTemplate(ct.client, nil) + require.NoError(ct.T(), err) + + rke1Versions, err := kubernetesversions.ListRKE1AllVersions(ct.client) + require.NoError(ct.T(), err) + require.True(ct.T(), len(rke1Versions) > 2) + require.True(ct.T(), len(ct.provisioningConfig.CNIs[0]) > 1) + + templateRevisonConfig := mgmt.ClusterTemplateRevision{ + ClusterConfig: &mgmt.ClusterSpecBase{RancherKubernetesEngineConfig: &mgmt.RancherKubernetesEngineConfig{ + Network: &mgmt.NetworkConfig{Plugin: ct.provisioningConfig.CNIs[0]}, + Version: rke1Versions[len(rke1Versions)-2], + }}, + } + + ct.provisioningConfig.RKE1KubernetesVersions[0] = templateRevisonConfig.ClusterConfig.RancherKubernetesEngineConfig.Version + + clusterTemplateRevision1, err := clustertemplates.CreateRkeTemplateRevision(ct.client, templateRevisonConfig, clusterTemplate.ID) + require.NoError(ct.T(), err) + + log.Info("Creating rke1 template and rke template revision1") + templateRevisonConfig.ClusterConfig.RancherKubernetesEngineConfig.Version = rke1Versions[len(rke1Versions)-1] + + log.Info("Creating a new rke template revisions in the previously created template") + templateRevision2, err := clustertemplates.CreateRkeTemplateRevision(ct.client, templateRevisonConfig, clusterTemplate.ID) + require.NoError(ct.T(), err) + + log.Info("Create an rke1 cluster with template revision1") + + rke1Provider := provisioning.CreateRKE1Provider(ct.provisioningConfig.Providers[0]) + nodeTemplate, err := rke1Provider.NodeTemplateFunc(ct.client) + require.NoError(ct.T(), err) + + nodeAndRoles := []provisioninginput.NodePools{ + provisioninginput.AllRolesNodePool, + } + + clusterObj, err := provisioning.CreateProvisioningRKE1ClusterWithClusterTemplate(ct.client, clusterTemplate.ID, clusterTemplateRevision1.ID, + nodeAndRoles, nodeTemplate, nil) + require.NoError(ct.T(), err) + + log.Info("Verify the rke1 cluster comes up active.") + + clusterConfig := clusters.ConvertConfigToClusterConfig(ct.provisioningConfig) + clusterConfig.KubernetesVersion = rke1Versions[len(rke1Versions)-2] + provisioning.VerifyRKE1Cluster(ct.T(), ct.client, clusterConfig, clusterObj) + + log.Info("Update the rke1 cluster with template revision 2") + rke1Cluster := &mgmt.Cluster{ + Name: namegenerator.AppendRandomString("rketemplate-cluster-"), + ClusterTemplateID: clusterTemplate.ID, + ClusterTemplateRevisionID: templateRevision2.ID, + ClusterTemplateAnswers: nil, + RancherKubernetesEngineConfig: nil, + } + + updatedClusterObj, err := extensionscluster.UpdateRKE1Cluster(ct.client, clusterObj, rke1Cluster) + require.NoError(ct.T(), err) + + log.Info("Verify the updated rke1 cluster has new cluster revision values.") + require.Equal(ct.T(), clusterObj.Version, updatedClusterObj.Version) +} + +// In order for 'go test' to run this suite, we need to create +// a normal test function and pass our suite to suite.Run +func TestClusterTemplateRKE1ProvisioningTestSuite(t *testing.T) { + suite.Run(t, new(ClusterTemplateProvisioningTestSuite)) +} diff --git a/tests/v2/validation/clustertemplates/rbac/clustertemplate_test.go b/tests/v2/validation/clustertemplates/rbac/clustertemplate_test.go new file mode 100644 index 00000000000..2ce3f59e7bd --- /dev/null +++ b/tests/v2/validation/clustertemplates/rbac/clustertemplate_test.go @@ -0,0 +1,150 @@ +package rbac + +import ( + "testing" + + "github.com/rancher/rancher/tests/v2/actions/clusters" + "github.com/rancher/rancher/tests/v2/actions/clustertemplates" + "github.com/rancher/rancher/tests/v2/actions/provisioning" + "github.com/rancher/rancher/tests/v2/actions/provisioninginput" + "github.com/rancher/shepherd/clients/rancher" + mgmt "github.com/rancher/shepherd/clients/rancher/generated/management/v3" + "github.com/rancher/shepherd/extensions/clusters/kubernetesversions" + "github.com/rancher/shepherd/extensions/settings" + "github.com/rancher/shepherd/extensions/users" + "github.com/rancher/shepherd/pkg/config" + + "github.com/rancher/shepherd/pkg/session" + log "github.com/sirupsen/logrus" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +const ( + dockerDir = "/var/lib/docker" +) + +type ClusterTemplateRKE1RBACTestSuite struct { + suite.Suite + client *rancher.Client + session *session.Session + provisioningConfig *provisioninginput.Config +} + +func (ct *ClusterTemplateRKE1RBACTestSuite) TearDownSuite() { + ct.session.Cleanup() +} + +func (ct *ClusterTemplateRKE1RBACTestSuite) SetupSuite() { + testSession := session.NewSession() + ct.session = testSession + + ct.provisioningConfig = new(provisioninginput.Config) + config.LoadConfig(provisioninginput.ConfigurationFileKey, ct.provisioningConfig) + + client, err := rancher.NewClient("", testSession) //ct.client + require.NoError(ct.T(), err) + + ct.client = client + + if ct.provisioningConfig.RKE1KubernetesVersions == nil { + rke1Versions, err := kubernetesversions.ListRKE1AllVersions(ct.client) + require.NoError(ct.T(), err) + + ct.provisioningConfig.RKE1KubernetesVersions = []string{rke1Versions[len(rke1Versions)-1]} + } + + if ct.provisioningConfig.CNIs == nil { + ct.provisioningConfig.CNIs = []string{clustertemplates.CniCalico} + } + +} + +func (ct *ClusterTemplateRKE1RBACTestSuite) TestClusterTemplateEnforcementForStandardUser() { + log.Info("Enforcing cluster template while provisioning rke1 clusters") + + clusterEnforcement, err := ct.client.Steve.SteveType(settings.ManagementSetting).ByID(clustertemplates.ClusterEnforcementSetting) + require.NoError(ct.T(), err) + _, err = settings.UpdateGlobalSettings(ct.client.Steve, clusterEnforcement, clustertemplates.EnabledClusterEnforcementSetting) + require.NoError(ct.T(), err) + + verifySetting, err := ct.client.Steve.SteveType(settings.ManagementSetting).ByID(clustertemplates.ClusterEnforcementSetting) + require.NoError(ct.T(), err) + require.Equal(ct.T(), verifySetting.JSONResp["value"], clustertemplates.EnabledClusterEnforcementSetting) + + log.Info("Creating a cluster template and verifying the user is not able to create the cluster without the required permissions.") + clusterTemplate, err := clustertemplates.CreateRkeTemplate(ct.client, nil) + require.NoError(ct.T(), err) + + templateRevisonConfig := mgmt.ClusterTemplateRevision{ + ClusterConfig: &mgmt.ClusterSpecBase{RancherKubernetesEngineConfig: &mgmt.RancherKubernetesEngineConfig{ + Network: &mgmt.NetworkConfig{Plugin: ct.provisioningConfig.CNIs[0]}, + Version: ct.provisioningConfig.RKE1KubernetesVersions[0], + }, + }, + } + + clusterTemplateRevision, err := clustertemplates.CreateRkeTemplateRevision(ct.client, templateRevisonConfig, clusterTemplate.ID) + require.NoError(ct.T(), err) + + nodeAndRoles := []provisioninginput.NodePools{ + provisioninginput.AllRolesNodePool, + } + + log.Info("Create a downstream cluster as the standard user.") + + log.Info("Create a standard user.") + user, err := users.CreateUserWithRole(ct.client, users.UserConfig(), "user") + require.NoError(ct.T(), err) + standardClient, err := ct.client.AsUser(user) + require.NoError(ct.T(), err) + + rke1Provider := provisioning.CreateRKE1Provider(ct.provisioningConfig.Providers[0]) + nodeTemplate, err := rke1Provider.NodeTemplateFunc(standardClient) + require.NoError(ct.T(), err) + + _, err = provisioning.CreateProvisioningRKE1ClusterWithClusterTemplate(standardClient, clusterTemplate.ID, clusterTemplateRevision.ID, + nodeAndRoles, nodeTemplate, nil) + require.Error(ct.T(), err, "User is not expected to be able to create a cluster.") + require.Contains(ct.T(), err.Error(), "The clusterTemplateRevision is not found") + + log.Info("Verifying user can now create the cluster with the permissions added to the cluster template.") + + members := []mgmt.Member{ + 0: {AccessType: "owner", + UserPrincipalID: clustertemplates.UserPrincipalID + user.ID}, + } + + updatedMembersTemplate := *clusterTemplate + updatedMembersTemplate.Members = members + + _, err = ct.client.Management.ClusterTemplate.Update(clusterTemplate, updatedMembersTemplate) + require.NoError(ct.T(), err) + + clusterObj, err := provisioning.CreateProvisioningRKE1ClusterWithClusterTemplate(standardClient, clusterTemplate.ID, clusterTemplateRevision.ID, + nodeAndRoles, nodeTemplate, nil) + require.NoError(ct.T(), err) + + log.Info("Verifying the rke1 cluster comes up active.") + + clusterConfig := clusters.ConvertConfigToClusterConfig(ct.provisioningConfig) + clusterConfig.KubernetesVersion = ct.provisioningConfig.RKE1KubernetesVersions[0] + provisioning.VerifyRKE1Cluster(ct.T(), ct.client, clusterConfig, clusterObj) + + log.Info("Update the global setting to enforce rke templates back to false.") + + clusterEnforcement, err = ct.client.Steve.SteveType(settings.ManagementSetting).ByID(clustertemplates.ClusterEnforcementSetting) + require.NoError(ct.T(), err) + _, err = settings.UpdateGlobalSettings(ct.client.Steve, clusterEnforcement, clustertemplates.DisabledClusterEnforcementSetting) + require.NoError(ct.T(), err) + + verifySetting, err = ct.client.Steve.SteveType(settings.ManagementSetting).ByID(clustertemplates.ClusterEnforcementSetting) + require.NoError(ct.T(), err) + require.Equal(ct.T(), verifySetting.JSONResp["value"], clustertemplates.DisabledClusterEnforcementSetting) +} + +// In order for 'go test' to run this suite, we need to create +// a normal test function and pass our suite to suite.Run +func TestClusterTemplateRKE1RBACTestSuite(t *testing.T) { + suite.Run(t, new(ClusterTemplateRKE1RBACTestSuite)) +}