github.phpd.cn/hashicorp/packer@v1.3.2/builder/azure/arm/artifact.go (about) 1 package arm 2 3 import ( 4 "bytes" 5 "fmt" 6 "net/url" 7 "path" 8 "strings" 9 ) 10 11 const ( 12 BuilderId = "Azure.ResourceManagement.VMImage" 13 ) 14 15 type AdditionalDiskArtifact struct { 16 AdditionalDiskUri string 17 AdditionalDiskUriReadOnlySas string 18 } 19 20 type Artifact struct { 21 // OS type: Linux, Windows 22 OSType string 23 24 // VHD 25 StorageAccountLocation string 26 OSDiskUri string 27 TemplateUri string 28 OSDiskUriReadOnlySas string 29 TemplateUriReadOnlySas string 30 31 // Managed Image 32 ManagedImageResourceGroupName string 33 ManagedImageName string 34 ManagedImageLocation string 35 ManagedImageId string 36 37 // Additional Disks 38 AdditionalDisks *[]AdditionalDiskArtifact 39 } 40 41 func NewManagedImageArtifact(osType, resourceGroup, name, location, id string) (*Artifact, error) { 42 return &Artifact{ 43 ManagedImageResourceGroupName: resourceGroup, 44 ManagedImageName: name, 45 ManagedImageLocation: location, 46 ManagedImageId: id, 47 OSType: osType, 48 }, nil 49 } 50 51 func NewArtifact(template *CaptureTemplate, getSasUrl func(name string) string, osType string) (*Artifact, error) { 52 if template == nil { 53 return nil, fmt.Errorf("nil capture template") 54 } 55 56 if len(template.Resources) != 1 { 57 return nil, fmt.Errorf("malformed capture template, expected one resource") 58 } 59 60 vhdUri, err := url.Parse(template.Resources[0].Properties.StorageProfile.OSDisk.Image.Uri) 61 if err != nil { 62 return nil, err 63 } 64 65 templateUri, err := storageUriToTemplateUri(vhdUri) 66 if err != nil { 67 return nil, err 68 } 69 70 var additional_disks *[]AdditionalDiskArtifact 71 if template.Resources[0].Properties.StorageProfile.DataDisks != nil { 72 data_disks := make([]AdditionalDiskArtifact, len(template.Resources[0].Properties.StorageProfile.DataDisks)) 73 for i, additionaldisk := range template.Resources[0].Properties.StorageProfile.DataDisks { 74 additionalVhdUri, err := url.Parse(additionaldisk.Image.Uri) 75 if err != nil { 76 return nil, err 77 } 78 data_disks[i].AdditionalDiskUri = additionalVhdUri.String() 79 data_disks[i].AdditionalDiskUriReadOnlySas = getSasUrl(getStorageUrlPath(additionalVhdUri)) 80 } 81 additional_disks = &data_disks 82 } 83 84 return &Artifact{ 85 OSType: osType, 86 OSDiskUri: vhdUri.String(), 87 OSDiskUriReadOnlySas: getSasUrl(getStorageUrlPath(vhdUri)), 88 TemplateUri: templateUri.String(), 89 TemplateUriReadOnlySas: getSasUrl(getStorageUrlPath(templateUri)), 90 91 AdditionalDisks: additional_disks, 92 93 StorageAccountLocation: template.Resources[0].Location, 94 }, nil 95 } 96 97 func getStorageUrlPath(u *url.URL) string { 98 parts := strings.Split(u.Path, "/") 99 return strings.Join(parts[3:], "/") 100 } 101 102 func storageUriToTemplateUri(su *url.URL) (*url.URL, error) { 103 // packer-osDisk.4085bb15-3644-4641-b9cd-f575918640b4.vhd -> 4085bb15-3644-4641-b9cd-f575918640b4 104 filename := path.Base(su.Path) 105 parts := strings.Split(filename, ".") 106 107 if len(parts) < 3 { 108 return nil, fmt.Errorf("malformed URL") 109 } 110 111 // packer-osDisk.4085bb15-3644-4641-b9cd-f575918640b4.vhd -> packer 112 prefixParts := strings.Split(parts[0], "-") 113 prefix := strings.Join(prefixParts[:len(prefixParts)-1], "-") 114 115 templateFilename := fmt.Sprintf("%s-vmTemplate.%s.json", prefix, parts[1]) 116 117 // https://storage.blob.core.windows.net/system/Microsoft.Compute/Images/images/packer-osDisk.4085bb15-3644-4641-b9cd-f575918640b4.vhd" 118 // -> 119 // https://storage.blob.core.windows.net/system/Microsoft.Compute/Images/images/packer-vmTemplate.4085bb15-3644-4641-b9cd-f575918640b4.json" 120 return url.Parse(strings.Replace(su.String(), filename, templateFilename, 1)) 121 } 122 123 func (a *Artifact) isManagedImage() bool { 124 return a.ManagedImageResourceGroupName != "" 125 } 126 127 func (*Artifact) BuilderId() string { 128 return BuilderId 129 } 130 131 func (*Artifact) Files() []string { 132 return []string{} 133 } 134 135 func (a *Artifact) Id() string { 136 if a.OSDiskUri != "" { 137 return a.OSDiskUri 138 } 139 return a.ManagedImageId 140 } 141 142 func (a *Artifact) State(name string) interface{} { 143 switch name { 144 case "atlas.artifact.metadata": 145 return a.stateAtlasMetadata() 146 default: 147 return nil 148 } 149 } 150 151 func (a *Artifact) String() string { 152 var buf bytes.Buffer 153 154 buf.WriteString(fmt.Sprintf("%s:\n\n", a.BuilderId())) 155 buf.WriteString(fmt.Sprintf("OSType: %s\n", a.OSType)) 156 if a.isManagedImage() { 157 buf.WriteString(fmt.Sprintf("ManagedImageResourceGroupName: %s\n", a.ManagedImageResourceGroupName)) 158 buf.WriteString(fmt.Sprintf("ManagedImageName: %s\n", a.ManagedImageName)) 159 buf.WriteString(fmt.Sprintf("ManagedImageId: %s\n", a.ManagedImageId)) 160 buf.WriteString(fmt.Sprintf("ManagedImageLocation: %s\n", a.ManagedImageLocation)) 161 } else { 162 buf.WriteString(fmt.Sprintf("StorageAccountLocation: %s\n", a.StorageAccountLocation)) 163 buf.WriteString(fmt.Sprintf("OSDiskUri: %s\n", a.OSDiskUri)) 164 buf.WriteString(fmt.Sprintf("OSDiskUriReadOnlySas: %s\n", a.OSDiskUriReadOnlySas)) 165 buf.WriteString(fmt.Sprintf("TemplateUri: %s\n", a.TemplateUri)) 166 buf.WriteString(fmt.Sprintf("TemplateUriReadOnlySas: %s\n", a.TemplateUriReadOnlySas)) 167 if a.AdditionalDisks != nil { 168 for i, additionaldisk := range *a.AdditionalDisks { 169 buf.WriteString(fmt.Sprintf("AdditionalDiskUri (datadisk-%d): %s\n", i+1, additionaldisk.AdditionalDiskUri)) 170 buf.WriteString(fmt.Sprintf("AdditionalDiskUriReadOnlySas (datadisk-%d): %s\n", i+1, additionaldisk.AdditionalDiskUriReadOnlySas)) 171 } 172 } 173 } 174 175 return buf.String() 176 } 177 178 func (*Artifact) Destroy() error { 179 return nil 180 } 181 182 func (a *Artifact) stateAtlasMetadata() interface{} { 183 metadata := make(map[string]string) 184 metadata["StorageAccountLocation"] = a.StorageAccountLocation 185 metadata["OSDiskUri"] = a.OSDiskUri 186 metadata["OSDiskUriReadOnlySas"] = a.OSDiskUriReadOnlySas 187 metadata["TemplateUri"] = a.TemplateUri 188 metadata["TemplateUriReadOnlySas"] = a.TemplateUriReadOnlySas 189 190 return metadata 191 }