diff --git a/pkg/api/azenvtypes.go b/pkg/api/azenvtypes.go index f8db06a20f5..537eb82e46d 100644 --- a/pkg/api/azenvtypes.go +++ b/pkg/api/azenvtypes.go @@ -7,18 +7,18 @@ import "fmt" //AzureEnvironmentSpecConfig is the overall configuration differences in different cloud environments. type AzureEnvironmentSpecConfig struct { - CloudName string - DockerSpecConfig DockerSpecConfig - KubernetesSpecConfig KubernetesSpecConfig - DCOSSpecConfig DCOSSpecConfig - EndpointConfig AzureEndpointConfig - OSImageConfig map[Distro]AzureOSImageConfig + CloudName string `json:"cloudName,omitempty"` + DockerSpecConfig DockerSpecConfig `json:"dockerSpecConfig,omitempty"` + KubernetesSpecConfig KubernetesSpecConfig `json:"kubernetesSpecConfig,omitempty"` + DCOSSpecConfig DCOSSpecConfig `json:"-"` + EndpointConfig AzureEndpointConfig `json:"endpointConfig,omitempty"` + OSImageConfig map[Distro]AzureOSImageConfig `json:"osImageConfig,omitempty"` } //DockerSpecConfig is the configurations of docker type DockerSpecConfig struct { - DockerEngineRepo string - DockerComposeDownloadURL string + DockerEngineRepo string `json:"dockerEngineRepo,omitempty"` + DockerComposeDownloadURL string `json:"dockerComposeDownloadURL,omitempty"` } //DCOSSpecConfig is the configurations of DCOS @@ -36,31 +36,31 @@ type DCOSSpecConfig struct { //KubernetesSpecConfig is the kubernetes container images used. type KubernetesSpecConfig struct { - KubernetesImageBase string - TillerImageBase string - ACIConnectorImageBase string - NVIDIAImageBase string - AzureCNIImageBase string - EtcdDownloadURLBase string - KubeBinariesSASURLBase string - WindowsTelemetryGUID string - CNIPluginsDownloadURL string - VnetCNILinuxPluginsDownloadURL string - VnetCNIWindowsPluginsDownloadURL string - ContainerdDownloadURLBase string + KubernetesImageBase string `json:"kubernetesImageBase,omitempty"` + TillerImageBase string `json:"tillerImageBase,omitempty"` + ACIConnectorImageBase string `json:"aciConnectorImageBase,omitempty"` + NVIDIAImageBase string `json:"nvidiaImageBase,omitempty"` + AzureCNIImageBase string `json:"azureCNIImageBase,omitempty"` + EtcdDownloadURLBase string `json:"etcdDownloadURLBase,omitempty"` + KubeBinariesSASURLBase string `json:"kubeBinariesSASURLBase,omitempty"` + WindowsTelemetryGUID string `json:"windowsTelemetryGUID,omitempty"` + CNIPluginsDownloadURL string `json:"cniPluginsDownloadURL,omitempty"` + VnetCNILinuxPluginsDownloadURL string `json:"vnetCNILinuxPluginsDownloadURL,omitempty"` + VnetCNIWindowsPluginsDownloadURL string `json:"vnetCNIWindowsPluginsDownloadURL,omitempty"` + ContainerdDownloadURLBase string `json:"containerdDownloadURLBase,omitempty"` } //AzureEndpointConfig describes an Azure endpoint type AzureEndpointConfig struct { - ResourceManagerVMDNSSuffix string + ResourceManagerVMDNSSuffix string `json:"resourceManagerVMDNSSuffix,omitempty"` } //AzureOSImageConfig describes an Azure OS image type AzureOSImageConfig struct { - ImageOffer string - ImageSku string - ImagePublisher string - ImageVersion string + ImageOffer string `json:"imageOffer,omitempty"` + ImageSku string `json:"imageSku,omitempty"` + ImagePublisher string `json:"imagePublisher,omitempty"` + ImageVersion string `json:"imageVersion,omitempty"` } var ( diff --git a/pkg/api/converterfromapi.go b/pkg/api/converterfromapi.go index 0bd35a7e183..254894fce54 100644 --- a/pkg/api/converterfromapi.go +++ b/pkg/api/converterfromapi.go @@ -1172,28 +1172,80 @@ func convertFeatureFlagsToVLabs(api *FeatureFlags, vlabs *vlabs.FeatureFlags) { vlabs.BlockOutboundInternet = api.BlockOutboundInternet } -func convertCloudProfileToVLabs(api *CustomCloudProfile, vlabs *vlabs.CustomCloudProfile) { +func convertCloudProfileToVLabs(api *CustomCloudProfile, vlabsccp *vlabs.CustomCloudProfile) { if api.Environment != nil { - vlabs.Environment = &azure.Environment{} - vlabs.Environment.Name = api.Environment.Name - vlabs.Environment.ManagementPortalURL = api.Environment.ManagementPortalURL - vlabs.Environment.PublishSettingsURL = api.Environment.PublishSettingsURL - vlabs.Environment.ServiceManagementEndpoint = api.Environment.ServiceManagementEndpoint - vlabs.Environment.ResourceManagerEndpoint = api.Environment.ResourceManagerEndpoint - vlabs.Environment.ActiveDirectoryEndpoint = api.Environment.ActiveDirectoryEndpoint - vlabs.Environment.GalleryEndpoint = api.Environment.GalleryEndpoint - vlabs.Environment.KeyVaultEndpoint = api.Environment.KeyVaultEndpoint - vlabs.Environment.GraphEndpoint = api.Environment.GraphEndpoint - vlabs.Environment.ServiceBusEndpoint = api.Environment.ServiceBusEndpoint - vlabs.Environment.BatchManagementEndpoint = api.Environment.BatchManagementEndpoint - vlabs.Environment.StorageEndpointSuffix = api.Environment.StorageEndpointSuffix - vlabs.Environment.SQLDatabaseDNSSuffix = api.Environment.SQLDatabaseDNSSuffix - vlabs.Environment.TrafficManagerDNSSuffix = api.Environment.TrafficManagerDNSSuffix - vlabs.Environment.KeyVaultDNSSuffix = api.Environment.KeyVaultDNSSuffix - vlabs.Environment.ServiceBusEndpointSuffix = api.Environment.ServiceBusEndpointSuffix - vlabs.Environment.ServiceManagementVMDNSSuffix = api.Environment.ServiceManagementVMDNSSuffix - vlabs.Environment.ResourceManagerVMDNSSuffix = api.Environment.ResourceManagerVMDNSSuffix - vlabs.Environment.ContainerRegistryDNSSuffix = api.Environment.ContainerRegistryDNSSuffix - vlabs.Environment.TokenAudience = api.Environment.TokenAudience + vlabsccp.Environment = &azure.Environment{} + vlabsccp.Environment.Name = api.Environment.Name + vlabsccp.Environment.ManagementPortalURL = api.Environment.ManagementPortalURL + vlabsccp.Environment.PublishSettingsURL = api.Environment.PublishSettingsURL + vlabsccp.Environment.ServiceManagementEndpoint = api.Environment.ServiceManagementEndpoint + vlabsccp.Environment.ResourceManagerEndpoint = api.Environment.ResourceManagerEndpoint + vlabsccp.Environment.ActiveDirectoryEndpoint = api.Environment.ActiveDirectoryEndpoint + vlabsccp.Environment.GalleryEndpoint = api.Environment.GalleryEndpoint + vlabsccp.Environment.KeyVaultEndpoint = api.Environment.KeyVaultEndpoint + vlabsccp.Environment.GraphEndpoint = api.Environment.GraphEndpoint + vlabsccp.Environment.ServiceBusEndpoint = api.Environment.ServiceBusEndpoint + vlabsccp.Environment.BatchManagementEndpoint = api.Environment.BatchManagementEndpoint + vlabsccp.Environment.StorageEndpointSuffix = api.Environment.StorageEndpointSuffix + vlabsccp.Environment.SQLDatabaseDNSSuffix = api.Environment.SQLDatabaseDNSSuffix + vlabsccp.Environment.TrafficManagerDNSSuffix = api.Environment.TrafficManagerDNSSuffix + vlabsccp.Environment.KeyVaultDNSSuffix = api.Environment.KeyVaultDNSSuffix + vlabsccp.Environment.ServiceBusEndpointSuffix = api.Environment.ServiceBusEndpointSuffix + vlabsccp.Environment.ServiceManagementVMDNSSuffix = api.Environment.ServiceManagementVMDNSSuffix + vlabsccp.Environment.ResourceManagerVMDNSSuffix = api.Environment.ResourceManagerVMDNSSuffix + vlabsccp.Environment.ContainerRegistryDNSSuffix = api.Environment.ContainerRegistryDNSSuffix + vlabsccp.Environment.TokenAudience = api.Environment.TokenAudience + } + + if api.AzureEnvironmentSpecConfig != nil { + vlabsccp.AzureEnvironmentSpecConfig = &vlabs.AzureEnvironmentSpecConfig{} + convertAzureEnvironmentSpecConfigToVLabs(api.AzureEnvironmentSpecConfig, vlabsccp.AzureEnvironmentSpecConfig) + } + +} + +func convertAzureEnvironmentSpecConfigToVLabs(api *AzureEnvironmentSpecConfig, vlabses *vlabs.AzureEnvironmentSpecConfig) { + vlabses.CloudName = api.CloudName + vlabses.DCOSSpecConfig = vlabs.DCOSSpecConfig{ + DCOS188BootstrapDownloadURL: api.DCOSSpecConfig.DCOS188BootstrapDownloadURL, + DCOS190BootstrapDownloadURL: api.DCOSSpecConfig.DCOS190BootstrapDownloadURL, + DCOS198BootstrapDownloadURL: api.DCOSSpecConfig.DCOS198BootstrapDownloadURL, + DCOS110BootstrapDownloadURL: api.DCOSSpecConfig.DCOS110BootstrapDownloadURL, + DCOS111BootstrapDownloadURL: api.DCOSSpecConfig.DCOS111BootstrapDownloadURL, + DCOSWindowsBootstrapDownloadURL: api.DCOSSpecConfig.DCOSWindowsBootstrapDownloadURL, + DcosRepositoryURL: api.DCOSSpecConfig.DcosRepositoryURL, + DcosClusterPackageListID: api.DCOSSpecConfig.DcosClusterPackageListID, + DcosProviderPackageID: api.DCOSSpecConfig.DcosProviderPackageID, + } + + vlabses.DockerSpecConfig = vlabs.DockerSpecConfig{ + DockerEngineRepo: api.DockerSpecConfig.DockerEngineRepo, + DockerComposeDownloadURL: api.DockerSpecConfig.DockerComposeDownloadURL, + } + vlabses.EndpointConfig = vlabs.AzureEndpointConfig{ + ResourceManagerVMDNSSuffix: api.EndpointConfig.ResourceManagerVMDNSSuffix, + } + vlabses.KubernetesSpecConfig = vlabs.KubernetesSpecConfig{ + KubernetesImageBase: api.KubernetesSpecConfig.KubernetesImageBase, + TillerImageBase: api.KubernetesSpecConfig.TillerImageBase, + ACIConnectorImageBase: api.KubernetesSpecConfig.ACIConnectorImageBase, + NVIDIAImageBase: api.KubernetesSpecConfig.NVIDIAImageBase, + AzureCNIImageBase: api.KubernetesSpecConfig.AzureCNIImageBase, + EtcdDownloadURLBase: api.KubernetesSpecConfig.EtcdDownloadURLBase, + KubeBinariesSASURLBase: api.KubernetesSpecConfig.KubeBinariesSASURLBase, + WindowsTelemetryGUID: api.KubernetesSpecConfig.WindowsTelemetryGUID, + CNIPluginsDownloadURL: api.KubernetesSpecConfig.CNIPluginsDownloadURL, + VnetCNILinuxPluginsDownloadURL: api.KubernetesSpecConfig.VnetCNILinuxPluginsDownloadURL, + VnetCNIWindowsPluginsDownloadURL: api.KubernetesSpecConfig.VnetCNIWindowsPluginsDownloadURL, + ContainerdDownloadURLBase: api.KubernetesSpecConfig.ContainerdDownloadURLBase, + } + vlabses.OSImageConfig = map[vlabs.Distro]vlabs.AzureOSImageConfig{} + for k, v := range api.OSImageConfig { + vlabses.OSImageConfig[vlabs.Distro(string(k))] = vlabs.AzureOSImageConfig{ + ImageOffer: v.ImageOffer, + ImageSku: v.ImageSku, + ImagePublisher: v.ImagePublisher, + ImageVersion: v.ImageVersion, + } } } diff --git a/pkg/api/converterfromapi_test.go b/pkg/api/converterfromapi_test.go new file mode 100644 index 00000000000..27624f8cdc9 --- /dev/null +++ b/pkg/api/converterfromapi_test.go @@ -0,0 +1,292 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +package api + +import ( + "testing" + + "github.com/Azure/aks-engine/pkg/api/vlabs" + "github.com/Azure/go-autorest/autorest/azure" +) + +func TestConvertCloudProfileToVLabs(t *testing.T) { + const ( + name = "AzureStackCloud" + managementPortalURL = "https=//management.local.azurestack.external/" + publishSettingsURL = "https=//management.local.azurestack.external/publishsettings/index" + serviceManagementEndpoint = "https=//management.azurestackci15.onmicrosoft.com/36f71706-54df-4305-9847-5b038a4cf189" + resourceManagerEndpoint = "https=//management.local.azurestack.external/" + activeDirectoryEndpoint = "https=//login.windows.net/" + galleryEndpoint = "https=//portal.local.azurestack.external=30015/" + keyVaultEndpoint = "https=//vault.azurestack.external/" + graphEndpoint = "https=//graph.windows.net/" + serviceBusEndpoint = "https=//servicebus.azurestack.external/" + batchManagementEndpoint = "https=//batch.azurestack.external/" + storageEndpointSuffix = "core.azurestack.external" + sqlDatabaseDNSSuffix = "database.azurestack.external" + trafficManagerDNSSuffix = "trafficmanager.cn" + keyVaultDNSSuffix = "vault.azurestack.external" + serviceBusEndpointSuffix = "servicebus.azurestack.external" + serviceManagementVMDNSSuffix = "chinacloudapp.cn" + resourceManagerVMDNSSuffix = "cloudapp.azurestack.external" + containerRegistryDNSSuffix = "azurecr.io" + tokenAudience = "https=//management.azurestack.external/" + ) + + cs := &ContainerService{ + Properties: &Properties{ + CustomCloudProfile: &CustomCloudProfile{ + Environment: &azure.Environment{ + Name: name, + ManagementPortalURL: managementPortalURL, + PublishSettingsURL: publishSettingsURL, + ServiceManagementEndpoint: serviceManagementEndpoint, + ResourceManagerEndpoint: resourceManagerEndpoint, + ActiveDirectoryEndpoint: activeDirectoryEndpoint, + GalleryEndpoint: galleryEndpoint, + KeyVaultEndpoint: keyVaultEndpoint, + GraphEndpoint: graphEndpoint, + ServiceBusEndpoint: serviceBusEndpoint, + BatchManagementEndpoint: batchManagementEndpoint, + StorageEndpointSuffix: storageEndpointSuffix, + SQLDatabaseDNSSuffix: sqlDatabaseDNSSuffix, + TrafficManagerDNSSuffix: trafficManagerDNSSuffix, + KeyVaultDNSSuffix: keyVaultDNSSuffix, + ServiceBusEndpointSuffix: serviceBusEndpointSuffix, + ServiceManagementVMDNSSuffix: serviceManagementVMDNSSuffix, + ResourceManagerVMDNSSuffix: resourceManagerVMDNSSuffix, + ContainerRegistryDNSSuffix: containerRegistryDNSSuffix, + TokenAudience: tokenAudience, + }, + }, + }, + } + + vlabscs := ConvertContainerServiceToVLabs(cs) + if vlabscs.Properties.CustomCloudProfile.Environment.Name != name { + t.Errorf("incorrect Name, expect: '%s', actual: '%s'", name, vlabscs.Properties.CustomCloudProfile.Environment.Name) + } + if vlabscs.Properties.CustomCloudProfile.Environment.ManagementPortalURL != managementPortalURL { + t.Errorf("incorrect ManagementPortalURL, expect: '%s', actual: '%s'", managementPortalURL, vlabscs.Properties.CustomCloudProfile.Environment.ManagementPortalURL) + } + if vlabscs.Properties.CustomCloudProfile.Environment.PublishSettingsURL != publishSettingsURL { + t.Errorf("incorrect PublishSettingsURL, expect: '%s', actual: '%s'", publishSettingsURL, vlabscs.Properties.CustomCloudProfile.Environment.PublishSettingsURL) + } + if vlabscs.Properties.CustomCloudProfile.Environment.ServiceManagementEndpoint != serviceManagementEndpoint { + t.Errorf("incorrect ServiceManagementEndpoint, expect: '%s', actual: '%s'", serviceManagementEndpoint, vlabscs.Properties.CustomCloudProfile.Environment.ServiceManagementEndpoint) + } + if vlabscs.Properties.CustomCloudProfile.Environment.ResourceManagerEndpoint != resourceManagerEndpoint { + t.Errorf("incorrect ResourceManagerEndpoint, expect: '%s', actual: '%s'", resourceManagerEndpoint, vlabscs.Properties.CustomCloudProfile.Environment.ResourceManagerEndpoint) + } + if vlabscs.Properties.CustomCloudProfile.Environment.ActiveDirectoryEndpoint != activeDirectoryEndpoint { + t.Errorf("incorrect ActiveDirectoryEndpoint, expect: '%s', actual: '%s'", activeDirectoryEndpoint, vlabscs.Properties.CustomCloudProfile.Environment.ActiveDirectoryEndpoint) + } + if vlabscs.Properties.CustomCloudProfile.Environment.GalleryEndpoint != galleryEndpoint { + t.Errorf("incorrect GalleryEndpoint, expect: '%s', actual: '%s'", galleryEndpoint, vlabscs.Properties.CustomCloudProfile.Environment.GalleryEndpoint) + } + if vlabscs.Properties.CustomCloudProfile.Environment.KeyVaultEndpoint != keyVaultEndpoint { + t.Errorf("incorrect KeyVaultEndpoint, expect: '%s', actual: '%s'", keyVaultEndpoint, vlabscs.Properties.CustomCloudProfile.Environment.KeyVaultEndpoint) + } + if vlabscs.Properties.CustomCloudProfile.Environment.GraphEndpoint != graphEndpoint { + t.Errorf("incorrect GraphEndpoint, expect: '%s', actual: '%s'", graphEndpoint, vlabscs.Properties.CustomCloudProfile.Environment.GraphEndpoint) + } + if vlabscs.Properties.CustomCloudProfile.Environment.ServiceBusEndpoint != serviceBusEndpoint { + t.Errorf("incorrect ServiceBusEndpoint, expect: '%s', actual: '%s'", serviceBusEndpoint, vlabscs.Properties.CustomCloudProfile.Environment.ServiceBusEndpoint) + } + if vlabscs.Properties.CustomCloudProfile.Environment.BatchManagementEndpoint != batchManagementEndpoint { + t.Errorf("incorrect BatchManagementEndpoint, expect: '%s', actual: '%s'", batchManagementEndpoint, vlabscs.Properties.CustomCloudProfile.Environment.BatchManagementEndpoint) + } + if vlabscs.Properties.CustomCloudProfile.Environment.StorageEndpointSuffix != storageEndpointSuffix { + t.Errorf("incorrect StorageEndpointSuffix, expect: '%s', actual: '%s'", storageEndpointSuffix, vlabscs.Properties.CustomCloudProfile.Environment.StorageEndpointSuffix) + } + if vlabscs.Properties.CustomCloudProfile.Environment.SQLDatabaseDNSSuffix != sqlDatabaseDNSSuffix { + t.Errorf("incorrect SQLDatabaseDNSSuffix, expect: '%s', actual: '%s'", sqlDatabaseDNSSuffix, vlabscs.Properties.CustomCloudProfile.Environment.SQLDatabaseDNSSuffix) + } + if vlabscs.Properties.CustomCloudProfile.Environment.TrafficManagerDNSSuffix != trafficManagerDNSSuffix { + t.Errorf("incorrect TrafficManagerDNSSuffix, expect: '%s', actual: '%s'", trafficManagerDNSSuffix, vlabscs.Properties.CustomCloudProfile.Environment.TrafficManagerDNSSuffix) + } + if vlabscs.Properties.CustomCloudProfile.Environment.KeyVaultDNSSuffix != keyVaultDNSSuffix { + t.Errorf("incorrect KeyVaultDNSSuffix, expect: '%s', actual: '%s'", keyVaultDNSSuffix, vlabscs.Properties.CustomCloudProfile.Environment.KeyVaultDNSSuffix) + } + if vlabscs.Properties.CustomCloudProfile.Environment.ServiceBusEndpointSuffix != serviceBusEndpointSuffix { + t.Errorf("incorrect ServiceBusEndpointSuffix, expect: '%s', actual: '%s'", serviceBusEndpointSuffix, vlabscs.Properties.CustomCloudProfile.Environment.ServiceBusEndpointSuffix) + } + if vlabscs.Properties.CustomCloudProfile.Environment.ServiceManagementVMDNSSuffix != serviceManagementVMDNSSuffix { + t.Errorf("incorrect ServiceManagementVMDNSSuffix, expect: '%s', actual: '%s'", serviceManagementVMDNSSuffix, vlabscs.Properties.CustomCloudProfile.Environment.ServiceManagementVMDNSSuffix) + } + if vlabscs.Properties.CustomCloudProfile.Environment.ResourceManagerVMDNSSuffix != resourceManagerVMDNSSuffix { + t.Errorf("incorrect ResourceManagerVMDNSSuffix, expect: '%s', actual: '%s'", resourceManagerVMDNSSuffix, vlabscs.Properties.CustomCloudProfile.Environment.ResourceManagerVMDNSSuffix) + } + if vlabscs.Properties.CustomCloudProfile.Environment.ContainerRegistryDNSSuffix != containerRegistryDNSSuffix { + t.Errorf("incorrect ContainerRegistryDNSSuffix, expect: '%s', actual: '%s'", containerRegistryDNSSuffix, vlabscs.Properties.CustomCloudProfile.Environment.ContainerRegistryDNSSuffix) + } + if vlabscs.Properties.CustomCloudProfile.Environment.TokenAudience != tokenAudience { + t.Errorf("incorrect TokenAudience, expect: '%s', actual: '%s'", tokenAudience, vlabscs.Properties.CustomCloudProfile.Environment.TokenAudience) + } +} + +func TestConvertAzureEnvironmentSpecConfigToVLabs(t *testing.T) { + //Mock AzureEnvironmentSpecConfig + cs := &ContainerService{ + Properties: &Properties{ + CustomCloudProfile: &CustomCloudProfile{ + AzureEnvironmentSpecConfig: &AzureEnvironmentSpecConfig{ + CloudName: "AzureStackCloud", + //DockerSpecConfig specify the docker engine download repo + DockerSpecConfig: DockerSpecConfig{ + DockerEngineRepo: "DockerEngineRepo", + DockerComposeDownloadURL: "DockerComposeDownloadURL", + }, + //KubernetesSpecConfig - Due to Chinese firewall issue, the default containers from google is blocked, use the Chinese local mirror instead + KubernetesSpecConfig: KubernetesSpecConfig{ + KubernetesImageBase: "KubernetesImageBase", + TillerImageBase: "TillerImageBase", + ACIConnectorImageBase: "ACIConnectorImageBase", + NVIDIAImageBase: "NVIDIAImageBase", + AzureCNIImageBase: "AzureCNIImageBase", + EtcdDownloadURLBase: "EtcdDownloadURLBase", + KubeBinariesSASURLBase: "KubeBinariesSASURLBase", + WindowsTelemetryGUID: "WindowsTelemetryGUID", + CNIPluginsDownloadURL: "CNIPluginsDownloadURL", + VnetCNILinuxPluginsDownloadURL: "VnetCNILinuxPluginsDownloadURL", + VnetCNIWindowsPluginsDownloadURL: "VnetCNIWindowsPluginsDownloadURL", + ContainerdDownloadURLBase: "ContainerdDownloadURLBase", + }, + DCOSSpecConfig: DCOSSpecConfig{ + DCOS188BootstrapDownloadURL: "DCOS188BootstrapDownloadURL", + DCOS190BootstrapDownloadURL: "DCOS190BootstrapDownloadURL", + DCOS198BootstrapDownloadURL: "DCOS198BootstrapDownloadURL", + DCOS110BootstrapDownloadURL: "DCOS110BootstrapDownloadURL", + DCOS111BootstrapDownloadURL: "DCOS111BootstrapDownloadURL", + DCOSWindowsBootstrapDownloadURL: "DCOSWindowsBootstrapDownloadURL", + DcosRepositoryURL: "DcosRepositoryURL", + DcosClusterPackageListID: "DcosClusterPackageListID", + DcosProviderPackageID: "DcosProviderPackageID", + }, + EndpointConfig: AzureEndpointConfig{ + ResourceManagerVMDNSSuffix: "ResourceManagerVMDNSSuffix", + }, + OSImageConfig: map[Distro]AzureOSImageConfig{ + Distro("Test"): { + ImageOffer: "ImageOffer", + ImageSku: "ImageSku", + ImagePublisher: "ImagePublisher", + ImageVersion: "ImageVersion", + }, + AKS: DefaultAKSOSImageConfig, + AKSDockerEngine: DefaultAKSDockerEngineOSImageConfig, + }, + }, + }, + }, + } + vlabscs := ConvertContainerServiceToVLabs(cs) + + csSpec := cs.Properties.CustomCloudProfile.AzureEnvironmentSpecConfig + vlabscsSpec := vlabscs.Properties.CustomCloudProfile.AzureEnvironmentSpecConfig + + if vlabscsSpec.CloudName != csSpec.CloudName { + t.Errorf("incorrect CloudName, expect: '%s', actual: '%s'", csSpec.CloudName, vlabscsSpec.CloudName) + } + + //KubernetesSpecConfig + if vlabscsSpec.KubernetesSpecConfig.KubernetesImageBase != csSpec.KubernetesSpecConfig.KubernetesImageBase { + t.Errorf("incorrect KubernetesImageBase, expect: '%s', actual: '%s'", csSpec.KubernetesSpecConfig.KubernetesImageBase, vlabscsSpec.KubernetesSpecConfig.KubernetesImageBase) + } + if vlabscsSpec.KubernetesSpecConfig.TillerImageBase != csSpec.KubernetesSpecConfig.TillerImageBase { + t.Errorf("incorrect TillerImageBase, expect: '%s', actual: '%s'", csSpec.KubernetesSpecConfig.TillerImageBase, vlabscsSpec.KubernetesSpecConfig.TillerImageBase) + } + if vlabscsSpec.KubernetesSpecConfig.ACIConnectorImageBase != csSpec.KubernetesSpecConfig.ACIConnectorImageBase { + t.Errorf("incorrect ACIConnectorImageBase, expect: '%s', actual: '%s'", csSpec.KubernetesSpecConfig.ACIConnectorImageBase, vlabscsSpec.KubernetesSpecConfig.ACIConnectorImageBase) + } + if vlabscsSpec.KubernetesSpecConfig.NVIDIAImageBase != csSpec.KubernetesSpecConfig.NVIDIAImageBase { + t.Errorf("incorrect NVIDIAImageBase, expect: '%s', actual: '%s'", csSpec.KubernetesSpecConfig.NVIDIAImageBase, vlabscsSpec.KubernetesSpecConfig.NVIDIAImageBase) + } + if vlabscsSpec.KubernetesSpecConfig.AzureCNIImageBase != csSpec.KubernetesSpecConfig.AzureCNIImageBase { + t.Errorf("incorrect AzureCNIImageBase, expect: '%s', actual: '%s'", csSpec.KubernetesSpecConfig.AzureCNIImageBase, vlabscsSpec.KubernetesSpecConfig.AzureCNIImageBase) + } + if vlabscsSpec.KubernetesSpecConfig.EtcdDownloadURLBase != csSpec.KubernetesSpecConfig.EtcdDownloadURLBase { + t.Errorf("incorrect EtcdDownloadURLBase, expect: '%s', actual: '%s'", csSpec.KubernetesSpecConfig.EtcdDownloadURLBase, vlabscsSpec.KubernetesSpecConfig.EtcdDownloadURLBase) + } + if vlabscsSpec.KubernetesSpecConfig.KubeBinariesSASURLBase != csSpec.KubernetesSpecConfig.KubeBinariesSASURLBase { + t.Errorf("incorrect KubeBinariesSASURLBase, expect: '%s', actual: '%s'", csSpec.KubernetesSpecConfig.KubeBinariesSASURLBase, vlabscsSpec.KubernetesSpecConfig.KubeBinariesSASURLBase) + } + if vlabscsSpec.KubernetesSpecConfig.WindowsTelemetryGUID != csSpec.KubernetesSpecConfig.WindowsTelemetryGUID { + t.Errorf("incorrect WindowsTelemetryGUID, expect: '%s', actual: '%s'", csSpec.KubernetesSpecConfig.WindowsTelemetryGUID, vlabscsSpec.KubernetesSpecConfig.WindowsTelemetryGUID) + } + if vlabscsSpec.KubernetesSpecConfig.CNIPluginsDownloadURL != csSpec.KubernetesSpecConfig.CNIPluginsDownloadURL { + t.Errorf("incorrect CNIPluginsDownloadURL, expect: '%s', actual: '%s'", csSpec.KubernetesSpecConfig.CNIPluginsDownloadURL, vlabscsSpec.KubernetesSpecConfig.CNIPluginsDownloadURL) + } + if vlabscsSpec.KubernetesSpecConfig.VnetCNILinuxPluginsDownloadURL != csSpec.KubernetesSpecConfig.VnetCNILinuxPluginsDownloadURL { + t.Errorf("incorrect VnetCNILinuxPluginsDownloadURL, expect: '%s', actual: '%s'", csSpec.KubernetesSpecConfig.VnetCNILinuxPluginsDownloadURL, vlabscsSpec.KubernetesSpecConfig.VnetCNILinuxPluginsDownloadURL) + } + if vlabscsSpec.KubernetesSpecConfig.VnetCNIWindowsPluginsDownloadURL != csSpec.KubernetesSpecConfig.VnetCNIWindowsPluginsDownloadURL { + t.Errorf("incorrect VnetCNIWindowsPluginsDownloadURL, expect: '%s', actual: '%s'", csSpec.KubernetesSpecConfig.VnetCNIWindowsPluginsDownloadURL, vlabscsSpec.KubernetesSpecConfig.VnetCNIWindowsPluginsDownloadURL) + } + if vlabscsSpec.KubernetesSpecConfig.ContainerdDownloadURLBase != csSpec.KubernetesSpecConfig.ContainerdDownloadURLBase { + t.Errorf("incorrect ContainerdDownloadURLBase, expect: '%s', actual: '%s'", csSpec.KubernetesSpecConfig.ContainerdDownloadURLBase, vlabscsSpec.KubernetesSpecConfig.ContainerdDownloadURLBase) + } + + //DockerSpecConfig + if vlabscsSpec.DockerSpecConfig.DockerComposeDownloadURL != csSpec.DockerSpecConfig.DockerComposeDownloadURL { + t.Errorf("incorrect DockerComposeDownloadURL, expect: '%s', actual: '%s'", csSpec.DockerSpecConfig.DockerComposeDownloadURL, vlabscsSpec.DockerSpecConfig.DockerComposeDownloadURL) + } + if vlabscsSpec.DockerSpecConfig.DockerEngineRepo != csSpec.DockerSpecConfig.DockerEngineRepo { + t.Errorf("incorrect DockerEngineRepo, expect: '%s', actual: '%s'", csSpec.DockerSpecConfig.DockerEngineRepo, vlabscsSpec.DockerSpecConfig.DockerEngineRepo) + } + + //DCOSSpecConfig + if vlabscsSpec.DCOSSpecConfig.DCOS188BootstrapDownloadURL != csSpec.DCOSSpecConfig.DCOS188BootstrapDownloadURL { + t.Errorf("incorrect DCOS188BootstrapDownloadURL, expect: '%s', actual: '%s'", csSpec.DCOSSpecConfig.DCOS188BootstrapDownloadURL, vlabscsSpec.DCOSSpecConfig.DCOS188BootstrapDownloadURL) + } + if vlabscsSpec.DCOSSpecConfig.DCOS190BootstrapDownloadURL != csSpec.DCOSSpecConfig.DCOS190BootstrapDownloadURL { + t.Errorf("incorrect DCOS190BootstrapDownloadURL, expect: '%s', actual: '%s'", csSpec.DCOSSpecConfig.DCOS190BootstrapDownloadURL, vlabscsSpec.DCOSSpecConfig.DCOS190BootstrapDownloadURL) + } + if vlabscsSpec.DCOSSpecConfig.DCOS198BootstrapDownloadURL != csSpec.DCOSSpecConfig.DCOS198BootstrapDownloadURL { + t.Errorf("incorrect DCOS198BootstrapDownloadURL, expect: '%s', actual: '%s'", csSpec.DCOSSpecConfig.DCOS198BootstrapDownloadURL, vlabscsSpec.DCOSSpecConfig.DCOS198BootstrapDownloadURL) + } + if vlabscsSpec.DCOSSpecConfig.DCOS110BootstrapDownloadURL != csSpec.DCOSSpecConfig.DCOS110BootstrapDownloadURL { + t.Errorf("incorrect DCOS110BootstrapDownloadURL, expect: '%s', actual: '%s'", csSpec.DCOSSpecConfig.DCOS110BootstrapDownloadURL, vlabscsSpec.DCOSSpecConfig.DCOS110BootstrapDownloadURL) + } + if vlabscsSpec.DCOSSpecConfig.DCOS111BootstrapDownloadURL != csSpec.DCOSSpecConfig.DCOS111BootstrapDownloadURL { + t.Errorf("incorrect DCOS111BootstrapDownloadURL, expect: '%s', actual: '%s'", csSpec.DCOSSpecConfig.DCOS111BootstrapDownloadURL, vlabscsSpec.DCOSSpecConfig.DCOS111BootstrapDownloadURL) + } + if vlabscsSpec.DCOSSpecConfig.DCOSWindowsBootstrapDownloadURL != csSpec.DCOSSpecConfig.DCOSWindowsBootstrapDownloadURL { + t.Errorf("incorrect DCOSWindowsBootstrapDownloadURL, expect: '%s', actual: '%s'", csSpec.DCOSSpecConfig.DCOSWindowsBootstrapDownloadURL, vlabscsSpec.DCOSSpecConfig.DCOSWindowsBootstrapDownloadURL) + } + if vlabscsSpec.DCOSSpecConfig.DcosRepositoryURL != csSpec.DCOSSpecConfig.DcosRepositoryURL { + t.Errorf("incorrect DcosRepositoryURL, expect: '%s', actual: '%s'", csSpec.DCOSSpecConfig.DcosRepositoryURL, vlabscsSpec.DCOSSpecConfig.DcosRepositoryURL) + } + if vlabscsSpec.DCOSSpecConfig.DcosClusterPackageListID != csSpec.DCOSSpecConfig.DcosClusterPackageListID { + t.Errorf("incorrect DcosClusterPackageListID, expect: '%s', actual: '%s'", csSpec.DCOSSpecConfig.DcosClusterPackageListID, vlabscsSpec.DCOSSpecConfig.DcosClusterPackageListID) + } + if vlabscsSpec.DCOSSpecConfig.DcosProviderPackageID != csSpec.DCOSSpecConfig.DcosProviderPackageID { + t.Errorf("incorrect DcosProviderPackageID, expect: '%s', actual: '%s'", csSpec.DCOSSpecConfig.DcosProviderPackageID, vlabscsSpec.DCOSSpecConfig.DcosProviderPackageID) + } + + //EndpointConfig + if vlabscsSpec.EndpointConfig.ResourceManagerVMDNSSuffix != csSpec.EndpointConfig.ResourceManagerVMDNSSuffix { + t.Errorf("incorrect ResourceManagerVMDNSSuffix, expect: '%s', actual: '%s'", csSpec.EndpointConfig.ResourceManagerVMDNSSuffix, vlabscsSpec.EndpointConfig.ResourceManagerVMDNSSuffix) + } + + //OSImageConfig + for k, v := range csSpec.OSImageConfig { + if actualValue, ok := vlabscsSpec.OSImageConfig[vlabs.Distro(string(k))]; ok { + if v.ImageOffer != actualValue.ImageOffer { + t.Errorf("incorrect ImageOffer for '%s', expect: '%s', actual: '%s'", string(k), v.ImageOffer, actualValue.ImageOffer) + } + if v.ImagePublisher != actualValue.ImagePublisher { + t.Errorf("incorrect ImagePublisher for '%s', expect: '%s', actual: '%s'", string(k), v.ImagePublisher, actualValue.ImagePublisher) + } + if v.ImageSku != actualValue.ImageSku { + t.Errorf("incorrect ImageSku for '%s', expect: '%s', actual: '%s'", string(k), v.ImageSku, actualValue.ImageSku) + } + if v.ImageVersion != actualValue.ImageVersion { + t.Errorf("incorrect ImageVersion for '%s', expect: '%s', actual: '%s'", string(k), v.ImageVersion, actualValue.ImageVersion) + } + } else { + t.Errorf("incorrect OSImageConfig: '%s' is missing", string(k)) + } + } +} diff --git a/pkg/api/convertertoapi.go b/pkg/api/convertertoapi.go index 083fd3b059c..01db928c02f 100644 --- a/pkg/api/convertertoapi.go +++ b/pkg/api/convertertoapi.go @@ -1247,4 +1247,54 @@ func convertVLabsCustomCloudProfile(vlabs *vlabs.CustomCloudProfile, api *Custom api.Environment.ContainerRegistryDNSSuffix = vlabs.Environment.ContainerRegistryDNSSuffix api.Environment.TokenAudience = vlabs.Environment.TokenAudience } + if vlabs.AzureEnvironmentSpecConfig != nil { + api.AzureEnvironmentSpecConfig = &AzureEnvironmentSpecConfig{} + convertAzureEnvironmentSpecConfig(vlabs.AzureEnvironmentSpecConfig, api.AzureEnvironmentSpecConfig) + } +} + +func convertAzureEnvironmentSpecConfig(vlabses *vlabs.AzureEnvironmentSpecConfig, api *AzureEnvironmentSpecConfig) { + api.CloudName = vlabses.CloudName + api.DCOSSpecConfig = DCOSSpecConfig{ + DCOS188BootstrapDownloadURL: vlabses.DCOSSpecConfig.DCOS188BootstrapDownloadURL, + DCOS190BootstrapDownloadURL: vlabses.DCOSSpecConfig.DCOS190BootstrapDownloadURL, + DCOS198BootstrapDownloadURL: vlabses.DCOSSpecConfig.DCOS198BootstrapDownloadURL, + DCOS110BootstrapDownloadURL: vlabses.DCOSSpecConfig.DCOS110BootstrapDownloadURL, + DCOS111BootstrapDownloadURL: vlabses.DCOSSpecConfig.DCOS111BootstrapDownloadURL, + DCOSWindowsBootstrapDownloadURL: vlabses.DCOSSpecConfig.DCOSWindowsBootstrapDownloadURL, + DcosRepositoryURL: vlabses.DCOSSpecConfig.DcosRepositoryURL, + DcosClusterPackageListID: vlabses.DCOSSpecConfig.DcosClusterPackageListID, + DcosProviderPackageID: vlabses.DCOSSpecConfig.DcosProviderPackageID, + } + + api.DockerSpecConfig = DockerSpecConfig{ + DockerEngineRepo: vlabses.DockerSpecConfig.DockerEngineRepo, + DockerComposeDownloadURL: vlabses.DockerSpecConfig.DockerComposeDownloadURL, + } + api.EndpointConfig = AzureEndpointConfig{ + ResourceManagerVMDNSSuffix: vlabses.EndpointConfig.ResourceManagerVMDNSSuffix, + } + api.KubernetesSpecConfig = KubernetesSpecConfig{ + KubernetesImageBase: vlabses.KubernetesSpecConfig.KubernetesImageBase, + TillerImageBase: vlabses.KubernetesSpecConfig.TillerImageBase, + ACIConnectorImageBase: vlabses.KubernetesSpecConfig.ACIConnectorImageBase, + NVIDIAImageBase: vlabses.KubernetesSpecConfig.NVIDIAImageBase, + AzureCNIImageBase: vlabses.KubernetesSpecConfig.AzureCNIImageBase, + EtcdDownloadURLBase: vlabses.KubernetesSpecConfig.EtcdDownloadURLBase, + KubeBinariesSASURLBase: vlabses.KubernetesSpecConfig.KubeBinariesSASURLBase, + WindowsTelemetryGUID: vlabses.KubernetesSpecConfig.WindowsTelemetryGUID, + CNIPluginsDownloadURL: vlabses.KubernetesSpecConfig.CNIPluginsDownloadURL, + VnetCNILinuxPluginsDownloadURL: vlabses.KubernetesSpecConfig.VnetCNILinuxPluginsDownloadURL, + VnetCNIWindowsPluginsDownloadURL: vlabses.KubernetesSpecConfig.VnetCNIWindowsPluginsDownloadURL, + ContainerdDownloadURLBase: vlabses.KubernetesSpecConfig.ContainerdDownloadURLBase, + } + api.OSImageConfig = map[Distro]AzureOSImageConfig{} + for k, v := range vlabses.OSImageConfig { + api.OSImageConfig[Distro(string(k))] = AzureOSImageConfig{ + ImageOffer: v.ImageOffer, + ImageSku: v.ImageSku, + ImagePublisher: v.ImagePublisher, + ImageVersion: v.ImageVersion, + } + } } diff --git a/pkg/api/convertertoapi_test.go b/pkg/api/convertertoapi_test.go index ae454845f13..ef927571e44 100644 --- a/pkg/api/convertertoapi_test.go +++ b/pkg/api/convertertoapi_test.go @@ -323,63 +323,225 @@ func TestCustomCloudProfile(t *testing.T) { t.Fatalf("failed to convert: '%s'", err) } if cs.Properties.CustomCloudProfile.Environment.Name != name { - t.Fatalf("incorrect Name, expect: '%s', actual: '%s'", name, cs.Properties.CustomCloudProfile.Environment.Name) + t.Errorf("incorrect Name, expect: '%s', actual: '%s'", name, cs.Properties.CustomCloudProfile.Environment.Name) } if cs.Properties.CustomCloudProfile.Environment.ManagementPortalURL != managementPortalURL { - t.Fatalf("incorrect ManagementPortalURL, expect: '%s', actual: '%s'", managementPortalURL, cs.Properties.CustomCloudProfile.Environment.ManagementPortalURL) + t.Errorf("incorrect ManagementPortalURL, expect: '%s', actual: '%s'", managementPortalURL, cs.Properties.CustomCloudProfile.Environment.ManagementPortalURL) } if cs.Properties.CustomCloudProfile.Environment.PublishSettingsURL != publishSettingsURL { - t.Fatalf("incorrect PublishSettingsURL, expect: '%s', actual: '%s'", publishSettingsURL, cs.Properties.CustomCloudProfile.Environment.PublishSettingsURL) + t.Errorf("incorrect PublishSettingsURL, expect: '%s', actual: '%s'", publishSettingsURL, cs.Properties.CustomCloudProfile.Environment.PublishSettingsURL) } if cs.Properties.CustomCloudProfile.Environment.ServiceManagementEndpoint != serviceManagementEndpoint { - t.Fatalf("incorrect ServiceManagementEndpoint, expect: '%s', actual: '%s'", serviceManagementEndpoint, cs.Properties.CustomCloudProfile.Environment.ServiceManagementEndpoint) + t.Errorf("incorrect ServiceManagementEndpoint, expect: '%s', actual: '%s'", serviceManagementEndpoint, cs.Properties.CustomCloudProfile.Environment.ServiceManagementEndpoint) } if cs.Properties.CustomCloudProfile.Environment.ResourceManagerEndpoint != resourceManagerEndpoint { - t.Fatalf("incorrect ResourceManagerEndpoint, expect: '%s', actual: '%s'", resourceManagerEndpoint, cs.Properties.CustomCloudProfile.Environment.ResourceManagerEndpoint) + t.Errorf("incorrect ResourceManagerEndpoint, expect: '%s', actual: '%s'", resourceManagerEndpoint, cs.Properties.CustomCloudProfile.Environment.ResourceManagerEndpoint) } if cs.Properties.CustomCloudProfile.Environment.ActiveDirectoryEndpoint != activeDirectoryEndpoint { - t.Fatalf("incorrect ActiveDirectoryEndpoint, expect: '%s', actual: '%s'", activeDirectoryEndpoint, cs.Properties.CustomCloudProfile.Environment.ActiveDirectoryEndpoint) + t.Errorf("incorrect ActiveDirectoryEndpoint, expect: '%s', actual: '%s'", activeDirectoryEndpoint, cs.Properties.CustomCloudProfile.Environment.ActiveDirectoryEndpoint) } if cs.Properties.CustomCloudProfile.Environment.GalleryEndpoint != galleryEndpoint { - t.Fatalf("incorrect GalleryEndpoint, expect: '%s', actual: '%s'", galleryEndpoint, cs.Properties.CustomCloudProfile.Environment.GalleryEndpoint) + t.Errorf("incorrect GalleryEndpoint, expect: '%s', actual: '%s'", galleryEndpoint, cs.Properties.CustomCloudProfile.Environment.GalleryEndpoint) } if cs.Properties.CustomCloudProfile.Environment.KeyVaultEndpoint != keyVaultEndpoint { - t.Fatalf("incorrect KeyVaultEndpoint, expect: '%s', actual: '%s'", keyVaultEndpoint, cs.Properties.CustomCloudProfile.Environment.KeyVaultEndpoint) + t.Errorf("incorrect KeyVaultEndpoint, expect: '%s', actual: '%s'", keyVaultEndpoint, cs.Properties.CustomCloudProfile.Environment.KeyVaultEndpoint) } if cs.Properties.CustomCloudProfile.Environment.GraphEndpoint != graphEndpoint { - t.Fatalf("incorrect GraphEndpoint, expect: '%s', actual: '%s'", graphEndpoint, cs.Properties.CustomCloudProfile.Environment.GraphEndpoint) + t.Errorf("incorrect GraphEndpoint, expect: '%s', actual: '%s'", graphEndpoint, cs.Properties.CustomCloudProfile.Environment.GraphEndpoint) } if cs.Properties.CustomCloudProfile.Environment.ServiceBusEndpoint != serviceBusEndpoint { - t.Fatalf("incorrect ServiceBusEndpoint, expect: '%s', actual: '%s'", serviceBusEndpoint, cs.Properties.CustomCloudProfile.Environment.ServiceBusEndpoint) + t.Errorf("incorrect ServiceBusEndpoint, expect: '%s', actual: '%s'", serviceBusEndpoint, cs.Properties.CustomCloudProfile.Environment.ServiceBusEndpoint) } if cs.Properties.CustomCloudProfile.Environment.BatchManagementEndpoint != batchManagementEndpoint { - t.Fatalf("incorrect BatchManagementEndpoint, expect: '%s', actual: '%s'", batchManagementEndpoint, cs.Properties.CustomCloudProfile.Environment.BatchManagementEndpoint) + t.Errorf("incorrect BatchManagementEndpoint, expect: '%s', actual: '%s'", batchManagementEndpoint, cs.Properties.CustomCloudProfile.Environment.BatchManagementEndpoint) } if cs.Properties.CustomCloudProfile.Environment.StorageEndpointSuffix != storageEndpointSuffix { - t.Fatalf("incorrect StorageEndpointSuffix, expect: '%s', actual: '%s'", storageEndpointSuffix, cs.Properties.CustomCloudProfile.Environment.StorageEndpointSuffix) + t.Errorf("incorrect StorageEndpointSuffix, expect: '%s', actual: '%s'", storageEndpointSuffix, cs.Properties.CustomCloudProfile.Environment.StorageEndpointSuffix) } if cs.Properties.CustomCloudProfile.Environment.SQLDatabaseDNSSuffix != sqlDatabaseDNSSuffix { - t.Fatalf("incorrect SQLDatabaseDNSSuffix, expect: '%s', actual: '%s'", sqlDatabaseDNSSuffix, cs.Properties.CustomCloudProfile.Environment.SQLDatabaseDNSSuffix) + t.Errorf("incorrect SQLDatabaseDNSSuffix, expect: '%s', actual: '%s'", sqlDatabaseDNSSuffix, cs.Properties.CustomCloudProfile.Environment.SQLDatabaseDNSSuffix) } if cs.Properties.CustomCloudProfile.Environment.TrafficManagerDNSSuffix != trafficManagerDNSSuffix { - t.Fatalf("incorrect TrafficManagerDNSSuffix, expect: '%s', actual: '%s'", trafficManagerDNSSuffix, cs.Properties.CustomCloudProfile.Environment.TrafficManagerDNSSuffix) + t.Errorf("incorrect TrafficManagerDNSSuffix, expect: '%s', actual: '%s'", trafficManagerDNSSuffix, cs.Properties.CustomCloudProfile.Environment.TrafficManagerDNSSuffix) } if cs.Properties.CustomCloudProfile.Environment.KeyVaultDNSSuffix != keyVaultDNSSuffix { - t.Fatalf("incorrect KeyVaultDNSSuffix, expect: '%s', actual: '%s'", keyVaultDNSSuffix, cs.Properties.CustomCloudProfile.Environment.KeyVaultDNSSuffix) + t.Errorf("incorrect KeyVaultDNSSuffix, expect: '%s', actual: '%s'", keyVaultDNSSuffix, cs.Properties.CustomCloudProfile.Environment.KeyVaultDNSSuffix) } if cs.Properties.CustomCloudProfile.Environment.ServiceBusEndpointSuffix != serviceBusEndpointSuffix { - t.Fatalf("incorrect ServiceBusEndpointSuffix, expect: '%s', actual: '%s'", serviceBusEndpointSuffix, cs.Properties.CustomCloudProfile.Environment.ServiceBusEndpointSuffix) + t.Errorf("incorrect ServiceBusEndpointSuffix, expect: '%s', actual: '%s'", serviceBusEndpointSuffix, cs.Properties.CustomCloudProfile.Environment.ServiceBusEndpointSuffix) } if cs.Properties.CustomCloudProfile.Environment.ServiceManagementVMDNSSuffix != serviceManagementVMDNSSuffix { - t.Fatalf("incorrect ServiceManagementVMDNSSuffix, expect: '%s', actual: '%s'", serviceManagementVMDNSSuffix, cs.Properties.CustomCloudProfile.Environment.ServiceManagementVMDNSSuffix) + t.Errorf("incorrect ServiceManagementVMDNSSuffix, expect: '%s', actual: '%s'", serviceManagementVMDNSSuffix, cs.Properties.CustomCloudProfile.Environment.ServiceManagementVMDNSSuffix) } if cs.Properties.CustomCloudProfile.Environment.ResourceManagerVMDNSSuffix != resourceManagerVMDNSSuffix { - t.Fatalf("incorrect ResourceManagerVMDNSSuffix, expect: '%s', actual: '%s'", resourceManagerVMDNSSuffix, cs.Properties.CustomCloudProfile.Environment.ResourceManagerVMDNSSuffix) + t.Errorf("incorrect ResourceManagerVMDNSSuffix, expect: '%s', actual: '%s'", resourceManagerVMDNSSuffix, cs.Properties.CustomCloudProfile.Environment.ResourceManagerVMDNSSuffix) } if cs.Properties.CustomCloudProfile.Environment.ContainerRegistryDNSSuffix != containerRegistryDNSSuffix { - t.Fatalf("incorrect ContainerRegistryDNSSuffix, expect: '%s', actual: '%s'", containerRegistryDNSSuffix, cs.Properties.CustomCloudProfile.Environment.ContainerRegistryDNSSuffix) + t.Errorf("incorrect ContainerRegistryDNSSuffix, expect: '%s', actual: '%s'", containerRegistryDNSSuffix, cs.Properties.CustomCloudProfile.Environment.ContainerRegistryDNSSuffix) } if cs.Properties.CustomCloudProfile.Environment.TokenAudience != tokenAudience { - t.Fatalf("incorrect TokenAudience, expect: '%s', actual: '%s'", tokenAudience, cs.Properties.CustomCloudProfile.Environment.TokenAudience) + t.Errorf("incorrect TokenAudience, expect: '%s', actual: '%s'", tokenAudience, cs.Properties.CustomCloudProfile.Environment.TokenAudience) + } +} + +func TestConvertAzureEnvironmentSpecConfig(t *testing.T) { + //Mock AzureEnvironmentSpecConfig + vlabscs := &vlabs.ContainerService{ + Properties: &vlabs.Properties{ + CustomCloudProfile: &vlabs.CustomCloudProfile{ + AzureEnvironmentSpecConfig: &vlabs.AzureEnvironmentSpecConfig{ + CloudName: "AzureStackCloud", + //DockerSpecConfig specify the docker engine download repo + DockerSpecConfig: vlabs.DockerSpecConfig{ + DockerEngineRepo: "DockerEngineRepo", + DockerComposeDownloadURL: "DockerComposeDownloadURL", + }, + //KubernetesSpecConfig - Due to Chinese firewall issue, the default containers from google is blocked, use the Chinese local mirror instead + KubernetesSpecConfig: vlabs.KubernetesSpecConfig{ + KubernetesImageBase: "KubernetesImageBase", + TillerImageBase: "TillerImageBase", + ACIConnectorImageBase: "ACIConnectorImageBase", + NVIDIAImageBase: "NVIDIAImageBase", + AzureCNIImageBase: "AzureCNIImageBase", + EtcdDownloadURLBase: "EtcdDownloadURLBase", + KubeBinariesSASURLBase: "KubeBinariesSASURLBase", + WindowsTelemetryGUID: "WindowsTelemetryGUID", + CNIPluginsDownloadURL: "CNIPluginsDownloadURL", + VnetCNILinuxPluginsDownloadURL: "VnetCNILinuxPluginsDownloadURL", + VnetCNIWindowsPluginsDownloadURL: "VnetCNIWindowsPluginsDownloadURL", + ContainerdDownloadURLBase: "ContainerdDownloadURLBase", + }, + DCOSSpecConfig: vlabs.DCOSSpecConfig{ + DCOS188BootstrapDownloadURL: "DCOS188BootstrapDownloadURL", + DCOS190BootstrapDownloadURL: "DCOS190BootstrapDownloadURL", + DCOS198BootstrapDownloadURL: "DCOS198BootstrapDownloadURL", + DCOS110BootstrapDownloadURL: "DCOS110BootstrapDownloadURL", + DCOS111BootstrapDownloadURL: "DCOS111BootstrapDownloadURL", + DCOSWindowsBootstrapDownloadURL: "DCOSWindowsBootstrapDownloadURL", + DcosRepositoryURL: "DcosRepositoryURL", + DcosClusterPackageListID: "DcosClusterPackageListID", + DcosProviderPackageID: "DcosProviderPackageID", + }, + EndpointConfig: vlabs.AzureEndpointConfig{ + ResourceManagerVMDNSSuffix: "ResourceManagerVMDNSSuffix", + }, + OSImageConfig: map[vlabs.Distro]vlabs.AzureOSImageConfig{ + vlabs.Distro("Test"): { + ImageOffer: "ImageOffer", + ImageSku: "ImageSku", + ImagePublisher: "ImagePublisher", + ImageVersion: "ImageVersion", + }, + }, + }, + }, + }, + } + cs := ConvertVLabsContainerService(vlabscs, false) + + csSpec := cs.Properties.CustomCloudProfile.AzureEnvironmentSpecConfig + vlabscsSpec := vlabscs.Properties.CustomCloudProfile.AzureEnvironmentSpecConfig + if csSpec.CloudName != vlabscsSpec.CloudName { + t.Errorf("incorrect CloudName, expect: '%s', actual: '%s'", vlabscsSpec.CloudName, csSpec.CloudName) + } + + //KubernetesSpecConfig + if csSpec.KubernetesSpecConfig.KubernetesImageBase != vlabscsSpec.KubernetesSpecConfig.KubernetesImageBase { + t.Errorf("incorrect KubernetesImageBase, expect: '%s', actual: '%s'", vlabscsSpec.KubernetesSpecConfig.KubernetesImageBase, csSpec.KubernetesSpecConfig.KubernetesImageBase) + } + if csSpec.KubernetesSpecConfig.TillerImageBase != vlabscsSpec.KubernetesSpecConfig.TillerImageBase { + t.Errorf("incorrect TillerImageBase, expect: '%s', actual: '%s'", vlabscsSpec.KubernetesSpecConfig.TillerImageBase, csSpec.KubernetesSpecConfig.TillerImageBase) + } + if csSpec.KubernetesSpecConfig.ACIConnectorImageBase != vlabscsSpec.KubernetesSpecConfig.ACIConnectorImageBase { + t.Errorf("incorrect ACIConnectorImageBase, expect: '%s', actual: '%s'", vlabscsSpec.KubernetesSpecConfig.ACIConnectorImageBase, csSpec.KubernetesSpecConfig.ACIConnectorImageBase) + } + if csSpec.KubernetesSpecConfig.NVIDIAImageBase != vlabscsSpec.KubernetesSpecConfig.NVIDIAImageBase { + t.Errorf("incorrect NVIDIAImageBase, expect: '%s', actual: '%s'", vlabscsSpec.KubernetesSpecConfig.NVIDIAImageBase, csSpec.KubernetesSpecConfig.NVIDIAImageBase) + } + if csSpec.KubernetesSpecConfig.AzureCNIImageBase != vlabscsSpec.KubernetesSpecConfig.AzureCNIImageBase { + t.Errorf("incorrect AzureCNIImageBase, expect: '%s', actual: '%s'", vlabscsSpec.KubernetesSpecConfig.AzureCNIImageBase, csSpec.KubernetesSpecConfig.AzureCNIImageBase) + } + if csSpec.KubernetesSpecConfig.EtcdDownloadURLBase != vlabscsSpec.KubernetesSpecConfig.EtcdDownloadURLBase { + t.Errorf("incorrect EtcdDownloadURLBase, expect: '%s', actual: '%s'", vlabscsSpec.KubernetesSpecConfig.EtcdDownloadURLBase, csSpec.KubernetesSpecConfig.EtcdDownloadURLBase) + } + if csSpec.KubernetesSpecConfig.KubeBinariesSASURLBase != vlabscsSpec.KubernetesSpecConfig.KubeBinariesSASURLBase { + t.Errorf("incorrect KubeBinariesSASURLBase, expect: '%s', actual: '%s'", vlabscsSpec.KubernetesSpecConfig.KubeBinariesSASURLBase, csSpec.KubernetesSpecConfig.KubeBinariesSASURLBase) + } + if csSpec.KubernetesSpecConfig.WindowsTelemetryGUID != vlabscsSpec.KubernetesSpecConfig.WindowsTelemetryGUID { + t.Errorf("incorrect WindowsTelemetryGUID, expect: '%s', actual: '%s'", vlabscsSpec.KubernetesSpecConfig.WindowsTelemetryGUID, csSpec.KubernetesSpecConfig.WindowsTelemetryGUID) + } + if csSpec.KubernetesSpecConfig.CNIPluginsDownloadURL != vlabscsSpec.KubernetesSpecConfig.CNIPluginsDownloadURL { + t.Errorf("incorrect CNIPluginsDownloadURL, expect: '%s', actual: '%s'", vlabscsSpec.KubernetesSpecConfig.CNIPluginsDownloadURL, csSpec.KubernetesSpecConfig.CNIPluginsDownloadURL) + } + if csSpec.KubernetesSpecConfig.VnetCNILinuxPluginsDownloadURL != vlabscsSpec.KubernetesSpecConfig.VnetCNILinuxPluginsDownloadURL { + t.Errorf("incorrect VnetCNILinuxPluginsDownloadURL, expect: '%s', actual: '%s'", vlabscsSpec.KubernetesSpecConfig.VnetCNILinuxPluginsDownloadURL, csSpec.KubernetesSpecConfig.VnetCNILinuxPluginsDownloadURL) + } + if csSpec.KubernetesSpecConfig.VnetCNIWindowsPluginsDownloadURL != vlabscsSpec.KubernetesSpecConfig.VnetCNIWindowsPluginsDownloadURL { + t.Errorf("incorrect VnetCNIWindowsPluginsDownloadURL, expect: '%s', actual: '%s'", vlabscsSpec.KubernetesSpecConfig.VnetCNIWindowsPluginsDownloadURL, csSpec.KubernetesSpecConfig.VnetCNIWindowsPluginsDownloadURL) + } + if csSpec.KubernetesSpecConfig.ContainerdDownloadURLBase != vlabscsSpec.KubernetesSpecConfig.ContainerdDownloadURLBase { + t.Errorf("incorrect ContainerdDownloadURLBase, expect: '%s', actual: '%s'", vlabscsSpec.KubernetesSpecConfig.ContainerdDownloadURLBase, csSpec.KubernetesSpecConfig.ContainerdDownloadURLBase) + } + + //DockerSpecConfig + if csSpec.DockerSpecConfig.DockerComposeDownloadURL != vlabscsSpec.DockerSpecConfig.DockerComposeDownloadURL { + t.Errorf("incorrect DockerComposeDownloadURL, expect: '%s', actual: '%s'", vlabscsSpec.DockerSpecConfig.DockerComposeDownloadURL, csSpec.DockerSpecConfig.DockerComposeDownloadURL) + } + if csSpec.DockerSpecConfig.DockerEngineRepo != vlabscsSpec.DockerSpecConfig.DockerEngineRepo { + t.Errorf("incorrect DockerEngineRepo, expect: '%s', actual: '%s'", vlabscsSpec.DockerSpecConfig.DockerEngineRepo, csSpec.DockerSpecConfig.DockerEngineRepo) + } + + //DCOSSpecConfig + if csSpec.DCOSSpecConfig.DCOS188BootstrapDownloadURL != vlabscsSpec.DCOSSpecConfig.DCOS188BootstrapDownloadURL { + t.Errorf("incorrect DCOS188BootstrapDownloadURL, expect: '%s', actual: '%s'", vlabscsSpec.DCOSSpecConfig.DCOS188BootstrapDownloadURL, csSpec.DCOSSpecConfig.DCOS188BootstrapDownloadURL) + } + if csSpec.DCOSSpecConfig.DCOS190BootstrapDownloadURL != vlabscsSpec.DCOSSpecConfig.DCOS190BootstrapDownloadURL { + t.Errorf("incorrect DCOS190BootstrapDownloadURL, expect: '%s', actual: '%s'", vlabscsSpec.DCOSSpecConfig.DCOS190BootstrapDownloadURL, csSpec.DCOSSpecConfig.DCOS190BootstrapDownloadURL) + } + if csSpec.DCOSSpecConfig.DCOS198BootstrapDownloadURL != vlabscsSpec.DCOSSpecConfig.DCOS198BootstrapDownloadURL { + t.Errorf("incorrect DCOS198BootstrapDownloadURL, expect: '%s', actual: '%s'", vlabscsSpec.DCOSSpecConfig.DCOS198BootstrapDownloadURL, csSpec.DCOSSpecConfig.DCOS198BootstrapDownloadURL) + } + if csSpec.DCOSSpecConfig.DCOS110BootstrapDownloadURL != vlabscsSpec.DCOSSpecConfig.DCOS110BootstrapDownloadURL { + t.Errorf("incorrect DCOS110BootstrapDownloadURL, expect: '%s', actual: '%s'", vlabscsSpec.DCOSSpecConfig.DCOS110BootstrapDownloadURL, csSpec.DCOSSpecConfig.DCOS110BootstrapDownloadURL) + } + if csSpec.DCOSSpecConfig.DCOS111BootstrapDownloadURL != vlabscsSpec.DCOSSpecConfig.DCOS111BootstrapDownloadURL { + t.Errorf("incorrect DCOS111BootstrapDownloadURL, expect: '%s', actual: '%s'", vlabscsSpec.DCOSSpecConfig.DCOS111BootstrapDownloadURL, csSpec.DCOSSpecConfig.DCOS111BootstrapDownloadURL) + } + if csSpec.DCOSSpecConfig.DCOSWindowsBootstrapDownloadURL != vlabscsSpec.DCOSSpecConfig.DCOSWindowsBootstrapDownloadURL { + t.Errorf("incorrect DCOSWindowsBootstrapDownloadURL, expect: '%s', actual: '%s'", vlabscsSpec.DCOSSpecConfig.DCOSWindowsBootstrapDownloadURL, csSpec.DCOSSpecConfig.DCOSWindowsBootstrapDownloadURL) + } + if csSpec.DCOSSpecConfig.DcosRepositoryURL != vlabscsSpec.DCOSSpecConfig.DcosRepositoryURL { + t.Errorf("incorrect DcosRepositoryURL, expect: '%s', actual: '%s'", vlabscsSpec.DCOSSpecConfig.DcosRepositoryURL, csSpec.DCOSSpecConfig.DcosRepositoryURL) + } + if csSpec.DCOSSpecConfig.DcosClusterPackageListID != vlabscsSpec.DCOSSpecConfig.DcosClusterPackageListID { + t.Errorf("incorrect DcosClusterPackageListID, expect: '%s', actual: '%s'", vlabscsSpec.DCOSSpecConfig.DcosClusterPackageListID, csSpec.DCOSSpecConfig.DcosClusterPackageListID) + } + if csSpec.DCOSSpecConfig.DcosProviderPackageID != vlabscsSpec.DCOSSpecConfig.DcosProviderPackageID { + t.Errorf("incorrect DcosProviderPackageID, expect: '%s', actual: '%s'", vlabscsSpec.DCOSSpecConfig.DcosProviderPackageID, csSpec.DCOSSpecConfig.DcosProviderPackageID) + } + + //EndpointConfig + if csSpec.EndpointConfig.ResourceManagerVMDNSSuffix != vlabscsSpec.EndpointConfig.ResourceManagerVMDNSSuffix { + t.Errorf("incorrect ResourceManagerVMDNSSuffix, expect: '%s', actual: '%s'", vlabscsSpec.EndpointConfig.ResourceManagerVMDNSSuffix, csSpec.EndpointConfig.ResourceManagerVMDNSSuffix) + } + + //OSImageConfig + for k, v := range vlabscsSpec.OSImageConfig { + if actualValue, ok := csSpec.OSImageConfig[Distro(string(k))]; ok { + if v.ImageOffer != actualValue.ImageOffer { + t.Errorf("incorrect ImageOffer for '%s', expect: '%s', actual: '%s'", string(k), v.ImageOffer, actualValue.ImageOffer) + } + if v.ImagePublisher != actualValue.ImagePublisher { + t.Errorf("incorrect ImagePublisher for '%s', expect: '%s', actual: '%s'", string(k), v.ImagePublisher, actualValue.ImagePublisher) + } + if v.ImageSku != actualValue.ImageSku { + t.Errorf("incorrect ImageSku for '%s', expect: '%s', actual: '%s'", string(k), v.ImageSku, actualValue.ImageSku) + } + if v.ImageVersion != actualValue.ImageVersion { + t.Errorf("incorrect ImageVersion for '%s', expect: '%s', actual: '%s'", string(k), v.ImageVersion, actualValue.ImageVersion) + } + } else { + t.Errorf("incorrect OSImageConfig: '%s' is missing", string(k)) + } } } diff --git a/pkg/api/defaults-apiserver.go b/pkg/api/defaults-apiserver.go index 73d9d355347..8356081b817 100644 --- a/pkg/api/defaults-apiserver.go +++ b/pkg/api/defaults-apiserver.go @@ -80,7 +80,7 @@ func (cs *ContainerService) setAPIServerConfig() { defaultAPIServerConfig["--oidc-groups-claim"] = "groups" defaultAPIServerConfig["--oidc-client-id"] = "spn:" + cs.Properties.AADProfile.ServerAppID issuerHost := "sts.windows.net" - if helpers.GetCloudTargetEnv(cs.Location) == "AzureChinaCloud" { + if helpers.GetTargetEnv(cs.Location, cs.Properties.GetCustomCloudName()) == "AzureChinaCloud" { issuerHost = "sts.chinacloudapi.cn" } defaultAPIServerConfig["--oidc-issuer-url"] = "https://" + issuerHost + "/" + cs.Properties.AADProfile.TenantID + "/" diff --git a/pkg/api/defaults-custom-cloud-profile.go b/pkg/api/defaults-custom-cloud-profile.go new file mode 100644 index 00000000000..a32d6be4d77 --- /dev/null +++ b/pkg/api/defaults-custom-cloud-profile.go @@ -0,0 +1,76 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +package api + +import "github.com/Azure/aks-engine/pkg/helpers" + +func (p *Properties) setCustomCloudProfileDefaults() { + + if p.IsAzureStackCloud() { + + //azureStackCloudSpec is the default configurations for azure stack with public Azure. + azureStackCloudSpec := AzureEnvironmentSpecConfig{ + CloudName: AzureStackCloud, + //DockerSpecConfig specify the docker engine download repo + DockerSpecConfig: DefaultDockerSpecConfig, + //KubernetesSpecConfig is the default kubernetes container image url. + KubernetesSpecConfig: DefaultKubernetesSpecConfig, + DCOSSpecConfig: DefaultDCOSSpecConfig, + EndpointConfig: AzureEndpointConfig{ + ResourceManagerVMDNSSuffix: "", + }, + OSImageConfig: map[Distro]AzureOSImageConfig{ + Ubuntu: DefaultUbuntuImageConfig, + RHEL: DefaultRHELOSImageConfig, + CoreOS: DefaultCoreOSImageConfig, + AKS: DefaultAKSOSImageConfig, + AKSDockerEngine: DefaultAKSDockerEngineOSImageConfig, + }, + } + + //Set default value for ResourceManagerVMDNSSuffix + azureStackCloudSpec.EndpointConfig.ResourceManagerVMDNSSuffix = p.CustomCloudProfile.Environment.ResourceManagerVMDNSSuffix + + // Use the custom input to overwrite the default values in AzureStackCloudSpec + if p.CustomCloudProfile.AzureEnvironmentSpecConfig != nil { + ascc := p.CustomCloudProfile.AzureEnvironmentSpecConfig + azureStackCloudSpec.CloudName = helpers.EnsureString(ascc.CloudName, azureStackCloudSpec.CloudName) + + // DockerSpecConfig + asccDockerSpecConfig := ascc.DockerSpecConfig + azsDockerSpecConfig := azureStackCloudSpec.DockerSpecConfig + azureStackCloudSpec.DockerSpecConfig.DockerComposeDownloadURL = helpers.EnsureString(asccDockerSpecConfig.DockerComposeDownloadURL, azsDockerSpecConfig.DockerComposeDownloadURL) + azureStackCloudSpec.DockerSpecConfig.DockerEngineRepo = helpers.EnsureString(asccDockerSpecConfig.DockerEngineRepo, azsDockerSpecConfig.DockerComposeDownloadURL) + + //KubernetesSpecConfig + asccKubernetesSpecConfig := ascc.KubernetesSpecConfig + azsKubernetesSpecConfig := azureStackCloudSpec.KubernetesSpecConfig + azureStackCloudSpec.KubernetesSpecConfig.ACIConnectorImageBase = helpers.EnsureString(asccKubernetesSpecConfig.ACIConnectorImageBase, azsKubernetesSpecConfig.ACIConnectorImageBase) + azureStackCloudSpec.KubernetesSpecConfig.AzureCNIImageBase = helpers.EnsureString(asccKubernetesSpecConfig.AzureCNIImageBase, azsKubernetesSpecConfig.AzureCNIImageBase) + azureStackCloudSpec.KubernetesSpecConfig.CNIPluginsDownloadURL = helpers.EnsureString(asccKubernetesSpecConfig.CNIPluginsDownloadURL, azsKubernetesSpecConfig.CNIPluginsDownloadURL) + azureStackCloudSpec.KubernetesSpecConfig.ContainerdDownloadURLBase = helpers.EnsureString(asccKubernetesSpecConfig.ContainerdDownloadURLBase, azsKubernetesSpecConfig.ContainerdDownloadURLBase) + azureStackCloudSpec.KubernetesSpecConfig.EtcdDownloadURLBase = helpers.EnsureString(asccKubernetesSpecConfig.EtcdDownloadURLBase, azsKubernetesSpecConfig.EtcdDownloadURLBase) + azureStackCloudSpec.KubernetesSpecConfig.KubeBinariesSASURLBase = helpers.EnsureString(asccKubernetesSpecConfig.KubeBinariesSASURLBase, azsKubernetesSpecConfig.KubeBinariesSASURLBase) + azureStackCloudSpec.KubernetesSpecConfig.KubernetesImageBase = helpers.EnsureString(asccKubernetesSpecConfig.KubernetesImageBase, azsKubernetesSpecConfig.KubernetesImageBase) + azureStackCloudSpec.KubernetesSpecConfig.NVIDIAImageBase = helpers.EnsureString(asccKubernetesSpecConfig.NVIDIAImageBase, azsKubernetesSpecConfig.NVIDIAImageBase) + azureStackCloudSpec.KubernetesSpecConfig.TillerImageBase = helpers.EnsureString(asccKubernetesSpecConfig.TillerImageBase, azsKubernetesSpecConfig.TillerImageBase) + azureStackCloudSpec.KubernetesSpecConfig.VnetCNILinuxPluginsDownloadURL = helpers.EnsureString(asccKubernetesSpecConfig.VnetCNILinuxPluginsDownloadURL, azsKubernetesSpecConfig.VnetCNILinuxPluginsDownloadURL) + azureStackCloudSpec.KubernetesSpecConfig.VnetCNIWindowsPluginsDownloadURL = helpers.EnsureString(asccKubernetesSpecConfig.VnetCNIWindowsPluginsDownloadURL, azsKubernetesSpecConfig.VnetCNIWindowsPluginsDownloadURL) + azureStackCloudSpec.KubernetesSpecConfig.WindowsTelemetryGUID = helpers.EnsureString(asccKubernetesSpecConfig.WindowsTelemetryGUID, azsKubernetesSpecConfig.WindowsTelemetryGUID) + + //EndpointConfig + asccEndpointConfig := ascc.EndpointConfig + azsEndpointConfig := azureStackCloudSpec.EndpointConfig + azureStackCloudSpec.EndpointConfig.ResourceManagerVMDNSSuffix = helpers.EnsureString(asccEndpointConfig.ResourceManagerVMDNSSuffix, azsEndpointConfig.ResourceManagerVMDNSSuffix) + + //OSImageConfig + azureStackCloudSpec.OSImageConfig = make(map[Distro]AzureOSImageConfig) + for k, v := range ascc.OSImageConfig { + azureStackCloudSpec.OSImageConfig[k] = v + } + } + p.CustomCloudProfile.AzureEnvironmentSpecConfig = &azureStackCloudSpec + AzureCloudSpecEnvMap[AzureStackCloud] = azureStackCloudSpec + } +} diff --git a/pkg/api/defaults.go b/pkg/api/defaults.go index 3b0d299e05b..a51659022e4 100644 --- a/pkg/api/defaults.go +++ b/pkg/api/defaults.go @@ -51,6 +51,10 @@ func (cs *ContainerService) SetPropertiesDefaults(isUpgrade, isScale bool) (bool properties.setHostedMasterProfileDefaults() } + // Set custom cloud profile defaults if this cluster configuration has custom cloud profile + if cs.Properties.CustomCloudProfile != nil { + properties.setCustomCloudProfileDefaults() + } certsGenerated, _, e := properties.setDefaultCerts() if e != nil { return false, e @@ -524,7 +528,7 @@ func (p *Properties) setDefaultCerts() (bool, []net.IP, error) { var azureProdFQDNs []string for _, location := range helpers.GetAzureLocations() { - azureProdFQDNs = append(azureProdFQDNs, FormatAzureProdFQDNByLocation(p.MasterProfile.DNSPrefix, location)) + azureProdFQDNs = append(azureProdFQDNs, FormatProdFQDNByLocation(p.MasterProfile.DNSPrefix, location, p.GetCustomCloudName())) } masterExtraFQDNs := append(azureProdFQDNs, p.MasterProfile.SubjectAltNames...) diff --git a/pkg/api/defaults_test.go b/pkg/api/defaults_test.go index 9e4416c6c0f..2d74927c782 100644 --- a/pkg/api/defaults_test.go +++ b/pkg/api/defaults_test.go @@ -1393,6 +1393,163 @@ func TestProxyModeDefaults(t *testing.T) { t.Fatalf("ProxyMode string not the expected default value, got %s, expected %s", properties.OrchestratorProfile.KubernetesConfig.ProxyMode, KubeProxyModeIPVS) } } +func TestSetCustomCloudProfileDefaults(t *testing.T) { + + //azureStackCloudSpec is the default configurations for azure stack with public Azure. + azureStackCloudSpec := AzureEnvironmentSpecConfig{ + CloudName: AzureStackCloud, + //DockerSpecConfig specify the docker engine download repo + DockerSpecConfig: DefaultDockerSpecConfig, + //KubernetesSpecConfig is the default kubernetes container image url. + KubernetesSpecConfig: DefaultKubernetesSpecConfig, + DCOSSpecConfig: DefaultDCOSSpecConfig, + EndpointConfig: AzureEndpointConfig{ + ResourceManagerVMDNSSuffix: "", + }, + OSImageConfig: map[Distro]AzureOSImageConfig{ + Ubuntu: DefaultUbuntuImageConfig, + RHEL: DefaultRHELOSImageConfig, + CoreOS: DefaultCoreOSImageConfig, + AKS: DefaultAKSOSImageConfig, + AKSDockerEngine: DefaultAKSDockerEngineOSImageConfig, + }, + } + + // Test that the ResourceManagerVMDNSSuffix is set in EndpointConfig + mockCS := getMockBaseContainerService("1.11.6") + mockCSP := getMockPropertiesWithCustomCloudProfile("azurestackcloud", true, true, false) + vmDNSSuffix := "contoso.net" + mockCSP.CustomCloudProfile.Environment.ResourceManagerVMDNSSuffix = vmDNSSuffix + mockCS.Properties.CustomCloudProfile = mockCSP.CustomCloudProfile + mockCS.SetPropertiesDefaults(false, false) + + if mockCS.Properties.CustomCloudProfile.AzureEnvironmentSpecConfig.EndpointConfig.ResourceManagerVMDNSSuffix != vmDNSSuffix { + t.Errorf("setCustomCloudProfileDefaults(): ResourceManagerVMDNSSuffix string not the expected default value, got %s, expected %s", mockCS.Properties.CustomCloudProfile.AzureEnvironmentSpecConfig.EndpointConfig.ResourceManagerVMDNSSuffix, vmDNSSuffix) + } + + if AzureCloudSpecEnvMap[AzureStackCloud].EndpointConfig.ResourceManagerVMDNSSuffix != vmDNSSuffix { + t.Errorf("setCustomCloudProfileDefaults(): ResourceManagerVMDNSSuffix string in AzureCloudSpecEnvMap[AzureStackCloud] not the expected default value, got %s, expected %s", azureStackCloudSpec.EndpointConfig.ResourceManagerVMDNSSuffix, vmDNSSuffix) + } + + // Test that the AzureStackCloudSpec is default when azureEnvironmentSpecConfig is empty in api model JSON file + mockCSDefaultSpec := getMockBaseContainerService("1.11.6") + mockCSPDefaultSpec := getMockPropertiesWithCustomCloudProfile("azurestackcloud", true, true, false) + mockCSDefaultSpec.Properties.CustomCloudProfile = mockCSPDefaultSpec.CustomCloudProfile + mockCSDefaultSpec.SetPropertiesDefaults(false, false) + + azsEnv := AzureCloudSpecEnvMap[AzureStackCloud] + if !reflect.DeepEqual(mockCSDefaultSpec.Properties.CustomCloudProfile.AzureEnvironmentSpecConfig, &azsEnv) { + t.Errorf("setCustomCloudProfileDefaults(): did not set AzureStackCloudSpec as default when azureEnvironmentSpecConfig is empty in api model JSON file") + } + + // Test that default assignment flow doesn't overwrite a user-provided config + mockCSCustom := getMockBaseContainerService("1.11.6") + mockCSPCustom := getMockPropertiesWithCustomCloudProfile("azurestackcloud", true, true, false) + + //Mock AzureEnvironmentSpecConfig + customCloudSpec := AzureEnvironmentSpecConfig{ + CloudName: "AzuReStackCloud", + //DockerSpecConfig specify the docker engine download repo + DockerSpecConfig: DockerSpecConfig{ + DockerEngineRepo: "DockerEngineRepo", + DockerComposeDownloadURL: "DockerComposeDownloadURL", + }, + //KubernetesSpecConfig - Due to Chinese firewall issue, the default containers from google is blocked, use the Chinese local mirror instead + KubernetesSpecConfig: KubernetesSpecConfig{ + KubernetesImageBase: "KubernetesImageBase", + TillerImageBase: "TillerImageBase", + ACIConnectorImageBase: "ACIConnectorImageBase", + NVIDIAImageBase: "NVIDIAImageBase", + AzureCNIImageBase: "AzureCNIImageBase", + EtcdDownloadURLBase: "EtcdDownloadURLBase", + KubeBinariesSASURLBase: "KubeBinariesSASURLBase", + WindowsTelemetryGUID: "WindowsTelemetryGUID", + CNIPluginsDownloadURL: "CNIPluginsDownloadURL", + VnetCNILinuxPluginsDownloadURL: "VnetCNILinuxPluginsDownloadURL", + VnetCNIWindowsPluginsDownloadURL: "VnetCNIWindowsPluginsDownloadURL", + ContainerdDownloadURLBase: "ContainerdDownloadURLBase", + }, + DCOSSpecConfig: DefaultDCOSSpecConfig, + EndpointConfig: AzureEndpointConfig{ + ResourceManagerVMDNSSuffix: "ResourceManagerVMDNSSuffix", + }, + OSImageConfig: map[Distro]AzureOSImageConfig{ + Distro("Test"): { + ImageOffer: "ImageOffer", + ImageSku: "ImageSku", + ImagePublisher: "ImagePublisher", + ImageVersion: "ImageVersion", + }, + AKS: DefaultAKSOSImageConfig, + AKSDockerEngine: DefaultAKSDockerEngineOSImageConfig, + }, + } + mockCSPCustom.CustomCloudProfile.AzureEnvironmentSpecConfig = &customCloudSpec + mockCSCustom.Properties.CustomCloudProfile = mockCSPCustom.CustomCloudProfile + mockCSCustom.SetPropertiesDefaults(false, false) + + if !reflect.DeepEqual(AzureCloudSpecEnvMap[AzureStackCloud], customCloudSpec) { + t.Errorf("setCustomCloudProfileDefaults(): did not set AzureCloudSpecEnvMap[AzureStackCloud] with customer input") + } + if !reflect.DeepEqual(mockCSCustom.Properties.CustomCloudProfile.AzureEnvironmentSpecConfig, &customCloudSpec) { + t.Errorf("setCustomCloudProfileDefaults(): did not set CustomCloudProfile.AzureEnvironmentSpecConfig with customer input") + } + + // Test that default assignment flow set the value if the field is partially missing in user-provided config + mockCSCustomP := getMockBaseContainerService("1.11.6") + mockCSPCustomP := getMockPropertiesWithCustomCloudProfile("azurestackcloud", true, true, false) + + //Mock AzureEnvironmentSpecConfig + customCloudSpecP := AzureEnvironmentSpecConfig{ + CloudName: "AzureStackCloud", + //DockerSpecConfig specify the docker engine download repo + DockerSpecConfig: DockerSpecConfig{ + DockerEngineRepo: "DockerEngineRepo", + }, + //KubernetesSpecConfig - Due to Chinese firewall issue, the default containers from google is blocked, use the Chinese local mirror instead + KubernetesSpecConfig: KubernetesSpecConfig{ + KubernetesImageBase: "KubernetesImageBase", + TillerImageBase: "TillerImageBase", + NVIDIAImageBase: "NVIDIAImageBase", + AzureCNIImageBase: "AzureCNIImageBase", + EtcdDownloadURLBase: "EtcdDownloadURLBase", + WindowsTelemetryGUID: "WindowsTelemetryGUID", + CNIPluginsDownloadURL: "CNIPluginsDownloadURL", + VnetCNILinuxPluginsDownloadURL: "VnetCNILinuxPluginsDownloadURL", + ContainerdDownloadURLBase: "ContainerdDownloadURLBase", + }, + DCOSSpecConfig: DefaultDCOSSpecConfig, + EndpointConfig: AzureEndpointConfig{ + ResourceManagerVMDNSSuffix: "ResourceManagerVMDNSSuffix", + }, + OSImageConfig: map[Distro]AzureOSImageConfig{ + Distro("Test"): { + ImageOffer: "ImageOffer", + ImageSku: "ImageSku", + ImagePublisher: "ImagePublisher", + ImageVersion: "ImageVersion", + }, + AKS: DefaultAKSOSImageConfig, + AKSDockerEngine: DefaultAKSDockerEngineOSImageConfig, + }, + } + mockCSPCustomP.CustomCloudProfile.AzureEnvironmentSpecConfig = &customCloudSpecP + mockCSCustomP.Properties.CustomCloudProfile = mockCSPCustomP.CustomCloudProfile + mockCSCustomP.SetPropertiesDefaults(false, false) + + if mockCSCustomP.Properties.CustomCloudProfile.AzureEnvironmentSpecConfig.DockerSpecConfig.DockerComposeDownloadURL != DefaultDockerSpecConfig.DockerComposeDownloadURL { + t.Errorf("setCustomCloudProfileDefaults(): did not set DockerComposeDownloadURL with default Value, got '%s', expected %s", mockCSCustomP.Properties.CustomCloudProfile.AzureEnvironmentSpecConfig.DockerSpecConfig.DockerComposeDownloadURL, DefaultDockerSpecConfig.DockerComposeDownloadURL) + } + if mockCSCustomP.Properties.CustomCloudProfile.AzureEnvironmentSpecConfig.KubernetesSpecConfig.ACIConnectorImageBase != DefaultKubernetesSpecConfig.ACIConnectorImageBase { + t.Errorf("setCustomCloudProfileDefaults(): did not set ACIConnectorImageBase with default Value, got '%s', expected %s", mockCSCustomP.Properties.CustomCloudProfile.AzureEnvironmentSpecConfig.KubernetesSpecConfig.ACIConnectorImageBase, DefaultKubernetesSpecConfig.ACIConnectorImageBase) + } + if mockCSCustomP.Properties.CustomCloudProfile.AzureEnvironmentSpecConfig.KubernetesSpecConfig.KubeBinariesSASURLBase != DefaultKubernetesSpecConfig.KubeBinariesSASURLBase { + t.Errorf("setCustomCloudProfileDefaults(): did not set KubeBinariesSASURLBase with default Value, got '%s', expected %s", mockCSCustomP.Properties.CustomCloudProfile.AzureEnvironmentSpecConfig.KubernetesSpecConfig.KubeBinariesSASURLBase, DefaultKubernetesSpecConfig.KubeBinariesSASURLBase) + } + if mockCSCustomP.Properties.CustomCloudProfile.AzureEnvironmentSpecConfig.KubernetesSpecConfig.VnetCNIWindowsPluginsDownloadURL != DefaultKubernetesSpecConfig.VnetCNIWindowsPluginsDownloadURL { + t.Errorf("setCustomCloudProfileDefaults(): did not set VnetCNIWindowsPluginsDownloadURL with default Value, got '%s', expected %s", mockCSCustomP.Properties.CustomCloudProfile.AzureEnvironmentSpecConfig.KubernetesSpecConfig.VnetCNIWindowsPluginsDownloadURL, DefaultKubernetesSpecConfig.VnetCNIWindowsPluginsDownloadURL) + } +} func getMockBaseContainerService(orchestratorVersion string) ContainerService { mockAPIProperties := getMockAPIProperties(orchestratorVersion) diff --git a/pkg/api/types.go b/pkg/api/types.go index af159f1704c..8bbc6fe9381 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -702,9 +702,10 @@ type V20180331ARMManagedContainerService struct { *v20180331.ManagedCluster } -// CustomCloudProfile Represents Azure Environment +// CustomCloudProfile represents the custom cloud profile type CustomCloudProfile struct { - Environment *azure.Environment `json:"environment,omitempty"` + Environment *azure.Environment `json:"environment,omitempty"` + AzureEnvironmentSpecConfig *AzureEnvironmentSpecConfig `json:"azureEnvironmentSpecConfig,omitempty"` } // HasWindows returns true if the cluster contains windows @@ -1401,6 +1402,17 @@ func (p *Properties) GetCustomEnvironmentJSON() string { return environmentJSON } +// GetCustomCloudName returns name of environment if customCloudProfile is provided, returns empty string if customCloudProfile is empty. +// Because customCloudProfile is empty for deployment is AzurePublicCloud, AzureChinaCloud,AzureGermanCloud,AzureUSGovernmentCloud, +// the return value will be empty string for those clouds +func (p *Properties) GetCustomCloudName() string { + var cloudProfileName string + if p.IsAzureStackCloud() { + cloudProfileName = p.CustomCloudProfile.Environment.Name + } + return cloudProfileName +} + func getDefaultNVIDIADevicePluginEnabled(p *Properties) bool { o := p.OrchestratorProfile var addonEnabled bool @@ -1492,13 +1504,13 @@ func (f *FeatureFlags) IsFeatureEnabled(feature string) bool { //for example: if the target is the public azure, then the default container image url should be k8s.gcr.io/... //if the target is azure china, then the default container image should be mirror.azure.cn:5000/google_container/... func (cs *ContainerService) GetCloudSpecConfig() AzureEnvironmentSpecConfig { - targetEnv := helpers.GetCloudTargetEnv(cs.Location) + targetEnv := helpers.GetTargetEnv(cs.Location, cs.Properties.GetCustomCloudName()) return AzureCloudSpecEnvMap[targetEnv] } // GetAzureProdFQDN returns the formatted FQDN string for a given apimodel. func (cs *ContainerService) GetAzureProdFQDN() string { - return FormatAzureProdFQDNByLocation(cs.Properties.MasterProfile.DNSPrefix, cs.Location) + return FormatProdFQDNByLocation(cs.Properties.MasterProfile.DNSPrefix, cs.Location, cs.Properties.GetCustomCloudName()) } // FormatAzureProdFQDNByLocation constructs an Azure prod fqdn @@ -1507,3 +1519,13 @@ func FormatAzureProdFQDNByLocation(fqdnPrefix string, location string) string { FQDNFormat := AzureCloudSpecEnvMap[targetEnv].EndpointConfig.ResourceManagerVMDNSSuffix return fmt.Sprintf("%s.%s."+FQDNFormat, fqdnPrefix, location) } + +// FormatProdFQDNByLocation constructs an Azure prod fqdn with custom cloud profile +// CustomCloudName is name of environment if customCloudProfile is provided, it will be empty string if customCloudProfile is empty. +// Because customCloudProfile is empty for deployment for AzurePublicCloud, AzureChinaCloud,AzureGermanCloud,AzureUSGovernmentCloud, +// The customCloudName value will be empty string for those clouds +func FormatProdFQDNByLocation(fqdnPrefix string, location string, cloudName string) string { + targetEnv := helpers.GetTargetEnv(location, cloudName) + FQDNFormat := AzureCloudSpecEnvMap[targetEnv].EndpointConfig.ResourceManagerVMDNSSuffix + return fmt.Sprintf("%s.%s."+FQDNFormat, fqdnPrefix, location) +} diff --git a/pkg/api/types_test.go b/pkg/api/types_test.go index 983994df2f6..138cada3c99 100644 --- a/pkg/api/types_test.go +++ b/pkg/api/types_test.go @@ -6,8 +6,10 @@ package api import ( "log" "reflect" + "strings" "testing" + "github.com/Azure/go-autorest/autorest/azure" "github.com/Azure/go-autorest/autorest/to" "github.com/Azure/aks-engine/pkg/api/common" @@ -2645,6 +2647,68 @@ func TestFormatAzureProdFQDN(t *testing.T) { } +func TestFormatProdFQDNByLocation(t *testing.T) { + dnsPrefix := "santest" + var actual []string + for _, location := range helpers.GetAzureLocations() { + actual = append(actual, FormatProdFQDNByLocation(dnsPrefix, location, "")) + } + + expected := []string{ + "santest.australiacentral.cloudapp.azure.com", + "santest.australiacentral2.cloudapp.azure.com", + "santest.australiaeast.cloudapp.azure.com", + "santest.australiasoutheast.cloudapp.azure.com", + "santest.brazilsouth.cloudapp.azure.com", + "santest.canadacentral.cloudapp.azure.com", + "santest.canadaeast.cloudapp.azure.com", + "santest.centralindia.cloudapp.azure.com", + "santest.centralus.cloudapp.azure.com", + "santest.centraluseuap.cloudapp.azure.com", + "santest.chinaeast.cloudapp.chinacloudapi.cn", + "santest.chinaeast2.cloudapp.chinacloudapi.cn", + "santest.chinanorth.cloudapp.chinacloudapi.cn", + "santest.chinanorth2.cloudapp.chinacloudapi.cn", + "santest.eastasia.cloudapp.azure.com", + "santest.eastus.cloudapp.azure.com", + "santest.eastus2.cloudapp.azure.com", + "santest.eastus2euap.cloudapp.azure.com", + "santest.francecentral.cloudapp.azure.com", + "santest.francesouth.cloudapp.azure.com", + "santest.japaneast.cloudapp.azure.com", + "santest.japanwest.cloudapp.azure.com", + "santest.koreacentral.cloudapp.azure.com", + "santest.koreasouth.cloudapp.azure.com", + "santest.northcentralus.cloudapp.azure.com", + "santest.northeurope.cloudapp.azure.com", + "santest.southcentralus.cloudapp.azure.com", + "santest.southeastasia.cloudapp.azure.com", + "santest.southindia.cloudapp.azure.com", + "santest.uksouth.cloudapp.azure.com", + "santest.ukwest.cloudapp.azure.com", + "santest.westcentralus.cloudapp.azure.com", + "santest.westeurope.cloudapp.azure.com", + "santest.westindia.cloudapp.azure.com", + "santest.westus.cloudapp.azure.com", + "santest.westus2.cloudapp.azure.com", + "santest.chinaeast.cloudapp.chinacloudapi.cn", + "santest.chinanorth.cloudapp.chinacloudapi.cn", + "santest.chinanorth2.cloudapp.chinacloudapi.cn", + "santest.chinaeast2.cloudapp.chinacloudapi.cn", + "santest.germanycentral.cloudapp.microsoftazure.de", + "santest.germanynortheast.cloudapp.microsoftazure.de", + "santest.usgovvirginia.cloudapp.usgovcloudapi.net", + "santest.usgoviowa.cloudapp.usgovcloudapi.net", + "santest.usgovarizona.cloudapp.usgovcloudapi.net", + "santest.usgovtexas.cloudapp.usgovcloudapi.net", + "santest.francecentral.cloudapp.azure.com", + } + + if !reflect.DeepEqual(actual, expected) { + t.Errorf("expected formatted fqdns %s, but got %s", expected, actual) + } +} + func TestKubernetesConfig_GetAddonScript(t *testing.T) { addon := getMockAddon(IPMASQAgentAddonName) addon.Data = "foobarbazdata" @@ -2877,3 +2941,176 @@ func TestKubernetesConfig_UserAssignedClientIDEnabled(t *testing.T) { t.Errorf("expected userAssignedClientIDEnabled to be false when useManagedIdentity is set to false") } } + +func TestIsAzureStackCloud(t *testing.T) { + testcases := []struct { + name string + properties Properties + expected bool + }{ + { + "Empty environment name", + getMockPropertiesWithCustomCloudProfile("", true, true, false), + false, + }, + { + "Empty environment name with AzureEnvironmentSpecConfig", + getMockPropertiesWithCustomCloudProfile("", true, true, true), + false, + }, + { + "lower case cloud name", + getMockPropertiesWithCustomCloudProfile("azurestackcloud", true, true, true), + true, + }, + { + "cammel case cloud name", + getMockPropertiesWithCustomCloudProfile("AzureStackCloud", true, true, true), + true, + }, + { + "incorrect cloud name", + getMockPropertiesWithCustomCloudProfile("NotAzureStackCloud", true, true, true), + false, + }, + { + "empty cloud profile", + getMockPropertiesWithCustomCloudProfile("AzureStackCloud", false, false, false), + false, + }, + { + "empty environment ", + getMockPropertiesWithCustomCloudProfile("AzureStackCloud", true, false, true), + false, + }, + } + for _, testcase := range testcases { + actual := testcase.properties.IsAzureStackCloud() + if testcase.expected != actual { + t.Errorf("Test \"%s\": expected IsAzureStackCloud() to return %t, but got %t . ", testcase.name, testcase.expected, actual) + } + } +} + +func TestGetCustomCloudName(t *testing.T) { + testcases := []struct { + name string + properties Properties + expected string + }{ + { + "lower case cloud name", + getMockPropertiesWithCustomCloudProfile("azurestackcloud", true, true, true), + "azurestackcloud", + }, + { + "cammel case cloud name", + getMockPropertiesWithCustomCloudProfile("AzureStackCloud", true, true, true), + "AzureStackCloud", + }, + } + for _, testcase := range testcases { + actual := testcase.properties.GetCustomCloudName() + if testcase.expected != actual { + t.Errorf("Test \"%s\": expected GetCustomCloudName() to return %s, but got %s . ", testcase.name, testcase.expected, actual) + } + } +} + +func TestGetCustomEnvironmentJSON(t *testing.T) { + expectedResult := `{"name":"azurestackcloud","managementPortalURL":"https://management.local.azurestack.external/","publishSettingsURL":"https://management.local.azurestack.external/publishsettings/index","serviceManagementEndpoint":"https://management.azurestackci15.onmicrosoft.com/36f71706-54df-4305-9847-5b038a4cf189","resourceManagerEndpoint":"https://management.local.azurestack.external/","activeDirectoryEndpoint":"https://login.windows.net/","galleryEndpoint":"https://portal.local.azurestack.external=30015/","keyVaultEndpoint":"https://vault.azurestack.external/","graphEndpoint":"https://graph.windows.net/","serviceBusEndpoint":"https://servicebus.azurestack.external/","batchManagementEndpoint":"https://batch.azurestack.external/","storageEndpointSuffix":"core.azurestack.external","sqlDatabaseDNSSuffix":"database.azurestack.external","trafficManagerDNSSuffix":"trafficmanager.cn","keyVaultDNSSuffix":"vault.azurestack.external","serviceBusEndpointSuffix":"servicebus.azurestack.external","serviceManagementVMDNSSuffix":"chinacloudapp.cn","resourceManagerVMDNSSuffix":"cloudapp.azurestack.external","containerRegistryDNSSuffix":"azurecr.io","tokenAudience":"https://management.azurestack.external/"}` + expectedResult = strings.Replace(expectedResult, "\"", "\\\"", -1) + testcases := []struct { + name string + properties Properties + expected string + }{ + { + "lower case cloud name", + getMockPropertiesWithCustomCloudProfile("azurestackcloud", true, true, true), + expectedResult, + }, + } + for _, testcase := range testcases { + actual := testcase.properties.GetCustomEnvironmentJSON() + if testcase.expected != actual { + t.Errorf("Test \"%s\": expected GetCustomEnvironmentJSON() to return %s, but got %s . ", testcase.name, testcase.expected, actual) + } + } +} + +func getMockPropertiesWithCustomCloudProfile(name string, hasCustomCloudProfile, hasEnvironment, hasAzureEnvironmentSpecConfig bool) Properties { + var ( + managementPortalURL = "https://management.local.azurestack.external/" + publishSettingsURL = "https://management.local.azurestack.external/publishsettings/index" + serviceManagementEndpoint = "https://management.azurestackci15.onmicrosoft.com/36f71706-54df-4305-9847-5b038a4cf189" + resourceManagerEndpoint = "https://management.local.azurestack.external/" + activeDirectoryEndpoint = "https://login.windows.net/" + galleryEndpoint = "https://portal.local.azurestack.external=30015/" + keyVaultEndpoint = "https://vault.azurestack.external/" + graphEndpoint = "https://graph.windows.net/" + serviceBusEndpoint = "https://servicebus.azurestack.external/" + batchManagementEndpoint = "https://batch.azurestack.external/" + storageEndpointSuffix = "core.azurestack.external" + sqlDatabaseDNSSuffix = "database.azurestack.external" + trafficManagerDNSSuffix = "trafficmanager.cn" + keyVaultDNSSuffix = "vault.azurestack.external" + serviceBusEndpointSuffix = "servicebus.azurestack.external" + serviceManagementVMDNSSuffix = "chinacloudapp.cn" + resourceManagerVMDNSSuffix = "cloudapp.azurestack.external" + containerRegistryDNSSuffix = "azurecr.io" + tokenAudience = "https://management.azurestack.external/" + ) + + p := Properties{} + if hasCustomCloudProfile { + p.CustomCloudProfile = &CustomCloudProfile{} + if hasEnvironment { + p.CustomCloudProfile.Environment = &azure.Environment{ + Name: name, + ManagementPortalURL: managementPortalURL, + PublishSettingsURL: publishSettingsURL, + ServiceManagementEndpoint: serviceManagementEndpoint, + ResourceManagerEndpoint: resourceManagerEndpoint, + ActiveDirectoryEndpoint: activeDirectoryEndpoint, + GalleryEndpoint: galleryEndpoint, + KeyVaultEndpoint: keyVaultEndpoint, + GraphEndpoint: graphEndpoint, + ServiceBusEndpoint: serviceBusEndpoint, + BatchManagementEndpoint: batchManagementEndpoint, + StorageEndpointSuffix: storageEndpointSuffix, + SQLDatabaseDNSSuffix: sqlDatabaseDNSSuffix, + TrafficManagerDNSSuffix: trafficManagerDNSSuffix, + KeyVaultDNSSuffix: keyVaultDNSSuffix, + ServiceBusEndpointSuffix: serviceBusEndpointSuffix, + ServiceManagementVMDNSSuffix: serviceManagementVMDNSSuffix, + ResourceManagerVMDNSSuffix: resourceManagerVMDNSSuffix, + ContainerRegistryDNSSuffix: containerRegistryDNSSuffix, + TokenAudience: tokenAudience, + } + } + if hasAzureEnvironmentSpecConfig { + //azureStackCloudSpec is the default configurations for azure stack with public Azure. + azureStackCloudSpec := AzureEnvironmentSpecConfig{ + CloudName: AzureStackCloud, + //DockerSpecConfig specify the docker engine download repo + DockerSpecConfig: DefaultDockerSpecConfig, + //KubernetesSpecConfig is the default kubernetes container image url. + KubernetesSpecConfig: DefaultKubernetesSpecConfig, + DCOSSpecConfig: DefaultDCOSSpecConfig, + EndpointConfig: AzureEndpointConfig{ + ResourceManagerVMDNSSuffix: "", + }, + OSImageConfig: map[Distro]AzureOSImageConfig{ + Ubuntu: DefaultUbuntuImageConfig, + RHEL: DefaultRHELOSImageConfig, + CoreOS: DefaultCoreOSImageConfig, + AKS: DefaultAKSOSImageConfig, + AKSDockerEngine: DefaultAKSDockerEngineOSImageConfig, + }, + } + p.CustomCloudProfile.AzureEnvironmentSpecConfig = &azureStackCloudSpec + } + } + return p +} diff --git a/pkg/api/vlabs/azenvtypes.go b/pkg/api/vlabs/azenvtypes.go new file mode 100644 index 00000000000..f211ce177b8 --- /dev/null +++ b/pkg/api/vlabs/azenvtypes.go @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +package vlabs + +//AzureEnvironmentSpecConfig is the overall configuration differences in different cloud environments. +type AzureEnvironmentSpecConfig struct { + CloudName string `json:"cloudName,omitempty"` + DockerSpecConfig DockerSpecConfig `json:"dockerSpecConfig,omitempty"` + KubernetesSpecConfig KubernetesSpecConfig `json:"kubernetesSpecConfig,omitempty"` + DCOSSpecConfig DCOSSpecConfig `json:"-"` + EndpointConfig AzureEndpointConfig `json:"endpointConfig,omitempty"` + OSImageConfig map[Distro]AzureOSImageConfig `json:"osImageConfig,omitempty"` +} + +//DockerSpecConfig is the configurations of docker +type DockerSpecConfig struct { + DockerEngineRepo string `json:"dockerEngineRepo,omitempty"` + DockerComposeDownloadURL string `json:"dockerComposeDownloadURL,omitempty"` +} + +//DCOSSpecConfig is the configurations of DCOS +type DCOSSpecConfig struct { + DCOS188BootstrapDownloadURL string + DCOS190BootstrapDownloadURL string + DCOS198BootstrapDownloadURL string + DCOS110BootstrapDownloadURL string + DCOS111BootstrapDownloadURL string + DCOSWindowsBootstrapDownloadURL string + DcosRepositoryURL string // For custom install, for example CI, need these three addributes + DcosClusterPackageListID string // the id of the package list file + DcosProviderPackageID string // the id of the dcos-provider-xxx package +} + +//KubernetesSpecConfig is the kubernetes container images used. +type KubernetesSpecConfig struct { + KubernetesImageBase string `json:"kubernetesImageBase,omitempty"` + TillerImageBase string `json:"tillerImageBase,omitempty"` + ACIConnectorImageBase string `json:"aciConnectorImageBase,omitempty"` + NVIDIAImageBase string `json:"nvidiaImageBase,omitempty"` + AzureCNIImageBase string `json:"azureCNIImageBase,omitempty"` + EtcdDownloadURLBase string `json:"etcdDownloadURLBase,omitempty"` + KubeBinariesSASURLBase string `json:"kubeBinariesSASURLBase,omitempty"` + WindowsTelemetryGUID string `json:"windowsTelemetryGUID,omitempty"` + CNIPluginsDownloadURL string `json:"cniPluginsDownloadURL,omitempty"` + VnetCNILinuxPluginsDownloadURL string `json:"vnetCNILinuxPluginsDownloadURL,omitempty"` + VnetCNIWindowsPluginsDownloadURL string `json:"vnetCNIWindowsPluginsDownloadURL,omitempty"` + ContainerdDownloadURLBase string `json:"containerdDownloadURLBase,omitempty"` +} + +//AzureEndpointConfig describes an Azure endpoint +type AzureEndpointConfig struct { + ResourceManagerVMDNSSuffix string `json:"resourceManagerVMDNSSuffix,omitempty"` +} + +//AzureOSImageConfig describes an Azure OS image +type AzureOSImageConfig struct { + ImageOffer string `json:"imageOffer,omitempty"` + ImageSku string `json:"imageSku,omitempty"` + ImagePublisher string `json:"imagePublisher,omitempty"` + ImageVersion string `json:"imageVersion,omitempty"` +} diff --git a/pkg/api/vlabs/types.go b/pkg/api/vlabs/types.go index eb7b8a40f83..a87a637c4d1 100644 --- a/pkg/api/vlabs/types.go +++ b/pkg/api/vlabs/types.go @@ -509,9 +509,10 @@ type OSType string // Distro represents Linux distro to use for Linux VMs type Distro string -// CustomCloudProfile Represents Azure Environment +// CustomCloudProfile represents the custom cloud profile type CustomCloudProfile struct { - Environment *azure.Environment `json:"environment,omitempty"` + Environment *azure.Environment `json:"environment,omitempty"` + AzureEnvironmentSpecConfig *AzureEnvironmentSpecConfig `json:"azureEnvironmentSpecConfig,omitempty"` } // HasWindows returns true if the cluster contains windows diff --git a/pkg/api/vlabs/validate.go b/pkg/api/vlabs/validate.go index cc104d381bc..834ec8ca064 100644 --- a/pkg/api/vlabs/validate.go +++ b/pkg/api/vlabs/validate.go @@ -1300,21 +1300,24 @@ func (a *Properties) validateCustomCloudProfile() error { if a.CustomCloudProfile.Environment == nil { return errors.New("environment needs to be specified when CustomCloudProfile is provided") } - if len(a.CustomCloudProfile.Environment.Name) == 0 { + if a.CustomCloudProfile.Environment.Name == "" { return errors.New("name needs to be specified when Environment is provided") } - if len(a.CustomCloudProfile.Environment.ServiceManagementEndpoint) == 0 { + if a.CustomCloudProfile.Environment.ServiceManagementEndpoint == "" { return errors.New("serviceManagementEndpoint needs to be specified when Environment is provided") } - if len(a.CustomCloudProfile.Environment.ResourceManagerEndpoint) == 0 { + if a.CustomCloudProfile.Environment.ResourceManagerEndpoint == "" { return errors.New("resourceManagerEndpoint needs to be specified when Environment is provided") } - if len(a.CustomCloudProfile.Environment.ActiveDirectoryEndpoint) == 0 { + if a.CustomCloudProfile.Environment.ActiveDirectoryEndpoint == "" { return errors.New("activeDirectoryEndpoint needs to be specified when Environment is provided") } - if len(a.CustomCloudProfile.Environment.GraphEndpoint) == 0 { + if a.CustomCloudProfile.Environment.GraphEndpoint == "" { return errors.New("graphEndpoint needs to be specified when Environment is provided") } + if a.CustomCloudProfile.Environment.ResourceManagerVMDNSSuffix == "" { + return errors.New("resourceManagerVMDNSSuffix needs to be specified when Environment is provided") + } } return nil } diff --git a/pkg/api/vlabs/validate_test.go b/pkg/api/vlabs/validate_test.go index 1d899aa3705..c760fc5e1fc 100644 --- a/pkg/api/vlabs/validate_test.go +++ b/pkg/api/vlabs/validate_test.go @@ -2443,6 +2443,34 @@ func TestValidateCustomCloudProfile(t *testing.T) { }, expectedErr: errors.New("graphEndpoint needs to be specified when Environment is provided"), }, + { + name: "resourceManagerVMDNSSuffix is empty", + customProfile: &CustomCloudProfile{ + Environment: &azure.Environment{ + Name: name, + ManagementPortalURL: managementPortalURL, + PublishSettingsURL: publishSettingsURL, + ServiceManagementEndpoint: serviceManagementEndpoint, + ResourceManagerEndpoint: resourceManagerEndpoint, + ActiveDirectoryEndpoint: activeDirectoryEndpoint, + GalleryEndpoint: galleryEndpoint, + KeyVaultEndpoint: keyVaultEndpoint, + GraphEndpoint: graphEndpoint, + ServiceBusEndpoint: serviceBusEndpoint, + BatchManagementEndpoint: batchManagementEndpoint, + StorageEndpointSuffix: storageEndpointSuffix, + SQLDatabaseDNSSuffix: sqlDatabaseDNSSuffix, + TrafficManagerDNSSuffix: trafficManagerDNSSuffix, + KeyVaultDNSSuffix: keyVaultDNSSuffix, + ServiceBusEndpointSuffix: serviceBusEndpointSuffix, + ServiceManagementVMDNSSuffix: serviceManagementVMDNSSuffix, + ResourceManagerVMDNSSuffix: "", + ContainerRegistryDNSSuffix: containerRegistryDNSSuffix, + TokenAudience: tokenAudience, + }, + }, + expectedErr: errors.New("resourceManagerVMDNSSuffix needs to be specified when Environment is provided"), + }, } for _, test := range tests { diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index 0278462afb3..343b0b4f7e9 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -74,7 +74,7 @@ func GenerateKubeConfig(properties *api.Properties, location string) (string, er kubeconfig = strings.Replace(kubeconfig, "{{WrapAsVerbatim \"reference(concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))).dnsSettings.fqdn\"}}", properties.MasterProfile.FirstConsecutiveStaticIP, -1) } } else { - kubeconfig = strings.Replace(kubeconfig, "{{WrapAsVerbatim \"reference(concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))).dnsSettings.fqdn\"}}", api.FormatAzureProdFQDNByLocation(properties.MasterProfile.DNSPrefix, location), -1) + kubeconfig = strings.Replace(kubeconfig, "{{WrapAsVerbatim \"reference(concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))).dnsSettings.fqdn\"}}", api.FormatProdFQDNByLocation(properties.MasterProfile.DNSPrefix, location, properties.GetCustomCloudName()), -1) } kubeconfig = strings.Replace(kubeconfig, "{{WrapAsVariable \"resourceGroup\"}}", properties.MasterProfile.DNSPrefix, -1) @@ -90,7 +90,7 @@ func GenerateKubeConfig(properties *api.Properties, location string) (string, er } authInfo = fmt.Sprintf("{\"auth-provider\":{\"name\":\"azure\",\"config\":{\"environment\":\"%v\",\"tenant-id\":\"%v\",\"apiserver-id\":\"%v\",\"client-id\":\"%v\"}}}", - helpers.GetCloudTargetEnv(location), + helpers.GetTargetEnv(location, properties.GetCustomCloudName()), tenantID, properties.AADProfile.ServerAppID, properties.AADProfile.ClientAppID) diff --git a/pkg/engine/params.go b/pkg/engine/params.go index c5a13a45aa2..a861a6586a9 100644 --- a/pkg/engine/params.go +++ b/pkg/engine/params.go @@ -38,7 +38,7 @@ func getParameters(cs *api.ContainerService, generatorCode string, aksEngineVers } addValue(parametersMap, "fqdnEndpointSuffix", cloudSpecConfig.EndpointConfig.ResourceManagerVMDNSSuffix) - addValue(parametersMap, "targetEnvironment", helpers.GetCloudTargetEnv(cs.Location)) + addValue(parametersMap, "targetEnvironment", helpers.GetTargetEnv(cs.Location, cs.Properties.GetCustomCloudName())) addValue(parametersMap, "linuxAdminUsername", properties.LinuxProfile.AdminUsername) if properties.LinuxProfile.CustomSearchDomain != nil { addValue(parametersMap, "searchDomainName", properties.LinuxProfile.CustomSearchDomain.Name) diff --git a/pkg/engine/testdata/azurestack/kubernetes.json b/pkg/engine/testdata/azurestack/kubernetes.json index 0631b1a3867..4117e6258e7 100644 --- a/pkg/engine/testdata/azurestack/kubernetes.json +++ b/pkg/engine/testdata/azurestack/kubernetes.json @@ -6,7 +6,8 @@ "orchestratorType": "Kubernetes", "orchestratorRelease": "1.11", "kubernetesConfig": { - "kubernetesImageBase": "msazurestackqa/", + "kubernetesImageBase": "k8s.gcr.io/", + "customHyperkubeImage": "msazurestackqa/hyperkube-amd64/v1.11.6", "useInstanceMetadata": false, "networkPolicy": "none" } @@ -30,7 +31,63 @@ "serviceManagementVMDNSSuffix": "cloudapp.net", "resourceManagerVMDNSSuffix": "cloudapp.azurestack.external", "containerRegistryDNSSuffix": "" - } + }, + "azureEnvironmentSpecConfig": { + "cloudName": "AzureStackCloud", + "dockerSpecConfig": { + "dockerEngineRepo": "https://aptdocker.azureedge.net/repo1", + "dockerComposeDownloadURL": "https://github.com/docker/compose/releases/download" + }, + "kubernetesSpecConfig": { + "kubernetesImageBase": "k8s.gcr.io/", + "tillerImageBase": "gcr.io/kubernetes-helm/", + "aciConnectorImageBase": "microsoft/", + "nvidiaImageBase": "nvidia/", + "azureCNIImageBase": "containernetworking/", + "etcdDownloadURLBase": "https://acs-mirror.azureedge.net/github-coreos", + "kubeBinariesSASURLBase": "https://acs-mirror.azureedge.net/wink8s/", + "windowsTelemetryGUID": "fb801154-36b9-41bc-89c2-f4d4f05472b0", + "cniPluginsDownloadURL": "https://acs-mirror.azureedge.net/cni/cni-plugins-amd64-v0.7.1.tgz", + "vnetCNILinuxPluginsDownloadURL": "https://acs-mirror.azureedge.net/cni/azure-vnet-cni-linux-amd64-v1.0.15.tgz", + "vnetCNIWindowsPluginsDownloadURL": "https://acs-mirror.azureedge.net/cni/azure-vnet-cni-windows-amd64-v1.0.15.zip", + "containerdDownloadURLBase": "https://storage.googleapis.com/cri-containerd-release/" + }, + "endpointConfig": { + "resourceManagerVMDNSSuffix": "cloudapp.azurestack.external" + }, + "osImageConfig": { + "aks": { + "imageOffer": "aks", + "imageSku": "aks-ubuntu-1604-201812", + "imagePublisher": "microsoft-aks", + "imageVersion": "2018.12.19" + }, + "aks-docker-engine": { + "imageOffer": "aks", + "imageSku": "aks-ubuntu-1604-docker-engine", + "imagePublisher": "microsoft-aks", + "imageVersion": "2018.12.19" + }, + "test": { + "imageOffer": "imageOffertest", + "imageSku": "imageSkutest", + "imagePublisher": "imagePublishertest", + "imageVersion": "imageVersiontest" + }, + "rhel": { + "imageOffer": "RHEL", + "imageSku": "7.3", + "imagePublisher": "RedHat", + "imageVersion": "latest" + }, + "ubuntu": { + "imageOffer": "UbuntuServer", + "imageSku": "16.04-LTS", + "imagePublisher": "Canonical", + "imageVersion": "latest" + } + } + } }, "masterProfile": { "dnsPrefix": "k111007", diff --git a/pkg/helpers/helpers.go b/pkg/helpers/helpers.go index 3f57fae678c..691236288b5 100644 --- a/pkg/helpers/helpers.go +++ b/pkg/helpers/helpers.go @@ -189,7 +189,7 @@ func CreateSaveSSH(username, outputDirectory string, s *i18n.Translator) (privat // GetCloudTargetEnv determines and returns whether the region is a sovereign cloud which // have their own data compliance regulations (China/Germany/USGov) or standard -// Azure public cloud +// Azure public cloud func GetCloudTargetEnv(location string) string { loc := strings.ToLower(strings.Join(strings.Fields(location), "")) switch { @@ -203,3 +203,28 @@ func GetCloudTargetEnv(location string) string { return "AzurePublicCloud" } } + +// GetTargetEnv determines and returns whether the region is a sovereign cloud which +// have their own data compliance regulations (China/Germany/USGov) or standard +// Azure public cloud +// CustomCloudName is name of environment if customCloudProfile is provided, it will be empty string if customCloudProfile is empty. +// Because customCloudProfile is empty for deployment for AzurePublicCloud, AzureChinaCloud,AzureGermanCloud,AzureUSGovernmentCloud, +// The customCloudName value will be empty string for those clouds +func GetTargetEnv(location, customCloudName string) string { + switch { + case customCloudName != "" && strings.EqualFold(customCloudName, "AzureStackCloud"): + return "AzureStackCloud" + default: + return GetCloudTargetEnv(location) + } +} + +// EnsureString returns an string for the default value. +// If val is not empty, return val +// If val is empty, return defaultVal +func EnsureString(val, defaultVal string) string { + if val != "" { + return val + } + return defaultVal +} diff --git a/pkg/helpers/helpers_test.go b/pkg/helpers/helpers_test.go index 5069cef462b..e461bc0b214 100644 --- a/pkg/helpers/helpers_test.go +++ b/pkg/helpers/helpers_test.go @@ -375,10 +375,9 @@ func TestCreateSaveSSH(t *testing.T) { t.Fatalf("ssh file was not created") } } - func TestGetCloudTargetEnv(t *testing.T) { testcases := []struct { - input string + location string expected string }{ { @@ -424,10 +423,116 @@ func TestGetCloudTargetEnv(t *testing.T) { } for _, testcase := range testcases { - actual := GetCloudTargetEnv(testcase.input) + actual := GetCloudTargetEnv(testcase.location) if testcase.expected != actual { t.Errorf("expected GetCloudTargetEnv to return %s, but got %s", testcase.expected, actual) } } +} +func TestGetTargetEnv(t *testing.T) { + testcases := []struct { + location string + clouldName string + expected string + }{ + { + "chinaeast", + "", + "AzureChinaCloud", + }, + { + "chinanorth", + "", + "AzureChinaCloud", + }, + { + "chinaeast", + "", + "AzureChinaCloud", + }, + { + "chinaeast2", + "", + "AzureChinaCloud", + }, + { + "chinanorth2", + "", + "AzureChinaCloud", + }, + { + "germanycentral", + "", + "AzureGermanCloud", + }, + { + "germanynortheast", + "", + "AzureGermanCloud", + }, + { + "usgov123", + "", + "AzureUSGovernmentCloud", + }, + { + "usdod-123", + "", + "AzureUSGovernmentCloud", + }, + { + "sampleinput", + "", + "AzurePublicCloud", + }, + { + "azurestacklocation", + "azurestackcloud", + "AzureStackCloud", + }, + { + "azurestacklocation", + "AzureStackcloud", + "AzureStackCloud", + }, + { + "azurestacklocation", + "azurestacklocation", + "AzurePublicCloud", + }, + } + + for _, testcase := range testcases { + actual := GetTargetEnv(testcase.location, testcase.clouldName) + if testcase.expected != actual { + t.Errorf("expected GetCloudTargetEnv to return %s, but got %s", testcase.expected, actual) + } + } +} + +func TestEnsureString(t *testing.T) { + testcases := []struct { + defaultstring string + overwrite string + expected string + }{ + { + "", + "randomstring", + "randomstring", + }, + { + "srcisnotempty", + "randomstring2", + "srcisnotempty", + }, + } + + for _, testcase := range testcases { + result := EnsureString(testcase.defaultstring, testcase.overwrite) + if testcase.expected != result { + t.Errorf("expected EnsureString to return %s, but got %s", testcase.expected, result) + } + } }