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