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  }