From b5b2251cde4fd44aeb87fe2cb8389023b88f53bb Mon Sep 17 00:00:00 2001 From: Caleb Warren Date: Fri, 8 Mar 2024 12:01:28 -0800 Subject: [PATCH] Enable automated install of vsphere cpi/csi --- clients/rancher/catalog/clusterrepo.go | 35 +++- extensions/charts/vsphereoutoftree.go | 178 ++++++++++++++++++ extensions/cloudcredentials/vsphere/create.go | 8 + extensions/clusters/clusters.go | 10 + .../persistentvolumeclaims.go | 26 ++- .../machinepools/vsphere_machine_config.go | 12 +- extensions/provisioning/creates.go | 36 ++++ extensions/provisioning/verify.go | 2 +- extensions/provisioninginput/config.go | 17 +- .../rke1/nodetemplates/vsphere/create.go | 22 ++- .../rke1/nodetemplates/vsphere_config.go | 5 +- 11 files changed, 325 insertions(+), 26 deletions(-) create mode 100644 extensions/charts/vsphereoutoftree.go diff --git a/clients/rancher/catalog/clusterrepo.go b/clients/rancher/catalog/clusterrepo.go index db15fc47..b682d2b6 100644 --- a/clients/rancher/catalog/clusterrepo.go +++ b/clients/rancher/catalog/clusterrepo.go @@ -20,6 +20,7 @@ const ( chartsURL = "v1/catalog.cattle.io.clusterrepos/" link = "link" index = "index" + info = "info" install = "install" RancherChartRepo = "rancher-charts" rancherAppsURL = "v1/catalog.cattle.io.apps/" @@ -27,10 +28,35 @@ const ( uninstall = "uninstall" chartName = "chartName" icon = "icon" + version = "version" + values = "values" ) -// FetchChartIcon - fetches the chart icon from the given repo, chart and version and validates the result -func (c *Client) FetchChartIcon(repo, chart, version string) (int, error) { +// GetChartValues - fetches the chart values from the given repo, chart and chartVersion and validates the result. +func (c *Client) GetChartValues(repoName, chart, chartVersion string) (map[string]interface{}, error) { + result, err := c.RESTClient().Get(). + AbsPath(chartsURL+repoName).Param(link, info).Param(chartName, chart).Param(version, chartVersion). + Do(context.Background()).Raw() + + if err != nil { + return map[string]interface{}{}, err + } + + var mapResponse map[string]interface{} + if err = json.Unmarshal(result, &mapResponse); err != nil { + return map[string]interface{}{}, err + } + + values, ok := mapResponse[values].(map[string]interface{}) + if !ok { + return map[string]interface{}{}, fmt.Errorf("failed to convert values to map[string]interface{}") + } + + return values, nil +} + +// FetchChartIcon - fetches the chart icon from the given repo and chart and validates the result. +func (c *Client) FetchChartIcon(repo, chart string) (int, error) { resp := c.RESTClient().Get(). AbsPath(chartsURL+repo). Param(chartName, chart).Param(link, icon). @@ -38,6 +64,7 @@ func (c *Client) FetchChartIcon(repo, chart, version string) (int, error) { Do(context.Background()) var contentType string + resp.ContentType(&contentType) result, err := resp.Raw() @@ -51,11 +78,13 @@ func (c *Client) FetchChartIcon(repo, chart, version string) (int, error) { if contentType == "image/svg+xml" { var xmlData interface{} + err = xml.Unmarshal(result, &xmlData) if err != nil { // If XML parsing fails, this is not a valid svg return 0, err } + return len(result), nil // Valid SVG } @@ -119,7 +148,7 @@ func (c *Client) GetListChartVersions(chartName, repoName string) ([]string, err versionsList := []string{} for _, entry := range specifiedChartEntries { entryMap := entry.(map[string]interface{}) - versionsList = append(versionsList, entryMap["version"].(string)) + versionsList = append(versionsList, entryMap[version].(string)) } return versionsList, nil diff --git a/extensions/charts/vsphereoutoftree.go b/extensions/charts/vsphereoutoftree.go new file mode 100644 index 00000000..8e230239 --- /dev/null +++ b/extensions/charts/vsphereoutoftree.go @@ -0,0 +1,178 @@ +package charts + +import ( + "github.com/rancher/shepherd/extensions/projects" + "github.com/rancher/shepherd/extensions/rke1/nodetemplates" + "github.com/rancher/shepherd/pkg/api/steve/catalog/types" + + "github.com/rancher/shepherd/clients/rancher" + "github.com/rancher/shepherd/clients/rancher/catalog" + r1vsphere "github.com/rancher/shepherd/extensions/rke1/nodetemplates/vsphere" +) + +const ( + systemProject = "System" + vsphereCPIchartName = "rancher-vsphere-cpi" + vsphereCSIchartName = "rancher-vsphere-csi" + + vcenter = "vCenter" + storageclass = "storageClass" + + datacenters = "datacenters" + host = "host" + password = "password" + username = "username" + port = "port" + clusterid = "clusterId" + datastoreurl = "datastoreURL" +) + +// InstallVsphereOutOfTreeCharts installs the CPI and CSI chart for aws cloud provider in a given cluster. +func InstallVsphereOutOfTreeCharts(client *rancher.Client, vsphereTemplate *nodetemplates.NodeTemplate, repoName, clusterID string) error { + + serverSetting, err := client.Management.Setting.ByID(serverURLSettingID) + if err != nil { + return err + } + + registrySetting, err := client.Management.Setting.ByID(defaultRegistrySettingID) + if err != nil { + return err + } + + project, err := projects.GetProjectByName(client, clusterID, systemProject) + if err != nil { + return err + } + + catalogClient, err := client.GetClusterCatalogClient(clusterID) + if err != nil { + return err + } + + latestCPIVersion, err := catalogClient.GetLatestChartVersion(vsphereCPIchartName, catalog.RancherChartRepo) + if err != nil { + return err + } + + installCPIOptions := &InstallOptions{ + ClusterID: clusterID, + Version: latestCPIVersion, + ProjectID: project.ID, + } + + chartInstallActionPayload := &payloadOpts{ + InstallOptions: *installCPIOptions, + Name: vsphereCPIchartName, + Namespace: kubeSystemNamespace, + Host: serverSetting.Value, + DefaultRegistry: registrySetting.Value, + } + + chartInstallAction, err := vsphereCPIChartInstallAction(catalogClient, + chartInstallActionPayload, vsphereTemplate, installCPIOptions, repoName, kubeSystemNamespace) + if err != nil { + return err + } + + err = catalogClient.InstallChart(chartInstallAction, repoName) + if err != nil { + return err + } + + err = VerifyChartInstall(catalogClient, kubeSystemNamespace, vsphereCPIchartName) + if err != nil { + return err + } + + latestCSIVersion, err := catalogClient.GetLatestChartVersion(vsphereCSIchartName, catalog.RancherChartRepo) + if err != nil { + return err + } + + installCSIOptions := &InstallOptions{ + ClusterID: clusterID, + Version: latestCSIVersion, + ProjectID: project.ID, + } + + chartInstallActionPayload = &payloadOpts{ + InstallOptions: *installCSIOptions, + Name: vsphereCSIchartName, + Namespace: kubeSystemNamespace, + Host: serverSetting.Value, + DefaultRegistry: registrySetting.Value, + } + + chartInstallAction, err = vsphereCSIChartInstallAction(catalogClient, chartInstallActionPayload, + vsphereTemplate, installCSIOptions, repoName, kubeSystemNamespace) + if err != nil { + return err + } + + err = catalogClient.InstallChart(chartInstallAction, repoName) + if err != nil { + return err + } + + return err +} + +// vsphereCPIChartInstallAction is a helper function that returns a chartInstallAction for aws out-of-tree chart. +func vsphereCPIChartInstallAction(client *catalog.Client, chartInstallActionPayload *payloadOpts, vsphereTemplate *nodetemplates.NodeTemplate, installOptions *InstallOptions, repoName, chartNamespace string) (*types.ChartInstallAction, error) { + chartValues, err := client.GetChartValues(repoName, vsphereCPIchartName, installOptions.Version) + if err != nil { + return nil, err + } + + chartValues[vcenter].(map[string]interface{})[datacenters] = vsphereTemplate.VmwareVsphereNodeTemplateConfig.Datacenter + chartValues[vcenter].(map[string]interface{})[host] = vsphereTemplate.VmwareVsphereNodeTemplateConfig.Vcenter + chartValues[vcenter].(map[string]interface{})[password] = r1vsphere.GetVspherePassword() + chartValues[vcenter].(map[string]interface{})[username] = vsphereTemplate.VmwareVsphereNodeTemplateConfig.Username + chartValues[vcenter].(map[string]interface{})[port] = vsphereTemplate.VmwareVsphereNodeTemplateConfig.VcenterPort + + chartInstall := newChartInstall( + chartInstallActionPayload.Name, + chartInstallActionPayload.InstallOptions.Version, + chartInstallActionPayload.InstallOptions.ClusterID, + chartInstallActionPayload.InstallOptions.ClusterName, + chartInstallActionPayload.Host, + repoName, + installOptions.ProjectID, + chartInstallActionPayload.DefaultRegistry, + chartValues) + chartInstalls := []types.ChartInstall{*chartInstall} + + return newChartInstallAction(chartNamespace, chartInstallActionPayload.ProjectID, chartInstalls), nil +} + +// vsphereCSIChartInstallAction is a helper function that returns a chartInstallAction for aws out-of-tree chart. +func vsphereCSIChartInstallAction(client *catalog.Client, chartInstallActionPayload *payloadOpts, vsphereTemplate *nodetemplates.NodeTemplate, installOptions *InstallOptions, repoName, chartNamespace string) (*types.ChartInstallAction, error) { + chartValues, err := client.GetChartValues(repoName, vsphereCSIchartName, installOptions.Version) + if err != nil { + return nil, err + } + + chartValues[vcenter].(map[string]interface{})[datacenters] = vsphereTemplate.VmwareVsphereNodeTemplateConfig.Datacenter + chartValues[vcenter].(map[string]interface{})[host] = vsphereTemplate.VmwareVsphereNodeTemplateConfig.Vcenter + chartValues[vcenter].(map[string]interface{})[password] = r1vsphere.GetVspherePassword() + chartValues[vcenter].(map[string]interface{})[username] = vsphereTemplate.VmwareVsphereNodeTemplateConfig.Username + chartValues[vcenter].(map[string]interface{})[port] = vsphereTemplate.VmwareVsphereNodeTemplateConfig.VcenterPort + chartValues[vcenter].(map[string]interface{})[clusterid] = installOptions.ClusterID + + chartValues[storageclass].(map[string]interface{})[datastoreurl] = r1vsphere.GetVsphereDatastoreUrl() + + chartInstall := newChartInstall( + chartInstallActionPayload.Name, + chartInstallActionPayload.InstallOptions.Version, + chartInstallActionPayload.InstallOptions.ClusterID, + chartInstallActionPayload.InstallOptions.ClusterName, + chartInstallActionPayload.Host, + repoName, + installOptions.ProjectID, + chartInstallActionPayload.DefaultRegistry, + chartValues) + chartInstalls := []types.ChartInstall{*chartInstall} + + return newChartInstallAction(chartNamespace, chartInstallActionPayload.ProjectID, chartInstalls), nil +} diff --git a/extensions/cloudcredentials/vsphere/create.go b/extensions/cloudcredentials/vsphere/create.go index 58ad6f60..f289c3c0 100644 --- a/extensions/cloudcredentials/vsphere/create.go +++ b/extensions/cloudcredentials/vsphere/create.go @@ -27,3 +27,11 @@ func CreateVsphereCloudCredentials(rancherClient *rancher.Client) (*cloudcredent } return resp, nil } + +func GetVspherePassword() string { + var vmwarevsphereCredentialConfig cloudcredentials.VmwarevsphereCredentialConfig + + config.LoadConfig(cloudcredentials.VmwarevsphereCredentialConfigurationFileKey, &vmwarevsphereCredentialConfig) + + return vmwarevsphereCredentialConfig.Password +} diff --git a/extensions/clusters/clusters.go b/extensions/clusters/clusters.go index 860aa175..2ca0db0e 100644 --- a/extensions/clusters/clusters.go +++ b/extensions/clusters/clusters.go @@ -424,6 +424,16 @@ func NewK3SRKE2ClusterConfig(clusterName, namespace string, clustersConfig *Clus machineSelectorConfigs = append(machineSelectorConfigs, awsOutOfTreeSystemConfig()...) } + if clustersConfig.CloudProvider == provisioninginput.VsphereCloudProviderName.String() { + machineSelectorConfigs = append(machineSelectorConfigs, + RKESystemConfigTemplate(map[string]interface{}{ + cloudProviderAnnotationName: provisioninginput.VsphereCloudProviderName.String(), + protectKernelDefaults: false, + }, + nil), + ) + } + rkeSpecCommon := rkev1.RKEClusterSpecCommon{ UpgradeStrategy: upgradeStrategy, ChartValues: chartValuesMap, diff --git a/extensions/kubeapi/volumes/persistentvolumeclaims/persistentvolumeclaims.go b/extensions/kubeapi/volumes/persistentvolumeclaims/persistentvolumeclaims.go index ffd198ea..0b3c3a69 100644 --- a/extensions/kubeapi/volumes/persistentvolumeclaims/persistentvolumeclaims.go +++ b/extensions/kubeapi/volumes/persistentvolumeclaims/persistentvolumeclaims.go @@ -14,24 +14,36 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" ) -// PersistentVolumeClaimGroupVersionResource is the required Group Version Resource for accessing persistent volume claims in a cluster, -// using the dynamic client. +const ( + PersistentVolumeClaimType = "persistentvolumeclaim" + PersistentVolumeBoundStatus = "Bound" + StevePersistentVolumeClaimVolumeName = "volumeName" + + AccessModeReadWriteOnce = "ReadWriteOnce" + AccessModeReadWriteMany = "ReadWriteMany" + AccessModeReadOnlyMany = "ReadOnlyMany" +) + +// PersistentVolumeClaimGroupVersionResource is the required Group Version Resource for accessing persistent +// volume claims in a cluster, using the dynamic client. var PersistentVolumeClaimGroupVersionResource = schema.GroupVersionResource{ Group: "", Version: "v1", Resource: "persistentvolumeclaims", } -// CreatePersistentVolumeClaim is a helper function that uses the dynamic client to create a persistent volume claim on a namespace for a specific cluster. -// If you pass a PersistentVolume then `storageClass` and `storage` would be optional, otherwise `persistentVolume` would be optional and `storage` and` storageClass` -// are needed. +// CreatePersistentVolumeClaim is a helper function that uses the dynamic client to create a persistent +// volume claim on a namespace for a specific cluster. +// If you pass a PersistentVolume then `storageClass` and `storage` would be optional, otherwise `persistentVolume` +// would be optional and `storage` and` storageClass` are needed. // The function registers a delete fuction. func CreatePersistentVolumeClaim(client *rancher.Client, clusterName, persistentVolumeClaimName, description, namespace string, storage int, accessModes []corev1.PersistentVolumeAccessMode, persistentVolume *corev1.PersistentVolume, storageClass *storagev1.StorageClass) (*corev1.PersistentVolumeClaim, error) { var unstructuredVolumeClaim *metav1Unstructured.Unstructured + annotations := map[string]string{ "field.cattle.io/description": description, } - // PersistentVolumeClaim object + persistentVolumeClaim := &corev1.PersistentVolumeClaim{ ObjectMeta: metav1.ObjectMeta{ Name: persistentVolumeClaimName, @@ -80,9 +92,11 @@ func CreatePersistentVolumeClaim(client *rancher.Client, clusterName, persistent } newPersistentVolumeClaim := &corev1.PersistentVolumeClaim{} + err = scheme.Scheme.Convert(unstructuredResp, newPersistentVolumeClaim, unstructuredResp.GroupVersionKind()) if err != nil { return nil, err } + return newPersistentVolumeClaim, nil } diff --git a/extensions/machinepools/vsphere_machine_config.go b/extensions/machinepools/vsphere_machine_config.go index cf7b80fe..273d0c34 100644 --- a/extensions/machinepools/vsphere_machine_config.go +++ b/extensions/machinepools/vsphere_machine_config.go @@ -15,11 +15,12 @@ const ( type VmwarevsphereMachineConfigs struct { VmwarevsphereMachineConfig []VmwarevsphereMachineConfig `json:"vmwarevsphereMachineConfig" yaml:"vmwarevsphereMachineConfig"` - Hostsystem string `json:"hostsystem" yaml:"hostsystem"` - Datacenter string `json:"datacenter" yaml:"datacenter"` - Datastore string `json:"datastore" yaml:"datastore"` - Folder string `json:"folder" yaml:"folder"` - Pool string `json:"pool" yaml:"pool"` + Hostsystem string `json:"hostsystem" yaml:"hostsystem"` + Datacenter string `json:"datacenter" yaml:"datacenter"` + Datastore string `json:"datastore" yaml:"datastore"` + DatastoreUrl string `json:"datastoreUrl" yaml:"datastoreUrl"` + Folder string `json:"folder" yaml:"folder"` + Pool string `json:"pool" yaml:"pool"` } // VsphereMachineConfig is configuration needed to create an rke-machine-config.cattle.io.vmwarevsphereconfig @@ -77,6 +78,7 @@ func NewVSphereMachineConfig(generatedPoolName, namespace string) []unstructured machineConfig.Object["datacenter"] = vmwarevsphereMachineConfigs.Datacenter machineConfig.Object["datastore"] = vmwarevsphereMachineConfigs.Datastore machineConfig.Object["datastoreCluster"] = vsphereMachineConfig.DatastoreCluster + machineConfig.Object["datastoreUrl"] = vmwarevsphereMachineConfigs.DatastoreUrl machineConfig.Object["diskSize"] = vsphereMachineConfig.DiskSize machineConfig.Object["folder"] = vmwarevsphereMachineConfigs.Folder machineConfig.Object["hostsystem"] = vmwarevsphereMachineConfigs.Hostsystem diff --git a/extensions/provisioning/creates.go b/extensions/provisioning/creates.go index f82313c5..d1c737fe 100644 --- a/extensions/provisioning/creates.go +++ b/extensions/provisioning/creates.go @@ -12,10 +12,12 @@ import ( "github.com/sirupsen/logrus" apiv1 "github.com/rancher/rancher/pkg/apis/provisioning.cattle.io/v1" + rkev1 "github.com/rancher/rancher/pkg/apis/rke.cattle.io/v1" v1 "github.com/rancher/shepherd/clients/rancher/v1" "github.com/rancher/shepherd/extensions/cloudcredentials/aws" "github.com/rancher/shepherd/extensions/cloudcredentials/azure" "github.com/rancher/shepherd/extensions/cloudcredentials/google" + "github.com/rancher/shepherd/extensions/cloudcredentials/vsphere" "github.com/rancher/shepherd/extensions/clusters" "github.com/rancher/shepherd/extensions/clusters/aks" "github.com/rancher/shepherd/extensions/clusters/eks" @@ -72,6 +74,7 @@ func CreateProvisioningCluster(client *rancher.Client, provider Provider, cluste clusterName := namegen.AppendRandomString(provider.Name.String()) generatedPoolName := fmt.Sprintf("nc-%s-pool1-", clusterName) machinePoolConfigs := provider.MachinePoolFunc(generatedPoolName, namespace) + var machinePoolResponses []v1.SteveAPIObject for _, machinePoolConfig := range machinePoolConfigs { @@ -91,6 +94,7 @@ func CreateProvisioningCluster(client *rancher.Client, provider Provider, cluste if err != nil { return nil, err } + secretName := fmt.Sprintf("priv-reg-sec-%s", clusterName) secretTemplate := secrets.NewSecretTemplate(secretName, namespace, map[string][]byte{ "password": []byte(clustersConfig.Registries.RKE2Password), @@ -103,6 +107,7 @@ func CreateProvisioningCluster(client *rancher.Client, provider Provider, cluste if err != nil { return nil, err } + for registryName, registry := range clustersConfig.Registries.RKE2Registries.Configs { registry.AuthConfigSecretName = registrySecret.Name clustersConfig.Registries.RKE2Registries.Configs[registryName] = registry @@ -120,6 +125,35 @@ func CreateProvisioningCluster(client *rancher.Client, provider Provider, cluste machinePools := machinepools. CreateAllMachinePools(machineConfigs, pools, machinePoolResponses, provider.Roles, hostnameTruncation) + + if clustersConfig.CloudProvider == provisioninginput.VsphereCloudProviderName.String() { + + vcenterCredentials := map[string]interface{}{ + "datacenters": machinePoolConfigs[0].Object["datacenter"], + "host": cloudCredential.VmwareVsphereConfig.Vcenter, + "password": vsphere.GetVspherePassword(), + "username": cloudCredential.VmwareVsphereConfig.Username, + } + clustersConfig.AddOnConfig = &provisioninginput.AddOnConfig{ + ChartValues: &rkev1.GenericMap{ + Data: map[string]interface{}{ + "rancher-vsphere-cpi": map[string]interface{}{ + "vCenter": vcenterCredentials, + }, + "rancher-vsphere-csi": map[string]interface{}{ + // "csiWindowsSupport": map[string]interface{}{ + // "enabled": "false", + // }, + "storageClass": map[string]interface{}{ + "datastoreURL": machinePoolConfigs[0].Object["datastoreUrl"], + }, + "vCenter": vcenterCredentials, + }, + }, + }, + } + } + cluster := clusters.NewK3SRKE2ClusterConfig(clusterName, namespace, clustersConfig, machinePools, cloudCredential.ID) for _, truncatedPool := range hostnameTruncation { @@ -128,6 +162,7 @@ func CreateProvisioningCluster(client *rancher.Client, provider Provider, cluste if truncatedPool.ClusterNameLengthLimit > 0 { cluster.Spec.RKEConfig.MachinePoolDefaults.HostnameLengthLimit = truncatedPool.ClusterNameLengthLimit } + break } } @@ -149,6 +184,7 @@ func CreateProvisioningCluster(client *rancher.Client, provider Provider, cluste createdCluster, err := adminClient.Steve. SteveType(clusters.ProvisioningSteveResourceType). ByID(namespace + "/" + clusterName) + return createdCluster, err } diff --git a/extensions/provisioning/verify.go b/extensions/provisioning/verify.go index 30d24957..60f7d062 100644 --- a/extensions/provisioning/verify.go +++ b/extensions/provisioning/verify.go @@ -93,7 +93,7 @@ func VerifyRKE1Cluster(t *testing.T, client *rancher.Client, clustersConfig *clu } } - if !strings.Contains(clustersConfig.CloudProvider, "external") { + if clustersConfig.CloudProvider == "" { podErrors := pods.StatusPods(client, cluster.ID) assert.Empty(t, podErrors) } diff --git a/extensions/provisioninginput/config.go b/extensions/provisioninginput/config.go index f97e3818..83db33d0 100644 --- a/extensions/provisioninginput/config.go +++ b/extensions/provisioninginput/config.go @@ -25,14 +25,15 @@ const ( type ProviderName string const ( - AWSProviderName ProviderName = "aws" - AzureProviderName ProviderName = "azure" - DOProviderName ProviderName = "do" - HarvesterProviderName ProviderName = "harvester" - LinodeProviderName ProviderName = "linode" - GoogleProviderName ProviderName = "google" - VsphereProviderName ProviderName = "vsphere" - ExternalProviderName ProviderName = "external" + AWSProviderName ProviderName = "aws" + AzureProviderName ProviderName = "azure" + DOProviderName ProviderName = "do" + HarvesterProviderName ProviderName = "harvester" + LinodeProviderName ProviderName = "linode" + GoogleProviderName ProviderName = "google" + VsphereProviderName ProviderName = "vsphere" + VsphereCloudProviderName ProviderName = "rancher-vsphere" + ExternalProviderName ProviderName = "external" ) var AllRolesMachinePool = MachinePools{ diff --git a/extensions/rke1/nodetemplates/vsphere/create.go b/extensions/rke1/nodetemplates/vsphere/create.go index ae51ea74..ca302435 100644 --- a/extensions/rke1/nodetemplates/vsphere/create.go +++ b/extensions/rke1/nodetemplates/vsphere/create.go @@ -13,6 +13,7 @@ const vmwarevsphereNodeTemplateNameBase = "vmwarevsphereNodeConfig" // an VSphere node template and returns the NodeTemplate response func CreateVSphereNodeTemplate(rancherClient *rancher.Client) (*nodetemplates.NodeTemplate, error) { var vmwarevsphereNodeTemplateConfig nodetemplates.VmwareVsphereNodeTemplateConfig + config.LoadConfig(nodetemplates.VmwareVsphereNodeTemplateConfigurationFileKey, &vmwarevsphereNodeTemplateConfig) nodeTemplate := nodetemplates.NodeTemplate{ @@ -24,15 +25,34 @@ func CreateVSphereNodeTemplate(rancherClient *rancher.Client) (*nodetemplates.No nodeTemplateConfig := &nodetemplates.NodeTemplate{} config.LoadConfig(nodetemplates.NodeTemplateConfigurationFileKey, nodeTemplateConfig) - nodeTemplateFinal, err := nodeTemplate.MergeOverride(nodeTemplateConfig, nodetemplates.VmwareVsphereNodeTemplateConfigurationFileKey) + nodeTemplateFinal, err := nodeTemplate. + MergeOverride(nodeTemplateConfig, nodetemplates.VmwareVsphereNodeTemplateConfigurationFileKey) if err != nil { return nil, err } resp := &nodetemplates.NodeTemplate{} err = rancherClient.Management.APIBaseClient.Ops.DoCreate(management.NodeTemplateType, *nodeTemplateFinal, resp) + if err != nil { return nil, err } + return resp, nil } + +func GetVsphereDatastoreUrl() string { + var vmwarevsphereNodeTemplateConfig nodetemplates.VmwareVsphereNodeTemplateConfig + + config.LoadConfig(nodetemplates.VmwareVsphereNodeTemplateConfigurationFileKey, &vmwarevsphereNodeTemplateConfig) + + return vmwarevsphereNodeTemplateConfig.DatastoreUrl +} + +func GetVspherePassword() string { + var vmwarevsphereNodeTemplateConfig nodetemplates.VmwareVsphereNodeTemplateConfig + + config.LoadConfig(nodetemplates.VmwareVsphereNodeTemplateConfigurationFileKey, &vmwarevsphereNodeTemplateConfig) + + return vmwarevsphereNodeTemplateConfig.Password +} diff --git a/extensions/rke1/nodetemplates/vsphere_config.go b/extensions/rke1/nodetemplates/vsphere_config.go index fdf1ae17..c4e2e657 100644 --- a/extensions/rke1/nodetemplates/vsphere_config.go +++ b/extensions/rke1/nodetemplates/vsphere_config.go @@ -13,8 +13,9 @@ type VmwareVsphereNodeTemplateConfig struct { CPUCount string `json:"cpuCount" yaml:"cpuCount"` CreationType string `json:"creationType" yaml:"creationType"` CustomAttribute []string `json:"customAttribute" yaml:"customAttribute"` - DataCenter string `json:"dataCenter" yaml:"dataCenter"` - DataStore string `json:"dataStore" yaml:"dataStore"` + Datacenter string `json:"datacenter" yaml:"datacenter"` + Datastore string `json:"datastore" yaml:"datastore"` + DatastoreUrl string `json:"datatoreUrl" yaml:"datastoreUrl"` DatastoreCluster string `json:"datastoreCluster" yaml:"datastoreCluster"` DiskSize string `json:"diskSize" yaml:"diskSize"` Folder string `json:"folder" yaml:"folder"`