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