diff --git a/pom.xml b/pom.xml index 4c93a338..e766c721 100644 --- a/pom.xml +++ b/pom.xml @@ -41,7 +41,7 @@ UTF-8 UTF-8 - 1.3.0 + 1.19.0 4.4.0 2.7.2 1.653 @@ -69,6 +69,10 @@ com.microsoft.azure azure-client-runtime + + javax.xml.bind + jaxb-api + diff --git a/src/main/java/com/microsoft/azure/vmagent/AzureVMAgentTemplate.java b/src/main/java/com/microsoft/azure/vmagent/AzureVMAgentTemplate.java index b67a29f6..f24cd66e 100644 --- a/src/main/java/com/microsoft/azure/vmagent/AzureVMAgentTemplate.java +++ b/src/main/java/com/microsoft/azure/vmagent/AzureVMAgentTemplate.java @@ -87,6 +87,10 @@ public static class ImageReferenceTypeClass { private String imageOffer; private String imageSku; private String imageVersion; + private String galleryName; + private String galleryImageDefinition; + private String galleryImageVersion; + private String galleryResourceGroup; @DataBoundConstructor public ImageReferenceTypeClass( @@ -95,13 +99,21 @@ public ImageReferenceTypeClass( String imagePublisher, String imageOffer, String imageSku, - String imageVersion) { + String imageVersion, + String galleryName, + String galleryImageDefinition, + String galleryImageVersion, + String galleryResourceGroup) { this.image = image; this.imageId = imageId; this.imagePublisher = imagePublisher; this.imageOffer = imageOffer; this.imageSku = imageSku; this.imageVersion = imageVersion; + this.galleryName = galleryName; + this.galleryImageDefinition = galleryImageDefinition; + this.galleryImageVersion = galleryImageVersion; + this.galleryResourceGroup = galleryResourceGroup; } public String getImage() { @@ -127,6 +139,22 @@ public String getImageSku() { public String getImageVersion() { return imageVersion; } + + public String getGalleryName() { + return galleryName; + } + + public String getGalleryImageDefinition() { + return galleryImageDefinition; + } + + public String getGalleryImageVersion() { + return galleryImageVersion; + } + + public String getGalleryResourceGroup() { + return galleryResourceGroup; + } } public static class AvailabilityTypeClass { @@ -209,6 +237,14 @@ public String getAvailabilitySet() { private final String imageVersion; + private final String galleryName; + + private final String galleryImageDefinition; + + private final String galleryImageVersion; + + private final String galleryResourceGroup; + private final String agentLaunchMethod; private boolean preInstallSsh; @@ -334,6 +370,10 @@ public AzureVMAgentTemplate( this.imageOffer = imageReferenceTypeClass.getImageOffer(); this.imageSku = imageReferenceTypeClass.getImageSku(); this.imageVersion = imageReferenceTypeClass.getImageVersion(); + this.galleryName = imageReferenceTypeClass.getGalleryName(); + this.galleryImageDefinition = imageReferenceTypeClass.getGalleryImageDefinition(); + this.galleryImageVersion = imageReferenceTypeClass.getGalleryImageVersion(); + this.galleryResourceGroup = imageReferenceTypeClass.getGalleryResourceGroup(); this.shutdownOnIdle = shutdownOnIdle; this.initScript = initScript; this.agentLaunchMethod = agentLaunchMethod; @@ -379,6 +419,17 @@ public static Map getTemplateProperties(AzureVMAgentTemplate tem isBasic ? defaultProperties.get(imageSkuName) : template.getImageSku()); templateProperties.put("imageVersion", isBasic ? defaultProperties.get(Constants.DEFAULT_IMAGE_VERSION) : template.getImageVersion()); + templateProperties.put("galleryName", + isBasic ? defaultProperties.get(Constants.DEFAULT_GALLERY_NAME) : template.getGalleryName()); + templateProperties.put("galleryImageDefinition", + isBasic ? defaultProperties.get(Constants.DEFAULT_GALLERY_IMAGE_DEFINITION) + : template.getGalleryImageDefinition()); + templateProperties.put("galleryImageVersion", + isBasic ? defaultProperties.get(Constants.DEFAULT_GALLERY_IMAGE_VERSION) + : template.getGalleryImageVersion()); + templateProperties.put("galleryResourceGroup", + isBasic ? defaultProperties.get(Constants.DEFAULT_GALLERY_RESOURCE_GROUP) + : template.getGalleryResourceGroup()); templateProperties.put("osType", isBasic ? defaultProperties.get(Constants.DEFAULT_OS_TYPE) : template.getOsType()); templateProperties.put("agentLaunchMethod", @@ -625,6 +676,9 @@ public String getImageReferenceType(ImageReferenceTypeClass imageReferenceTypeCl if (imageReferenceTypeClass.imageId != null) { return ImageReferenceType.CUSTOM_IMAGE.getName(); } + if (imageReferenceTypeClass.getGalleryName() != null) { + return ImageReferenceType.GALLERY.getName(); + } return ImageReferenceType.REFERENCE.getName(); } @@ -676,6 +730,22 @@ public String getImageVersion() { return imageVersion; } + public String getGalleryName() { + return galleryName; + } + + public String getGalleryImageDefinition() { + return galleryImageDefinition; + } + + public String getGalleryImageVersion() { + return galleryImageVersion; + } + + public String getGalleryResourceGroup() { + return galleryResourceGroup; + } + public String getInitScript() { return initScript; } @@ -832,6 +902,12 @@ public AdvancedImage getAdvancedImageInside() { return new AdvancedImageBuilder() .withCustomImage(getImage()) .withCustomManagedImage(getImageId()) + .withGalleryImage( + getGalleryName(), + getGalleryImageDefinition(), + getGalleryImageVersion(), + getGalleryResourceGroup() + ) .withReferenceImage( getImagePublisher(), getImageOffer(), @@ -937,6 +1013,10 @@ public List verifyTemplate() throws Exception { imageOffer, imageSku, imageVersion, + galleryName, + galleryImageDefinition, + galleryImageVersion, + galleryResourceGroup, agentLaunchMethod, initScript, credentialsId, @@ -1259,6 +1339,10 @@ public FormValidation doVerifyConfiguration( @RelativePath("imageReferenceTypeClass") @QueryParameter String imageOffer, @RelativePath("imageReferenceTypeClass") @QueryParameter String imageSku, @RelativePath("imageReferenceTypeClass") @QueryParameter String imageVersion, + @RelativePath("imageReferenceTypeClass") @QueryParameter String galleryName, + @RelativePath("imageReferenceTypeClass") @QueryParameter String galleryImageDefinition, + @RelativePath("imageReferenceTypeClass") @QueryParameter String galleryImageVersion, + @RelativePath("imageReferenceTypeClass") @QueryParameter String galleryResourceGroup, @QueryParameter String agentLaunchMethod, @QueryParameter String initScript, @QueryParameter String credentialsId, @@ -1313,7 +1397,11 @@ public FormValidation doVerifyConfiguration( + "subnetName: {25};\n\t" + "privateIP: {26};\n\t" + "nsgName: {27};\n\t" - + "jvmOptions: {28};", + + "jvmOptions: {28};\n\t" + + "galleryName: {29}\n\t" + + "galleryImageDefinition: {30}\n\t" + + "galleryImageVersion: {31}\n\t" + + "galleryResourceGroup: {32}", new Object[]{ "", "", @@ -1343,7 +1431,11 @@ public FormValidation doVerifyConfiguration( subnetName, usePrivateIP, nsgName, - jvmOptions}); + jvmOptions, + galleryName, + galleryImageDefinition, + galleryImageVersion, + galleryResourceGroup}); // First validate the subscription info. If it is not correct, // then we can't validate the @@ -1371,6 +1463,10 @@ public FormValidation doVerifyConfiguration( imageOffer, imageSku, imageVersion, + galleryName, + galleryImageDefinition, + galleryImageVersion, + galleryResourceGroup, agentLaunchMethod, initScript, credentialsId, diff --git a/src/main/java/com/microsoft/azure/vmagent/AzureVMManagementServiceDelegate.java b/src/main/java/com/microsoft/azure/vmagent/AzureVMManagementServiceDelegate.java index 4eef3a13..743c304d 100644 --- a/src/main/java/com/microsoft/azure/vmagent/AzureVMManagementServiceDelegate.java +++ b/src/main/java/com/microsoft/azure/vmagent/AzureVMManagementServiceDelegate.java @@ -49,6 +49,7 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.jenkinsci.plugins.cloudstats.ProvisioningActivity; +import org.joda.time.DateTime; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -248,7 +249,8 @@ public AzureVMDeploymentInfo createDeployment( if (useCustomImage) { templateLocation = EMBEDDED_TEMPLATE_IMAGE_WITH_SCRIPT_MANAGED_FILENAME; } else { - templateLocation = referenceType == ImageReferenceType.CUSTOM_IMAGE + templateLocation = (referenceType == ImageReferenceType.CUSTOM_IMAGE + || referenceType == ImageReferenceType.GALLERY) ? EMBEDDED_TEMPLATE_IMAGE_ID_WITH_SCRIPT_MANAGED_FILENAME : EMBEDDED_TEMPLATE_WITH_SCRIPT_MANAGED_FILENAME; } @@ -266,7 +268,8 @@ public AzureVMDeploymentInfo createDeployment( if (useCustomImage) { templateLocation = EMBEDDED_TEMPLATE_IMAGE_WITH_MANAGED_FILENAME; } else { - templateLocation = referenceType == ImageReferenceType.CUSTOM_IMAGE + templateLocation = (referenceType == ImageReferenceType.CUSTOM_IMAGE + || referenceType == ImageReferenceType.GALLERY) ? EMBEDDED_TEMPLATE_IMAGE_ID_WITH_MANAGED_FILENAME : EMBEDDED_TEMPLATE_WITH_MANAGED_FILENAME; } @@ -368,6 +371,36 @@ public AzureVMDeploymentInfo createDeployment( copyVariableIfNotBlank(tmp, properties, "osType"); putVariableIfNotBlank(tmp, "image", template.getImage()); + // Gallery Image is a special case for custom image, reuse the logic of custom image by replacing the imageId here + if (referenceType == ImageReferenceType.GALLERY) { + GalleryImageVersion galleryImageVersion; + String galleryImageVersionStr = template.getGalleryImageVersion(); + String galleryImageDefinition = template.getGalleryImageDefinition(); + String galleryResourceGroup = template.getGalleryResourceGroup(); + String galleryName = template.getGalleryName(); + if (StringUtils.isBlank(galleryImageVersionStr) || StringUtils.isBlank(galleryImageDefinition) || + StringUtils.isBlank(galleryResourceGroup) || StringUtils.isBlank(galleryName)) { + throw AzureCloudException.create("AzureVMManagementServiceDelegate: createDeployment: " + + "one of gallery name, gallery image version, image definition and image resource group " + + "is blank."); + } + if (Constants.VERSION_LATEST.equals(galleryImageVersionStr)) { + galleryImageVersion = getGalleryImageLatestVersion(galleryResourceGroup, + galleryName, galleryImageDefinition); + } else { + galleryImageVersion = azureClient.galleryImageVersions() + .getByGalleryImage(galleryResourceGroup, galleryName, + galleryImageDefinition, galleryImageVersionStr); + } + if (galleryImageVersion == null) { + throw AzureCloudException.create("AzureVMManagementServiceDelegate: createDeployment: " + + "Can not find the right version for the gallery image."); + } + String galleryImageId = galleryImageVersion.id(); + LOGGER.log(Level.INFO, "Create VM with gallery image id {0}", new Object[]{galleryImageId}); + putVariableIfNotBlank(tmp, "imageId", galleryImageId); + } + // If using the custom script extension (vs. SSH) to startup the powershell scripts, // add variables for that and upload the init script to the storage account if (useCustomScriptExtension) { @@ -480,6 +513,22 @@ private boolean checkImageParameter(AzureVMAgentTemplate template) { return true; } + private GalleryImageVersion getGalleryImageLatestVersion(String galleryResourceGroup, String galleryName, + String galleryImageDefinition) { + PagedList galleryImageVersions = azureClient.galleryImageVersions().listByGalleryImage(galleryResourceGroup, galleryName, galleryImageDefinition); + if (galleryImageVersions.isEmpty()) { + return null; + } + GalleryImageVersion latestVersion = galleryImageVersions.get(0); + for (int i = 1; i < galleryImageVersions.size(); i++) { + DateTime currentPublishedDate = latestVersion.publishingProfile().publishedDate(); + if (galleryImageVersions.get(i).publishingProfile().publishedDate().compareTo(currentPublishedDate) > 0) { + latestVersion = galleryImageVersions.get(i); + } + } + return latestVersion; + } + private static void putVariable(JsonNode template, String name, String value) { ObjectNode.class.cast(template.get("variables")).put(name, value); } @@ -1835,6 +1884,10 @@ public List verifyTemplate( String imageOffer, String imageSku, String imageVersion, + String galleryName, + String galleryImageDefinition, + String galleryImageVersion, + String galleryResourceGroup, String agentLaunchMethod, String initScript, String credentialsId, @@ -1907,7 +1960,11 @@ public List verifyTemplate( imagePublisher, imageOffer, imageSku, - imageVersion); + imageVersion, + galleryName, + galleryImageDefinition, + galleryImageVersion, + galleryResourceGroup); addValidationResultIfFailed(validationResult, errors); if (returnOnSingleError && errors.size() > 0) { return errors; @@ -1924,6 +1981,10 @@ public List verifyTemplate( imageOffer, imageSku, imageVersion, + galleryName, + galleryImageDefinition, + galleryImageVersion, + galleryResourceGroup, storageAccountName, storageAccountType, virtualNetworkName, @@ -1954,6 +2015,10 @@ private void verifyTemplateAsync( final String imageOffer, final String imageSku, final String imageVersion, + final String galleryName, + final String galleryImageDefinition, + final String galleryImageVersion, + final String galleryResourceGroup, final String storageAccountName, final String storageAccountType, final String virtualNetworkName, @@ -1997,7 +2062,11 @@ public String call() throws Exception { imagePublisher, imageOffer, imageSku, - imageVersion); + imageVersion, + galleryName, + galleryImageDefinition, + galleryImageVersion, + galleryResourceGroup); } }; verificationTaskList.add(callVerifyVirtualMachineImage); @@ -2125,7 +2194,11 @@ public String verifyVirtualMachineImage( String imagePublisher, String imageOffer, String imageSku, - String imageVersion) { + String imageVersion, + String galleryName, + String galleryImageDefinition, + String galleryImageVersion, + String galleryResourceGroup) { if (imageTopLevelType == null || imageTopLevelType.equals(Constants.IMAGE_TOP_LEVEL_BASIC)) { if (StringUtils.isNotBlank(builtInImage)) { // As imageTopLevelType have to be null before save the template, @@ -2177,6 +2250,23 @@ public String verifyVirtualMachineImage( } catch (Exception e) { return Messages.Azure_GC_Template_ImageID_Not_Valid(); } + } else if (referenceType == ImageReferenceType.GALLERY) { + try { + if (Constants.VERSION_LATEST.equals(galleryImageVersion)) { + PagedList galleryImageVersions = azureClient.galleryImageVersions().listByGalleryImage(galleryResourceGroup, galleryName, galleryImageDefinition); + if (galleryImageVersions.isEmpty()) { + return Messages.Azure_GC_Template_Gallery_Image_Not_Found(); + } + } else { + GalleryImageVersion galleryImage = azureClient.galleryImageVersions().getByGalleryImage(galleryResourceGroup, galleryName, galleryImageDefinition, galleryImageVersion); + if (galleryImage == null) { + return Messages.Azure_GC_Template_Gallery_Image_Not_Found(); + } + } + } catch (Exception e) { + return Messages.Azure_GC_Template_Gallery_Image_Not_Found(); + } + return Constants.OP_SUCCESS; } else { try { final String locationName = AzureUtil.getLocationNameByLabel(locationLabel); @@ -2305,7 +2395,11 @@ private static String verifyImageParameters( String imagePublisher, String imageOffer, String imageSku, - String imageVersion) { + String imageVersion, + String galleryName, + String galleryImageDefinition, + String galleryImageVersion, + String galleryResourceGroup) { if (imageTopLevelType == null || imageTopLevelType.equals(Constants.IMAGE_TOP_LEVEL_BASIC)) { // As imageTopLevelType have to be null before save the template, // so the verifyImageParameters always return success. @@ -2333,6 +2427,11 @@ private static String verifyImageParameters( && StringUtils.isNotBlank(imageSku) && StringUtils.isNotBlank(imageVersion)) { return Constants.OP_SUCCESS; + } else if (StringUtils.isNotBlank(galleryName) + && StringUtils.isNotBlank(galleryImageDefinition) + && StringUtils.isNotBlank(galleryImageVersion) + && StringUtils.isNotBlank(galleryResourceGroup)) { + return Constants.OP_SUCCESS; } else { return Messages.Azure_GC_Template_ImageReference_Not_Valid( "Image parameters should not be blank."); diff --git a/src/main/java/com/microsoft/azure/vmagent/ImageReferenceType.java b/src/main/java/com/microsoft/azure/vmagent/ImageReferenceType.java index dd72c358..0cd14d56 100644 --- a/src/main/java/com/microsoft/azure/vmagent/ImageReferenceType.java +++ b/src/main/java/com/microsoft/azure/vmagent/ImageReferenceType.java @@ -7,6 +7,7 @@ public enum ImageReferenceType { UNKNOWN("unknown"), CUSTOM("custom"), CUSTOM_IMAGE("customImage"), + GALLERY("gallery"), REFERENCE("reference"); private String name; diff --git a/src/main/java/com/microsoft/azure/vmagent/builders/AdvancedImage.java b/src/main/java/com/microsoft/azure/vmagent/builders/AdvancedImage.java index 13847a77..ee2e94a6 100644 --- a/src/main/java/com/microsoft/azure/vmagent/builders/AdvancedImage.java +++ b/src/main/java/com/microsoft/azure/vmagent/builders/AdvancedImage.java @@ -19,6 +19,14 @@ public class AdvancedImage { private String imageVersion; + private String galleryName; + + private String galleryImageDefinition; + + private String galleryImageVersion; + + private String galleryResourceGroup; + private String agentLaunchMethod; private boolean preInstallSsh; @@ -55,6 +63,10 @@ public AdvancedImage(String imageReferenceType, String imageOffer, String imageSku, String imageVersion, + String galleryName, + String galleryImageDefinition, + String galleryImageVersion, + String galleryResourceGroup, String agentLaunchMethod, boolean preInstallSsh, String initScript, @@ -77,6 +89,10 @@ public AdvancedImage(String imageReferenceType, this.imageOffer = imageOffer; this.imageSku = imageSku; this.imageVersion = imageVersion; + this.galleryName = galleryName; + this.galleryImageDefinition = galleryImageDefinition; + this.galleryImageVersion = galleryImageVersion; + this.galleryResourceGroup = galleryResourceGroup; this.agentLaunchMethod = agentLaunchMethod; this.preInstallSsh = preInstallSsh; this.initScript = initScript; @@ -124,6 +140,22 @@ public String getImageVersion() { return imageVersion; } + public String getGalleryName() { + return galleryName; + } + + public String getGalleryImageDefinition() { + return galleryImageDefinition; + } + + public String getGalleryImageVersion() { + return galleryImageVersion; + } + + public String getGalleryResourceGroup() { + return galleryResourceGroup; + } + public String getAgentLaunchMethod() { return agentLaunchMethod; } diff --git a/src/main/java/com/microsoft/azure/vmagent/builders/AdvancedImageBuilder.java b/src/main/java/com/microsoft/azure/vmagent/builders/AdvancedImageBuilder.java index 30e7d7c4..21fbd729 100644 --- a/src/main/java/com/microsoft/azure/vmagent/builders/AdvancedImageBuilder.java +++ b/src/main/java/com/microsoft/azure/vmagent/builders/AdvancedImageBuilder.java @@ -81,6 +81,10 @@ public AdvancedImage build() { fluent.getImageOffer(), fluent.getImageSku(), fluent.getImageVersion(), + fluent.getGalleryName(), + fluent.getGalleryImageDefinition(), + fluent.getGalleryImageVersion(), + fluent.getGalleryResourceGroup(), fluent.getAgentLaunchMethod(), fluent.isPreInstallSsh(), fluent.getInitScript(), diff --git a/src/main/java/com/microsoft/azure/vmagent/builders/AdvancedImageFluent.java b/src/main/java/com/microsoft/azure/vmagent/builders/AdvancedImageFluent.java index 6be1bfb7..f79e6b9e 100644 --- a/src/main/java/com/microsoft/azure/vmagent/builders/AdvancedImageFluent.java +++ b/src/main/java/com/microsoft/azure/vmagent/builders/AdvancedImageFluent.java @@ -22,6 +22,14 @@ public class AdvancedImageFluent> { private String imageVersion; + private String galleryName; + + private String galleryImageDefinition; + + private String galleryImageVersion; + + private String galleryResourceGroup; + private String agentLaunchMethod; private boolean preInstallSsh; @@ -89,6 +97,18 @@ public T withReferenceImage(String imagePublisher, return (T) this; } + public T withGalleryImage(String galleryName, + String galleryImageDefinition, + String galleryImageVersion, + String galleryResourceGroup) { + this.imageReferenceType = ImageReferenceType.GALLERY.getName(); + this.galleryName = galleryName; + this.galleryImageDefinition = galleryImageDefinition; + this.galleryImageVersion = galleryImageVersion; + this.galleryResourceGroup = galleryResourceGroup; + return (T) this; + } + public T withOsType(String osType) { this.osType = osType; return (T) this; @@ -196,6 +216,22 @@ public String getImageVersion() { return imageVersion; } + public String getGalleryName() { + return galleryName; + } + + public String getGalleryImageDefinition() { + return galleryImageDefinition; + } + + public String getGalleryImageVersion() { + return galleryImageVersion; + } + + public String getGalleryResourceGroup() { + return galleryResourceGroup; + } + public String getAgentLaunchMethod() { return agentLaunchMethod; } diff --git a/src/main/java/com/microsoft/azure/vmagent/builders/AzureVMTemplateBuilder.java b/src/main/java/com/microsoft/azure/vmagent/builders/AzureVMTemplateBuilder.java index f953c5bf..424f1511 100644 --- a/src/main/java/com/microsoft/azure/vmagent/builders/AzureVMTemplateBuilder.java +++ b/src/main/java/com/microsoft/azure/vmagent/builders/AzureVMTemplateBuilder.java @@ -99,7 +99,11 @@ public AzureVMAgentTemplate build() { fluent.getAdvancedImage().getImagePublisher(), fluent.getAdvancedImage().getImageOffer(), fluent.getAdvancedImage().getImageSku(), - fluent.getAdvancedImage().getImageVersion()), + fluent.getAdvancedImage().getImageVersion(), + fluent.getAdvancedImage().getGalleryName(), + fluent.getAdvancedImage().getGalleryImageDefinition(), + fluent.getAdvancedImage().getGalleryImageVersion(), + fluent.getAdvancedImage().getGalleryResourceGroup()), fluent.getAdvancedImage().getAgentLaunchMethod(), fluent.getAdvancedImage().isPreInstallSsh(), fluent.getAdvancedImage().getInitScript(), diff --git a/src/main/java/com/microsoft/azure/vmagent/util/Constants.java b/src/main/java/com/microsoft/azure/vmagent/util/Constants.java index 28d2bec3..9f6a31ed 100644 --- a/src/main/java/com/microsoft/azure/vmagent/util/Constants.java +++ b/src/main/java/com/microsoft/azure/vmagent/util/Constants.java @@ -132,6 +132,10 @@ public final class Constants { public static final String DEFAULT_IMAGE_SKU = "defaultImageSku"; public static final String DEFAULT_DOCKER_IMAGE_SKU = "defaultDockerImageSku"; public static final String DEFAULT_IMAGE_VERSION = "defaultImageVersion"; + public static final String DEFAULT_GALLERY_NAME = "defaultGalleryName"; + public static final String DEFAULT_GALLERY_IMAGE_DEFINITION = "defaultGalleryImageDefinition"; + public static final String DEFAULT_GALLERY_IMAGE_VERSION = "defaultGalleryImageVersion"; + public static final String DEFAULT_GALLERY_RESOURCE_GROUP = "defaultGalleryResourceGroup"; public static final String DEFAULT_OS_TYPE = "defaultOsType"; public static final String DEFAULT_LAUNCH_METHOD = "defaultLaunchMethod"; public static final String DEFAULT_PRE_INSTALL_SSH = "defaultPreInstallSsh"; @@ -226,6 +230,8 @@ public final class Constants { public static final long AZURE_DEPLOYMENT_TIMEOUT = 2 * 60 * 60; //in seconds + public static final String VERSION_LATEST = "latest"; + /** * AI constants. */ diff --git a/src/main/resources/com/microsoft/azure/vmagent/AzureVMAgentTemplate/config.jelly b/src/main/resources/com/microsoft/azure/vmagent/AzureVMAgentTemplate/config.jelly index 67bb794a..e145949d 100644 --- a/src/main/resources/com/microsoft/azure/vmagent/AzureVMAgentTemplate/config.jelly +++ b/src/main/resources/com/microsoft/azure/vmagent/AzureVMAgentTemplate/config.jelly @@ -134,6 +134,21 @@ + + + + + + + + + + + + + + + @@ -231,6 +246,6 @@ + with="azureCredentialsId,resourceGroupReferenceType,newResourceGroupName,existingResourceGroupName,maxVirtualMachinesLimit,deploymentTimeout,templateName,labels,location,virtualMachineSize,storageAccountNameReferenceType,newStorageAccountName,existingStorageAccountName,storageAccountType,noOfParallelJobs,imageTopLevelType,builtInImage,image,osType,imageId,imagePublisher,imageOffer,imageSku,imageVersion,galleryName,galleryImageDefinition,galleryImageVersion,galleryResourceGroup,agentLaunchMethod,initScript,credentialsId,virtualNetworkName,virtualNetworkResourceGroupName,subnetName,usePrivateIP,nsgName,jvmOptions,imageReferenceType"/> diff --git a/src/main/resources/com/microsoft/azure/vmagent/AzureVMAgentTemplate/config.properties b/src/main/resources/com/microsoft/azure/vmagent/AzureVMAgentTemplate/config.properties index 829d5596..59bd3142 100644 --- a/src/main/resources/com/microsoft/azure/vmagent/AzureVMAgentTemplate/config.properties +++ b/src/main/resources/com/microsoft/azure/vmagent/AzureVMAgentTemplate/config.properties @@ -34,6 +34,11 @@ Image_Publisher=Image Publisher Image_Offer=Image Offer Image_Sku=Image Sku Image_Version=Image Version +Gallery_Image=Gallery Image +Gallery_Name=Gallery Name +Gallery_Resource_Group=Resource Group +Gallery_Image_Definition=Image Definition +Gallery_Image_Version=Image Version Launch_Method=Launch Method Pre_Install_Ssh=Pre-Install SSH in Windows Slave (Check when using Windows and SSH) diff --git a/src/main/resources/com/microsoft/azure/vmagent/AzureVMAgentTemplate/help-galleryImageDefinition.html b/src/main/resources/com/microsoft/azure/vmagent/AzureVMAgentTemplate/help-galleryImageDefinition.html new file mode 100644 index 00000000..cec24812 --- /dev/null +++ b/src/main/resources/com/microsoft/azure/vmagent/AzureVMAgentTemplate/help-galleryImageDefinition.html @@ -0,0 +1,3 @@ +
+ Images are defined within a gallery and carry information about the image and requirements for using it internally. This includes whether the image is Windows or Linux, release notes, and minimum and maximum memory requirements. It is a definition of a type of image. +
diff --git a/src/main/resources/com/microsoft/azure/vmagent/AzureVMAgentTemplate/help-galleryImageVersion.html b/src/main/resources/com/microsoft/azure/vmagent/AzureVMAgentTemplate/help-galleryImageVersion.html new file mode 100644 index 00000000..29b7e06a --- /dev/null +++ b/src/main/resources/com/microsoft/azure/vmagent/AzureVMAgentTemplate/help-galleryImageVersion.html @@ -0,0 +1,4 @@ +
+ If this field is set as latest, it will use the latest published version of the gallery image. + An image version is what you use to create a VM when using a gallery. You can have multiple versions of an image as needed for your environment. Like a managed image, when you use an image version to create a VM, the image version is used to create new disks for the VM. Image versions can be used multiple times. +
diff --git a/src/main/resources/com/microsoft/azure/vmagent/AzureVMAgentTemplate/help-galleryName.html b/src/main/resources/com/microsoft/azure/vmagent/AzureVMAgentTemplate/help-galleryName.html new file mode 100644 index 00000000..c63f37df --- /dev/null +++ b/src/main/resources/com/microsoft/azure/vmagent/AzureVMAgentTemplate/help-galleryName.html @@ -0,0 +1,3 @@ +
+ Like the Azure Marketplace, an image gallery is a repository for managing and sharing images, but you control who has access. +
diff --git a/src/main/resources/com/microsoft/azure/vmagent/AzureVMAgentTemplate/help-galleryResourceGroup.html b/src/main/resources/com/microsoft/azure/vmagent/AzureVMAgentTemplate/help-galleryResourceGroup.html new file mode 100644 index 00000000..4adcfe4b --- /dev/null +++ b/src/main/resources/com/microsoft/azure/vmagent/AzureVMAgentTemplate/help-galleryResourceGroup.html @@ -0,0 +1,6 @@ +
+ Specify a resource group name for Shared Image Galleries.
+ Note
+ Resource group name can only include alphanumeric characters, periods, underscores, hyphens and parenthesis and cannot end in a period.

+ Although it will also work when you type exist resource group name in "Create new", we recommend to use "Use existing" to avoid typo. +
diff --git a/src/main/resources/com/microsoft/azure/vmagent/Messages.properties b/src/main/resources/com/microsoft/azure/vmagent/Messages.properties index 4499099b..62aff301 100644 --- a/src/main/resources/com/microsoft/azure/vmagent/Messages.properties +++ b/src/main/resources/com/microsoft/azure/vmagent/Messages.properties @@ -44,6 +44,7 @@ Azure_GC_Template_ImageURI_Not_Valid=Failed to validate the provided image locat Azure_GC_Template_ImageURI_Wrong_Storage_Account=The reference image should be in the same storage account as the one declared in the template. Azure_GC_Template_ImageReference_Not_Valid=Failed to validate the provided image reference: {0} Azure_GC_Template_ImageID_Not_Valid=The provided Image ID does not exist +Azure_GC_Template_Gallery_Image_Not_Found=The target gallery image does not exist Azure_GC_Template_ImageURI_Not_In_Same_Account=The image URI is not located in the same storage account as the target storage account for the VM Azure_GC_Template_JNLP_Not_Supported=The JNLP launch method is supported only for Windows. Azure_GC_Template_UN_Null_Or_Empty=Missing admin user name. diff --git a/src/main/resources/referenceImageIDTemplateWithManagedDisk.json b/src/main/resources/referenceImageIDTemplateWithManagedDisk.json index 4eab1f17..094c341e 100644 --- a/src/main/resources/referenceImageIDTemplateWithManagedDisk.json +++ b/src/main/resources/referenceImageIDTemplateWithManagedDisk.json @@ -57,7 +57,7 @@ } }, { - "apiVersion": "2016-04-30-preview", + "apiVersion": "2018-04-01", "type": "Microsoft.Compute/virtualMachines", "name": "[concat(variables('vmName'), copyIndex())]", "location": "[variables('location')]", diff --git a/src/test/java/com/microsoft/azure/vmagent/test/ITAzureVMManagementServiceDelegate.java b/src/test/java/com/microsoft/azure/vmagent/test/ITAzureVMManagementServiceDelegate.java index c39a0ea8..575fd36e 100644 --- a/src/test/java/com/microsoft/azure/vmagent/test/ITAzureVMManagementServiceDelegate.java +++ b/src/test/java/com/microsoft/azure/vmagent/test/ITAzureVMManagementServiceDelegate.java @@ -903,35 +903,35 @@ public void verifyVirtualMachineImageTest() { try { Assert.assertEquals(Constants.OP_SUCCESS, delegate .verifyVirtualMachineImage(testEnv.azureLocation, "", Constants.IMAGE_TOP_LEVEL_ADVANCED, ImageReferenceType.REFERENCE, "", "", - "", testEnv.azureImagePublisher, testEnv.azureImageOffer, testEnv.azureImageSku, "latest")); + "", testEnv.azureImagePublisher, testEnv.azureImageOffer, testEnv.azureImageSku, "latest", testEnv.galleryName, testEnv.galleryImageDefinition, testEnv.galleryImageVersion, testEnv.galleryResourceGroup)); Assert.assertEquals(Constants.OP_SUCCESS, delegate .verifyVirtualMachineImage(testEnv.azureLocation, "", Constants.IMAGE_TOP_LEVEL_ADVANCED, ImageReferenceType.REFERENCE, "", "", - "", testEnv.azureImagePublisher, testEnv.azureImageOffer, testEnv.azureImageSku, "")); + "", testEnv.azureImagePublisher, testEnv.azureImageOffer, testEnv.azureImageSku, "", testEnv.galleryName, testEnv.galleryImageDefinition, testEnv.galleryImageVersion, testEnv.galleryResourceGroup)); Assert.assertNotEquals(Constants.OP_SUCCESS, delegate .verifyVirtualMachineImage(testEnv.azureLocation, "", Constants.IMAGE_TOP_LEVEL_ADVANCED, ImageReferenceType.REFERENCE, "", "", - "",testEnv.azureImagePublisher, testEnv.azureImageOffer, testEnv.azureImageSku, "wrong_version")); + "",testEnv.azureImagePublisher, testEnv.azureImageOffer, testEnv.azureImageSku, "wrong_version", testEnv.galleryName, testEnv.galleryImageDefinition, testEnv.galleryImageVersion, testEnv.galleryResourceGroup)); Assert.assertNotEquals(Constants.OP_SUCCESS, delegate .verifyVirtualMachineImage(testEnv.azureLocation + "wrong", "", Constants.IMAGE_TOP_LEVEL_ADVANCED, ImageReferenceType.REFERENCE, "", "", - "",testEnv.azureImagePublisher, testEnv.azureImageOffer, testEnv.azureImageSku, "")); + "",testEnv.azureImagePublisher, testEnv.azureImageOffer, testEnv.azureImageSku, "", testEnv.galleryName, testEnv.galleryImageDefinition, testEnv.galleryImageVersion, testEnv.galleryResourceGroup)); Assert.assertNotEquals(Constants.OP_SUCCESS, delegate .verifyVirtualMachineImage(testEnv.azureLocation, "", Constants.IMAGE_TOP_LEVEL_ADVANCED, ImageReferenceType.REFERENCE, "", "", - "", testEnv.azureImagePublisher + "wrong", testEnv.azureImageOffer, testEnv.azureImageSku, "latest")); + "", testEnv.azureImagePublisher + "wrong", testEnv.azureImageOffer, testEnv.azureImageSku, "latest", testEnv.galleryName, testEnv.galleryImageDefinition, testEnv.galleryImageVersion, testEnv.galleryResourceGroup)); Assert.assertNotEquals(Constants.OP_SUCCESS, delegate .verifyVirtualMachineImage(testEnv.azureLocation, "", Constants.IMAGE_TOP_LEVEL_ADVANCED, ImageReferenceType.REFERENCE, "", "", - "", testEnv.azureImagePublisher, testEnv.azureImageOffer + "wrong", testEnv.azureImageSku, "")); + "", testEnv.azureImagePublisher, testEnv.azureImageOffer + "wrong", testEnv.azureImageSku, "", testEnv.galleryName, testEnv.galleryImageDefinition, testEnv.galleryImageVersion, testEnv.galleryResourceGroup)); Assert.assertNotEquals(Constants.OP_SUCCESS, delegate .verifyVirtualMachineImage(testEnv.azureLocation, "", Constants.IMAGE_TOP_LEVEL_ADVANCED, ImageReferenceType.REFERENCE, "", "", - "", testEnv.azureImagePublisher, testEnv.azureImageOffer, testEnv.azureImageSku + "wrong", "latest")); + "", testEnv.azureImagePublisher, testEnv.azureImageOffer, testEnv.azureImageSku + "wrong", "latest", testEnv.galleryName, testEnv.galleryImageDefinition, testEnv.galleryImageVersion, testEnv.galleryResourceGroup)); Assert.assertNotEquals(Constants.OP_SUCCESS, delegate .verifyVirtualMachineImage(testEnv.azureLocation, "", Constants.IMAGE_TOP_LEVEL_ADVANCED, ImageReferenceType.CUSTOM_IMAGE, "", "", - "", "", "", "", "")); + "", "", "", "", "", testEnv.galleryName, testEnv.galleryImageDefinition, testEnv.galleryImageVersion, testEnv.galleryResourceGroup)); } catch (Exception e) { LOGGER.log(Level.SEVERE, null, e); diff --git a/src/test/java/com/microsoft/azure/vmagent/test/IntegrationTest.java b/src/test/java/com/microsoft/azure/vmagent/test/IntegrationTest.java index 8d57c615..8ca60423 100644 --- a/src/test/java/com/microsoft/azure/vmagent/test/IntegrationTest.java +++ b/src/test/java/com/microsoft/azure/vmagent/test/IntegrationTest.java @@ -52,6 +52,7 @@ import org.junit.Before; import org.junit.ClassRule; import org.junit.Rule; +import org.junit.Test; import org.junit.rules.Timeout; import org.jvnet.hudson.test.JenkinsRule; @@ -107,6 +108,10 @@ protected static class TestEnvironment { public String azureImageOffer; public String azureImageSku; public String azureImageVersion; + public String galleryName; + public String galleryImageDefinition; + public String galleryImageVersion; + public String galleryResourceGroup; public int osDiskSize; public final String azureImageSize; public final Map blobEndpointSuffixForTemplate; @@ -136,6 +141,10 @@ protected static class TestEnvironment { azureImageOffer = TestEnvironment.loadFromEnv("VM_AGENTS_TEST_DEFAULT_IMAGE_OFFER", "UbuntuServer"); azureImageSku = TestEnvironment.loadFromEnv("VM_AGENTS_TEST_DEFAULT_IMAGE_SKU", "18.04-LTS"); azureImageVersion = TestEnvironment.loadFromEnv("VM_AGENTS_TEST_DEFAULT_IMAGE_VERSION", "latest"); + galleryName = TestEnvironment.loadFromEnv("VM_AGENTS_TEST_DEFAULT_GALLERY_NAME", ""); + galleryImageDefinition = TestEnvironment.loadFromEnv("VM_AGENTS_TEST_DEFAULT_GALLERY_IMAGE_DEFINITION", ""); + galleryImageVersion = TestEnvironment.loadFromEnv("VM_AGENTS_TEST_DEFAULT_GALLERY_IMAGE_VERSION", ""); + galleryResourceGroup = TestEnvironment.loadFromEnv("VM_AGENTS_TEST_DEFAULT_GALLERY_RESOURCE_GROUP", ""); azureImageSize = TestEnvironment.loadFromEnv("VM_AGENTS_TEST_DEFAULT_IMAGE_SIZE", "Basic_A0"); osDiskSize = 0; availabilityType = AvailabilityType.UNKNOWN.getName();