From aa2f90f17701b50b2488f7103d98d9ce8c2d996f Mon Sep 17 00:00:00 2001 From: Bruce Campbell Date: Fri, 5 Jan 2018 08:56:48 -0800 Subject: [PATCH] Added Windows Custom Image. Only works in dcos, but can be added to k8s --- parts/dcos/dcosWindowsAgentResourcesVmas.t | 21 +++++++++++++++++++++ parts/dcos/dcosWindowsAgentResourcesVmss.t | 21 +++++++++++++++++++++ parts/windowsparams.t | 9 ++++++++- pkg/acsengine/engine.go | 6 ++++++ pkg/acsengine/transform/json.go | 1 + pkg/api/converterfromapi.go | 1 + pkg/api/convertertoapi.go | 1 + pkg/api/types.go | 14 ++++++++++---- pkg/api/vlabs/types.go | 9 +++++---- pkg/api/vlabs/validate.go | 7 +++++++ 10 files changed, 81 insertions(+), 9 deletions(-) diff --git a/parts/dcos/dcosWindowsAgentResourcesVmas.t b/parts/dcos/dcosWindowsAgentResourcesVmas.t index b3089cfede..09f1d06970 100644 --- a/parts/dcos/dcosWindowsAgentResourcesVmas.t +++ b/parts/dcos/dcosWindowsAgentResourcesVmas.t @@ -9,6 +9,23 @@ }, "type": "Microsoft.Network/networkSecurityGroups" }, +{{if HasWindowsCustomImage}} + {"type": "Microsoft.Compute/images", + "apiVersion": "2017-12-01", + "name": "{{.Name}}CustomWindowsImage", + "location": "[variables('location')]", + "properties": { + "storageProfile": { + "osDisk": { + "osType": "Windows", + "osState": "Generalized", + "blobUri": "[parameters('agentWindowsSourceUrl')]", + "storageAccountType": "Standard_LRS" + } + } + } + }, +{{end}} { "apiVersion": "[variables('apiVersionDefault')]", "copy": { @@ -224,10 +241,14 @@ "storageProfile": { {{GetDataDisks .}} "imageReference": { +{{if HasWindowsCustomImage}} + "id": "[resourceId('Microsoft.Compute/images','{{.Name}}CustomWindowsImage')]" +{{else}} "offer": "[variables('agentWindowsOffer')]", "publisher": "[variables('agentWindowsPublisher')]", "sku": "[variables('agentWindowsSKU')]", "version": "[variables('agentWindowsVersion')]" +{{end}} } ,"osDisk": { "caching": "ReadOnly" diff --git a/parts/dcos/dcosWindowsAgentResourcesVmss.t b/parts/dcos/dcosWindowsAgentResourcesVmss.t index 7b41afe580..41de3a653f 100644 --- a/parts/dcos/dcosWindowsAgentResourcesVmss.t +++ b/parts/dcos/dcosWindowsAgentResourcesVmss.t @@ -9,6 +9,23 @@ }, "type": "Microsoft.Network/networkSecurityGroups" }, +{{if HasWindowsCustomImage}} + {"type": "Microsoft.Compute/images", + "apiVersion": "2017-12-01", + "name": "{{.Name}}CustomWindowsImage", + "location": "[variables('location')]", + "properties": { + "storageProfile": { + "osDisk": { + "osType": "Windows", + "osState": "Generalized", + "blobUri": "[parameters('agentWindowsSourceUrl')]", + "storageAccountType": "Standard_LRS" + } + } + } + }, +{{end}} {{if .IsStorageAccount}} { "apiVersion": "[variables('apiVersionStorage')]", @@ -152,10 +169,14 @@ }, "storageProfile": { "imageReference": { +{{if HasWindowsCustomImage}} + "id": "[resourceId('Microsoft.Compute/images','{{.Name}}CustomWindowsImage')]" +{{else}} "publisher": "[variables('agentWindowsPublisher')]", "offer": "[variables('agentWindowsOffer')]", "sku": "[variables('agentWindowsSku')]", "version": "latest" +{{end}} }, {{GetDataDisks .}} "osDisk": { diff --git a/parts/windowsparams.t b/parts/windowsparams.t index e3c1b5a3ef..6f66e3751f 100644 --- a/parts/windowsparams.t +++ b/parts/windowsparams.t @@ -16,4 +16,11 @@ "description": "Version of the Windows Server 2016 OS image to use for the agent virtual machines." }, "type": "string" - } \ No newline at end of file + }, + "agentWindowsSourceUrl": { + "defaultValue": "", + "metadata": { + "description": "The source of the generalized blob which will be used to create a custom windows image for the agent virtual machines." + }, + "type": "string" + } diff --git a/pkg/acsengine/engine.go b/pkg/acsengine/engine.go index af24f30573..3a61f7d6e0 100644 --- a/pkg/acsengine/engine.go +++ b/pkg/acsengine/engine.go @@ -699,6 +699,9 @@ func getParameters(cs *api.ContainerService, isClassicMode bool, generatorCode s if properties.WindowsProfile.ImageVersion != "" { addValue(parametersMap, "agentWindowsVersion", properties.WindowsProfile.ImageVersion) } + if properties.WindowsProfile.WindowsImageSourceURL != "" { + addValue(parametersMap, "agentWindowsSourceUrl", properties.WindowsProfile.WindowsImageSourceURL) + } if properties.OrchestratorProfile.OrchestratorType == api.Kubernetes { k8sVersion := properties.OrchestratorProfile.OrchestratorVersion addValue(parametersMap, "kubeBinariesSASURL", cloudSpecConfig.KubernetesSpecConfig.KubeBinariesSASURLBase+KubeConfigs[k8sVersion]["windowszip"]) @@ -1197,6 +1200,9 @@ func (t *TemplateGenerator) getTemplateFuncMap(cs *api.ContainerService) templat "HasWindowsSecrets": func() bool { return cs.Properties.WindowsProfile.HasSecrets() }, + "HasWindowsCustomImage": func() bool { + return cs.Properties.WindowsProfile.HasCustomImage() + }, "GetConfigurationScriptRootURL": func() string { if cs.Properties.LinuxProfile.ScriptRootURL == "" { return DefaultConfigurationScriptRootURL diff --git a/pkg/acsengine/transform/json.go b/pkg/acsengine/transform/json.go index f121047a13..30f639ddbd 100644 --- a/pkg/acsengine/transform/json.go +++ b/pkg/acsengine/transform/json.go @@ -1,6 +1,7 @@ package transform import ( + //fmt "encoding/json" "strings" diff --git a/pkg/api/converterfromapi.go b/pkg/api/converterfromapi.go index b5c9d1a3a0..b72e6c5939 100644 --- a/pkg/api/converterfromapi.go +++ b/pkg/api/converterfromapi.go @@ -574,6 +574,7 @@ func convertWindowsProfileToVLabs(api *WindowsProfile, vlabsProfile *vlabs.Windo vlabsProfile.AdminUsername = api.AdminUsername vlabsProfile.AdminPassword = api.AdminPassword vlabsProfile.ImageVersion = api.ImageVersion + vlabsProfile.WindowsImageSourceURL = api.WindowsImageSourceURL vlabsProfile.Secrets = []vlabs.KeyVaultSecrets{} for _, s := range api.Secrets { secret := &vlabs.KeyVaultSecrets{} diff --git a/pkg/api/convertertoapi.go b/pkg/api/convertertoapi.go index 7418c627db..cc36fddaa6 100644 --- a/pkg/api/convertertoapi.go +++ b/pkg/api/convertertoapi.go @@ -500,6 +500,7 @@ func convertVLabsWindowsProfile(vlabs *vlabs.WindowsProfile, api *WindowsProfile api.AdminUsername = vlabs.AdminUsername api.AdminPassword = vlabs.AdminPassword api.ImageVersion = vlabs.ImageVersion + api.WindowsImageSourceURL = vlabs.WindowsImageSourceURL api.Secrets = []KeyVaultSecrets{} for _, s := range vlabs.Secrets { secret := &KeyVaultSecrets{} diff --git a/pkg/api/types.go b/pkg/api/types.go index ad6e7be9ac..77326266ee 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -123,10 +123,11 @@ type PublicKey struct { // WindowsProfile represents the windows parameters passed to the cluster type WindowsProfile struct { - AdminUsername string `json:"adminUsername"` - AdminPassword string `json:"adminPassword"` - ImageVersion string `json:"imageVersion"` - Secrets []KeyVaultSecrets `json:"secrets,omitempty"` + AdminUsername string `json:"adminUsername"` + AdminPassword string `json:"adminPassword"` + ImageVersion string `json:"imageVersion"` + WindowsImageSourceURL string `json:"windowsImageSourceURL"` + Secrets []KeyVaultSecrets `json:"secrets,omitempty"` } // ProvisioningState represents the current state of container service resource. @@ -556,6 +557,11 @@ func (w *WindowsProfile) HasSecrets() bool { return len(w.Secrets) > 0 } +// HasCustomImage returns true if there is a custom windows os image url specified +func (w *WindowsProfile) HasCustomImage() bool { + return len(w.WindowsImageSourceURL) > 0 +} + // HasSecrets returns true if the customer specified secrets to install func (l *LinuxProfile) HasSecrets() bool { return len(l.Secrets) > 0 diff --git a/pkg/api/vlabs/types.go b/pkg/api/vlabs/types.go index fa9aae6194..de58196cec 100644 --- a/pkg/api/vlabs/types.go +++ b/pkg/api/vlabs/types.go @@ -125,10 +125,11 @@ type PublicKey struct { // WindowsProfile represents the windows parameters passed to the cluster type WindowsProfile struct { - AdminUsername string `json:"adminUsername,omitempty"` - AdminPassword string `json:"adminPassword,omitempty"` - ImageVersion string `json:"imageVersion,omitempty"` - Secrets []KeyVaultSecrets `json:"secrets,omitempty"` + AdminUsername string `json:"adminUsername,omitempty"` + AdminPassword string `json:"adminPassword,omitempty"` + ImageVersion string `json:"imageVersion,omitempty"` + WindowsImageSourceURL string `json:"WindowsImageSourceUrl"` + Secrets []KeyVaultSecrets `json:"secrets,omitempty"` } // ProvisioningState represents the current state of container service resource. diff --git a/pkg/api/vlabs/validate.go b/pkg/api/vlabs/validate.go index 8576b22a89..c1291a61db 100644 --- a/pkg/api/vlabs/validate.go +++ b/pkg/api/vlabs/validate.go @@ -142,6 +142,7 @@ func (o *OrchestratorProfile) Validate(isUpdate bool) error { if o.OrchestratorType != DCOS && o.DcosConfig != nil && (*o.DcosConfig != DcosConfig{}) { return fmt.Errorf("DcosConfig can be specified only when OrchestratorType is DCOS") } + return nil } @@ -453,6 +454,12 @@ func (a *Properties) Validate(isUpdate bool) error { } } + if a.OrchestratorProfile.OrchestratorType != DCOS && a.WindowsProfile != nil { + if a.WindowsProfile.WindowsImageSourceURL != "" { + return fmt.Errorf("Windows Custom Images are only supported if the Orchestrator Type is DCOS") + } + } + return nil }