launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/environs/tools/boilerplate.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package tools
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"io/ioutil"
    10  	"os"
    11  	"path/filepath"
    12  	"text/template"
    13  	"time"
    14  
    15  	"launchpad.net/juju-core/environs/simplestreams"
    16  	"launchpad.net/juju-core/juju/osenv"
    17  )
    18  
    19  const (
    20  	defaultIndexFileName = "index.json"
    21  	defaultToolsFileName = "toolsmetadata.json"
    22  	streamsDir           = "streams/v1"
    23  )
    24  
    25  // Boilerplate generates some basic simplestreams metadata using the specified cloud and tools details.
    26  func Boilerplate(tm *ToolsMetadata, cloudSpec *simplestreams.CloudSpec) ([]string, error) {
    27  	return MakeBoilerplate(tm, cloudSpec, true)
    28  }
    29  
    30  // MakeBoilerplate exists so it can be called by tests. See Boilerplate above. It provides an option to retain
    31  // the streams directories when writing the generated metadata files.
    32  func MakeBoilerplate(tm *ToolsMetadata, cloudSpec *simplestreams.CloudSpec, flattenPath bool) ([]string, error) {
    33  	indexFileName := defaultIndexFileName
    34  	toolsFileName := defaultToolsFileName
    35  	now := time.Now()
    36  	imparams := toolsMetadataParams{
    37  		ToolsBinarySize:   tm.Size,
    38  		ToolsBinaryPath:   tm.Path,
    39  		ToolsBinarySHA256: tm.SHA256,
    40  		Version:           tm.Version,
    41  		Arch:              tm.Arch,
    42  		Series:            tm.Release,
    43  		Region:            cloudSpec.Region,
    44  		URL:               cloudSpec.Endpoint,
    45  		Path:              streamsDir,
    46  		ToolsFileName:     toolsFileName,
    47  		Updated:           now.Format(time.RFC1123Z),
    48  		VersionKey:        now.Format("20060102"),
    49  	}
    50  
    51  	var err error
    52  	imparams.SeriesVersion, err = simplestreams.SeriesVersion(tm.Release)
    53  	if err != nil {
    54  		return nil, fmt.Errorf("invalid series %q", tm.Release)
    55  	}
    56  
    57  	if !flattenPath {
    58  		streamsPath := osenv.JujuHomePath(streamsDir)
    59  		if err := os.MkdirAll(streamsPath, 0755); err != nil {
    60  			return nil, err
    61  		}
    62  		indexFileName = filepath.Join(streamsDir, indexFileName)
    63  		toolsFileName = filepath.Join(streamsDir, toolsFileName)
    64  	}
    65  	err = writeJsonFile(imparams, indexFileName, indexBoilerplate)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  	err = writeJsonFile(imparams, toolsFileName, productBoilerplate)
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  	return []string{indexFileName, toolsFileName}, nil
    74  }
    75  
    76  type toolsMetadataParams struct {
    77  	ToolsBinaryPath   string
    78  	ToolsBinarySize   int64
    79  	ToolsBinarySHA256 string
    80  	Region            string
    81  	URL               string
    82  	Updated           string
    83  	Arch              string
    84  	Path              string
    85  	Series            string
    86  	SeriesVersion     string
    87  	Version           string
    88  	VersionKey        string
    89  	ToolsFileName     string
    90  }
    91  
    92  func writeJsonFile(imparams toolsMetadataParams, filename, boilerplate string) error {
    93  	t := template.Must(template.New("").Parse(boilerplate))
    94  	var metadata bytes.Buffer
    95  	if err := t.Execute(&metadata, imparams); err != nil {
    96  		panic(fmt.Errorf("cannot generate %s metdata: %v", filename, err))
    97  	}
    98  	data := metadata.Bytes()
    99  	path := osenv.JujuHomePath(filename)
   100  	if err := ioutil.WriteFile(path, data, 0666); err != nil {
   101  		return err
   102  	}
   103  	return nil
   104  }
   105  
   106  var indexBoilerplate = `
   107  {
   108   "index": {
   109     "com.ubuntu.juju:custom": {
   110       "updated": "{{.Updated}}",
   111       "cloudname": "custom",
   112       "datatype": "content-download",
   113       "format": "products:1.0",
   114       "products": [
   115         "com.ubuntu.juju:{{.SeriesVersion}}:{{.Arch}}"
   116       ],
   117       "path": "{{.Path}}/{{.ToolsFileName}}"
   118     }
   119   },
   120   "updated": "{{.Updated}}",
   121   "format": "index:1.0"
   122  }
   123  `
   124  
   125  var productBoilerplate = `
   126  {
   127    "content_id": "com.ubuntu.juju:custom",
   128    "format": "products:1.0",
   129    "updated": "{{.Updated}}",
   130    "datatype": "content-download",
   131    "products": {
   132      "com.ubuntu.juju:{{.SeriesVersion}}:{{.Arch}}": {
   133        "release": "{{.Series}}",
   134        "arch": "{{.Arch}}",
   135        "versions": {
   136          "{{.VersionKey}}": {
   137            "items": {
   138              "{{.Series}}{{.Version}}": {
   139                "version": "{{.Version}}",
   140                "size": {{.ToolsBinarySize}},
   141                "path": "{{.ToolsBinaryPath}}",
   142                "ftype": "tar.gz",
   143                "sha256": "{{.ToolsBinarySHA256}}"
   144              }
   145            },
   146            "pubname": "juju-{{.Series}}-{{.Arch}}-{{.VersionKey}}",
   147            "label": "custom"
   148          }
   149        }
   150      }
   151    }
   152  }
   153  `