launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/cmd/plugins/juju-metadata/validatetoolsmetadata.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package main 5 6 import ( 7 "fmt" 8 "os" 9 "strings" 10 11 "launchpad.net/gnuflag" 12 13 "launchpad.net/juju-core/cmd" 14 "launchpad.net/juju-core/environs" 15 "launchpad.net/juju-core/environs/configstore" 16 "launchpad.net/juju-core/environs/simplestreams" 17 "launchpad.net/juju-core/environs/tools" 18 "launchpad.net/juju-core/version" 19 ) 20 21 // ValidateToolsMetadataCommand 22 type ValidateToolsMetadataCommand struct { 23 cmd.EnvCommandBase 24 providerType string 25 metadataDir string 26 series string 27 region string 28 endpoint string 29 exactVersion string 30 partVersion string 31 major int 32 minor int 33 } 34 35 var validateToolsMetadataDoc = ` 36 validate-tools loads simplestreams metadata and validates the contents by 37 looking for tools belonging to the specified series, architecture, for the 38 specified cloud. If version is specified, tools matching the exact specified 39 version are found. It is also possible to just specify the major (and optionally 40 minor) version numbers to search for. 41 42 The cloud specification comes from the current Juju environment, as specified in 43 the usual way from either ~/.juju/environments.yaml, the -e option, or JUJU_ENV. 44 Series, Region, and Endpoint are the key attributes. 45 46 It is possible to specify a local directory containing tools metadata, in which 47 case cloud attributes like provider type, region etc are optional. 48 49 The key environment attributes may be overridden using command arguments, so 50 that the validation may be peformed on arbitary metadata. 51 52 Examples: 53 54 - validate using the current environment settings but with series raring 55 56 juju metadata validate-tools -s raring 57 58 - validate using the current environment settings but with Juju version 1.11.4 59 60 juju metadata validate-tools -j 1.11.4 61 62 - validate using the current environment settings but with Juju major version 2 63 64 juju metadata validate-tools -m 2 65 66 - validate using the current environment settings but with Juju major.minor version 2.1 67 68 juju metadata validate-tools -m 2.1 69 70 - validate using the current environment settings and list all tools found for any series 71 72 juju metadata validate-tools --series= 73 74 - validate with series raring and using metadata from local directory 75 76 juju metadata validate-images -s raring -d <some directory> 77 78 A key use case is to validate newly generated metadata prior to deployment to 79 production. In this case, the metadata is placed in a local directory, a cloud 80 provider type is specified (ec2, openstack etc), and the validation is performed 81 for each supported series, version, and arcgitecture. 82 83 Example bash snippet: 84 85 #!/bin/bash 86 87 juju metadata validate-tools -p ec2 -r us-east-1 -s precise --juju-version 1.12.0 -d <some directory> 88 RETVAL=$? 89 [ $RETVAL -eq 0 ] && echo Success 90 [ $RETVAL -ne 0 ] && echo Failure 91 ` 92 93 func (c *ValidateToolsMetadataCommand) Info() *cmd.Info { 94 return &cmd.Info{ 95 Name: "validate-tools", 96 Purpose: "validate tools metadata and ensure tools tarball(s) exist for Juju version(s)", 97 Doc: validateToolsMetadataDoc, 98 } 99 } 100 101 func (c *ValidateToolsMetadataCommand) SetFlags(f *gnuflag.FlagSet) { 102 c.EnvCommandBase.SetFlags(f) 103 f.StringVar(&c.providerType, "p", "", "the provider type eg ec2, openstack") 104 f.StringVar(&c.metadataDir, "d", "", "directory where metadata files are found") 105 f.StringVar(&c.series, "s", "", "the series for which to validate (overrides env config series)") 106 f.StringVar(&c.series, "series", "", "") 107 f.StringVar(&c.region, "r", "", "the region for which to validate (overrides env config region)") 108 f.StringVar(&c.endpoint, "u", "", "the cloud endpoint URL for which to validate (overrides env config endpoint)") 109 f.StringVar(&c.exactVersion, "j", "current", "the Juju version (use 'current' for current version)") 110 f.StringVar(&c.exactVersion, "juju-version", "", "") 111 f.StringVar(&c.partVersion, "m", "", "the Juju major[.minor] version") 112 f.StringVar(&c.partVersion, "majorminor-version", "", "") 113 } 114 115 func (c *ValidateToolsMetadataCommand) Init(args []string) error { 116 if c.providerType != "" { 117 if c.region == "" { 118 return fmt.Errorf("region required if provider type is specified") 119 } 120 if c.metadataDir == "" { 121 return fmt.Errorf("metadata directory required if provider type is specified") 122 } 123 } 124 if c.exactVersion == "current" { 125 c.exactVersion = version.Current.Number.String() 126 } 127 if c.partVersion != "" { 128 var err error 129 if c.major, c.minor, err = version.ParseMajorMinor(c.partVersion); err != nil { 130 return err 131 } 132 } 133 return c.EnvCommandBase.Init(args) 134 } 135 136 func (c *ValidateToolsMetadataCommand) Run(context *cmd.Context) error { 137 var params *simplestreams.MetadataLookupParams 138 139 if c.providerType == "" { 140 store, err := configstore.Default() 141 if err != nil { 142 return err 143 } 144 environ, err := environs.PrepareFromName(c.EnvName, store) 145 if err == nil { 146 mdLookup, ok := environ.(simplestreams.MetadataValidator) 147 if !ok { 148 return fmt.Errorf("%s provider does not support tools metadata validation", environ.Config().Type()) 149 } 150 params, err = mdLookup.MetadataLookupParams(c.region) 151 if err != nil { 152 return err 153 } 154 params.Sources, err = tools.GetMetadataSources(environ) 155 if err != nil { 156 return err 157 } 158 } else { 159 if c.metadataDir == "" { 160 return err 161 } 162 params = &simplestreams.MetadataLookupParams{ 163 Architectures: []string{"amd64", "arm", "i386"}, 164 } 165 } 166 } else { 167 prov, err := environs.Provider(c.providerType) 168 if err != nil { 169 return err 170 } 171 mdLookup, ok := prov.(simplestreams.MetadataValidator) 172 if !ok { 173 return fmt.Errorf("%s provider does not support tools metadata validation", c.providerType) 174 } 175 params, err = mdLookup.MetadataLookupParams(c.region) 176 if err != nil { 177 return err 178 } 179 } 180 181 if c.series != "" { 182 params.Series = c.series 183 } 184 if c.region != "" { 185 params.Region = c.region 186 } 187 if c.endpoint != "" { 188 params.Endpoint = c.endpoint 189 } 190 if c.metadataDir != "" { 191 if _, err := os.Stat(c.metadataDir); err != nil { 192 return err 193 } 194 params.Sources = []simplestreams.DataSource{simplestreams.NewURLDataSource("file://"+c.metadataDir, simplestreams.VerifySSLHostnames)} 195 } 196 197 versions, err := tools.ValidateToolsMetadata(&tools.ToolsMetadataLookupParams{ 198 MetadataLookupParams: *params, 199 Version: c.exactVersion, 200 Major: c.major, 201 Minor: c.minor, 202 }) 203 if err != nil { 204 return err 205 } 206 207 if len(versions) > 0 { 208 fmt.Fprintf(context.Stdout, "matching tools versions:\n%s\n", strings.Join(versions, "\n")) 209 } else { 210 var urls []string 211 for _, s := range params.Sources { 212 url, err := s.URL("") 213 if err != nil { 214 urls = append(urls, url) 215 } 216 } 217 return fmt.Errorf("no matching tools using URLs:\n%s", strings.Join(urls, "\n")) 218 } 219 return nil 220 }