github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/plugins/juju-metadata/validateimagemetadata_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package main
     5  
     6  import (
     7  	"strings"
     8  
     9  	"github.com/juju/cmd"
    10  	"github.com/juju/cmd/cmdtesting"
    11  	jc "github.com/juju/testing/checkers"
    12  	"github.com/juju/utils"
    13  	"gopkg.in/amz.v3/aws"
    14  	gc "gopkg.in/check.v1"
    15  
    16  	"github.com/juju/juju/cloud"
    17  	"github.com/juju/juju/cmd/modelcmd"
    18  	"github.com/juju/juju/core/model"
    19  	"github.com/juju/juju/environs/config"
    20  	"github.com/juju/juju/environs/filestorage"
    21  	"github.com/juju/juju/environs/imagemetadata"
    22  	"github.com/juju/juju/environs/simplestreams"
    23  	"github.com/juju/juju/jujuclient"
    24  	"github.com/juju/juju/jujuclient/jujuclienttesting"
    25  	coretesting "github.com/juju/juju/testing"
    26  )
    27  
    28  type ValidateImageMetadataSuite struct {
    29  	coretesting.FakeJujuXDGDataHomeSuite
    30  	metadataDir string
    31  	store       *jujuclient.MemStore
    32  }
    33  
    34  var _ = gc.Suite(&ValidateImageMetadataSuite{})
    35  
    36  func runValidateImageMetadata(c *gc.C, store jujuclient.ClientStore, args ...string) (*cmd.Context, error) {
    37  	cmd := &validateImageMetadataCommand{}
    38  	cmd.SetClientStore(store)
    39  	return cmdtesting.RunCommand(c, modelcmd.WrapController(cmd), args...)
    40  }
    41  
    42  var validateInitImageErrorTests = []struct {
    43  	args []string
    44  	err  string
    45  }{
    46  	{
    47  		args: []string{"-p", "ec2", "-r", "region", "-d", "dir"},
    48  		err:  `series required if provider type is specified`,
    49  	}, {
    50  		args: []string{"-p", "ec2", "-s", "series", "-d", "dir"},
    51  		err:  `region required if provider type is specified`,
    52  	}, {
    53  		args: []string{"-p", "ec2", "-s", "series", "-r", "region"},
    54  		err:  `metadata directory required if provider type is specified`,
    55  	},
    56  }
    57  
    58  func (s *ValidateImageMetadataSuite) TestInitErrors(c *gc.C) {
    59  	for i, t := range validateInitImageErrorTests {
    60  		c.Logf("test %d", i)
    61  		cmd := &validateImageMetadataCommand{}
    62  		cmd.SetClientStore(jujuclienttesting.MinimalStore())
    63  		err := cmdtesting.InitCommand(modelcmd.WrapController(cmd), t.args)
    64  		c.Check(err, gc.ErrorMatches, t.err)
    65  	}
    66  }
    67  
    68  func (s *ValidateImageMetadataSuite) TestInvalidProviderError(c *gc.C) {
    69  	_, err := runValidateImageMetadata(c, s.store, "-p", "foo", "-s", "series", "-r", "region", "-d", "dir")
    70  	c.Check(err, gc.ErrorMatches, `no registered provider for "foo"`)
    71  }
    72  
    73  func (s *ValidateImageMetadataSuite) TestUnsupportedProviderError(c *gc.C) {
    74  	_, err := runValidateImageMetadata(c, s.store, "-p", "maas", "-s", "series", "-r", "region", "-d", "dir")
    75  	c.Check(err, gc.ErrorMatches, `maas provider does not support image metadata validation`)
    76  }
    77  
    78  func (s *ValidateImageMetadataSuite) makeLocalMetadata(c *gc.C, id, region, series, endpoint, stream string) error {
    79  	im := &imagemetadata.ImageMetadata{
    80  		Id:     id,
    81  		Arch:   "amd64",
    82  		Stream: stream,
    83  	}
    84  	cloudSpec := simplestreams.CloudSpec{
    85  		Region:   region,
    86  		Endpoint: endpoint,
    87  	}
    88  	targetStorage, err := filestorage.NewFileStorageWriter(s.metadataDir)
    89  	if err != nil {
    90  		return err
    91  	}
    92  	err = imagemetadata.MergeAndWriteMetadata(series, []*imagemetadata.ImageMetadata{im}, &cloudSpec, targetStorage)
    93  	if err != nil {
    94  		return err
    95  	}
    96  	return nil
    97  }
    98  
    99  func cacheTestEnvConfig(c *gc.C, store *jujuclient.MemStore) {
   100  	ec2UUID := utils.MustNewUUID().String()
   101  	ec2Config, err := config.New(config.UseDefaults, map[string]interface{}{
   102  		"name":            "ec2",
   103  		"type":            "ec2",
   104  		"default-series":  "precise",
   105  		"controller-uuid": coretesting.ControllerTag.Id(),
   106  		"uuid":            ec2UUID,
   107  	})
   108  	c.Assert(err, jc.ErrorIsNil)
   109  	store.Controllers["ec2-controller"] = jujuclient.ControllerDetails{
   110  		ControllerUUID: coretesting.ControllerTag.Id(),
   111  		CACert:         coretesting.CACert,
   112  	}
   113  	store.Controllers["ec2-controller-lts"] = jujuclient.ControllerDetails{
   114  		ControllerUUID: coretesting.ControllerTag.Id(),
   115  		CACert:         coretesting.CACert,
   116  	}
   117  	store.Models["ec2-controller"] = &jujuclient.ControllerModels{
   118  		Models: map[string]jujuclient.ModelDetails{
   119  			"admin/ec2": {
   120  				ModelType: model.IAAS,
   121  			},
   122  			"admin/ec2-latest-lts": {
   123  				ModelType: model.IAAS,
   124  			},
   125  		},
   126  		CurrentModel: "admin/controller",
   127  	}
   128  	store.Accounts["ec2-controller"] = jujuclient.AccountDetails{
   129  		User: "admin",
   130  	}
   131  	store.Accounts["ec2-controller-lts"] = jujuclient.AccountDetails{
   132  		User: "admin",
   133  	}
   134  
   135  	store.BootstrapConfig["ec2-controller"] = jujuclient.BootstrapConfig{
   136  		ControllerConfig:    coretesting.FakeControllerConfig(),
   137  		ControllerModelUUID: ec2UUID,
   138  		Config:              ec2Config.AllAttrs(),
   139  		Cloud:               "ec2",
   140  		CloudType:           "ec2",
   141  		CloudRegion:         "us-east-1",
   142  		CloudEndpoint:       "https://ec2.us-east-1.amazonaws.com",
   143  	}
   144  
   145  	azureUUID := utils.MustNewUUID().String()
   146  	azureConfig, err := config.New(config.UseDefaults, map[string]interface{}{
   147  		"name":            "azure",
   148  		"type":            "azure",
   149  		"controller-uuid": coretesting.ControllerTag.Id(),
   150  		"uuid":            azureUUID,
   151  		"default-series":  "raring",
   152  	})
   153  	c.Assert(err, jc.ErrorIsNil)
   154  	store.Controllers["azure-controller"] = jujuclient.ControllerDetails{
   155  		ControllerUUID: coretesting.ControllerTag.Id(),
   156  		CACert:         coretesting.CACert,
   157  	}
   158  	store.Models["azure-controller"] = &jujuclient.ControllerModels{
   159  		Models: map[string]jujuclient.ModelDetails{
   160  			"admin/azure": {
   161  				ModelType: model.IAAS,
   162  			},
   163  		},
   164  		CurrentModel: "admin/controller",
   165  	}
   166  	store.Accounts["azure-controller"] = jujuclient.AccountDetails{
   167  		User: "admin",
   168  	}
   169  	store.BootstrapConfig["azure-controller"] = jujuclient.BootstrapConfig{
   170  		ControllerConfig:     coretesting.FakeControllerConfig(),
   171  		ControllerModelUUID:  azureUUID,
   172  		Config:               azureConfig.AllAttrs(),
   173  		Cloud:                "azure",
   174  		CloudType:            "azure",
   175  		CloudRegion:          "West US",
   176  		CloudEndpoint:        "https://management.azure.com",
   177  		CloudStorageEndpoint: "https://core.windows.net",
   178  		Credential:           "default",
   179  	}
   180  	store.Credentials["azure"] = cloud.CloudCredential{
   181  		AuthCredentials: map[string]cloud.Credential{
   182  			"default": cloud.NewCredential(
   183  				"service-principal-secret",
   184  				map[string]string{
   185  					"application-id":       "application-id",
   186  					"subscription-id":      "subscription-id",
   187  					"application-password": "application-password",
   188  				},
   189  			),
   190  		},
   191  	}
   192  }
   193  
   194  func (s *ValidateImageMetadataSuite) SetUpTest(c *gc.C) {
   195  	s.FakeJujuXDGDataHomeSuite.SetUpTest(c)
   196  	s.metadataDir = c.MkDir()
   197  
   198  	s.store = jujuclienttesting.MinimalStore()
   199  	cacheTestEnvConfig(c, s.store)
   200  
   201  	s.PatchEnvironment("AWS_ACCESS_KEY_ID", "access")
   202  	s.PatchEnvironment("AWS_SECRET_ACCESS_KEY", "secret")
   203  	// All of the following are recognized as fallbacks by goamz.
   204  	s.PatchEnvironment("AWS_ACCESS_KEY", "")
   205  	s.PatchEnvironment("AWS_SECRET_KEY", "")
   206  	s.PatchEnvironment("EC2_ACCESS_KEY", "")
   207  	s.PatchEnvironment("EC2_SECRET_KEY", "")
   208  }
   209  
   210  func (s *ValidateImageMetadataSuite) setupEc2LocalMetadata(c *gc.C, region, stream string) {
   211  	ec2Region, ok := aws.Regions[region]
   212  	if !ok {
   213  		c.Fatalf("unknown ec2 region %q", region)
   214  	}
   215  	endpoint := ec2Region.EC2Endpoint
   216  	s.makeLocalMetadata(c, "1234", region, "precise", endpoint, stream)
   217  }
   218  
   219  func (s *ValidateImageMetadataSuite) assertEc2LocalMetadataUsingEnvironment(c *gc.C, stream string) {
   220  	s.setupEc2LocalMetadata(c, "us-east-1", stream)
   221  	ctx, err := runValidateImageMetadata(c, s.store, "-c", "ec2-controller", "-d", s.metadataDir, "--stream", stream)
   222  	c.Assert(err, jc.ErrorIsNil)
   223  	stdout := cmdtesting.Stdout(ctx)
   224  	stderr := cmdtesting.Stderr(ctx)
   225  	strippedOut := strings.Replace(stdout, "\n", "", -1)
   226  	c.Check(strippedOut, gc.Matches,
   227  		`ImageIds:.*"1234".*Region:.*us-east-1.*Resolve Metadata:.*source: local metadata directory.*`,
   228  	)
   229  	c.Check(stderr, gc.Matches, "")
   230  }
   231  
   232  func (s *ValidateImageMetadataSuite) TestEc2LocalMetadataUsingEnvironment(c *gc.C) {
   233  	s.assertEc2LocalMetadataUsingEnvironment(c, "")
   234  	s.assertEc2LocalMetadataUsingEnvironment(c, imagemetadata.ReleasedStream)
   235  	s.assertEc2LocalMetadataUsingEnvironment(c, "daily")
   236  }
   237  
   238  func (s *ValidateImageMetadataSuite) TestEc2LocalMetadataUsingIncompleteEnvironment(c *gc.C) {
   239  	s.PatchEnvironment("AWS_ACCESS_KEY_ID", "")
   240  	s.PatchEnvironment("AWS_SECRET_ACCESS_KEY", "")
   241  	s.PatchEnvironment("EC2_ACCESS_KEY", "")
   242  	s.PatchEnvironment("EC2_SECRET_KEY", "")
   243  	s.setupEc2LocalMetadata(c, "us-east-1", "")
   244  	_, err := runValidateImageMetadata(c, s.store, "-c", "ec2-controller", "-d", s.metadataDir)
   245  	c.Assert(err, gc.ErrorMatches, `detecting credentials.*AWS_SECRET_ACCESS_KEY not found in environment`)
   246  }
   247  
   248  func (s *ValidateImageMetadataSuite) TestEc2LocalMetadataWithManualParams(c *gc.C) {
   249  	s.setupEc2LocalMetadata(c, "us-west-1", "")
   250  	ctx, err := runValidateImageMetadata(c, s.store,
   251  		"-p", "ec2", "-s", "precise", "-r", "us-west-1",
   252  		"-u", "https://ec2.us-west-1.amazonaws.com", "-d", s.metadataDir,
   253  	)
   254  	c.Assert(err, jc.ErrorIsNil)
   255  	errOut := cmdtesting.Stdout(ctx)
   256  	strippedOut := strings.Replace(errOut, "\n", "", -1)
   257  	c.Check(
   258  		strippedOut, gc.Matches,
   259  		`ImageIds:.*"1234".*Region:.*us-west-1.*Resolve Metadata:.*source: local metadata directory.*`)
   260  }
   261  
   262  func (s *ValidateImageMetadataSuite) TestEc2LocalMetadataNoMatch(c *gc.C) {
   263  	s.setupEc2LocalMetadata(c, "us-east-1", "")
   264  	_, err := runValidateImageMetadata(c, s.store,
   265  		"-p", "ec2", "-s", "raring", "-r", "us-west-1",
   266  		"-u", "https://ec2.us-west-1.amazonaws.com", "-d", s.metadataDir,
   267  	)
   268  	c.Check(err, gc.ErrorMatches, "(.|\n)*Resolve Metadata:(.|\n)*")
   269  	_, err = runValidateImageMetadata(c, s.store,
   270  		"-p", "ec2", "-s", "precise", "-r", "region",
   271  		"-u", "https://ec2.region.amazonaws.com", "-d", s.metadataDir,
   272  	)
   273  	c.Check(err, gc.ErrorMatches, `unknown region "region"`)
   274  }
   275  
   276  func (s *ValidateImageMetadataSuite) TestOpenstackLocalMetadataWithManualParams(c *gc.C) {
   277  	s.makeLocalMetadata(c, "1234", "region-2", "raring", "some-auth-url", "")
   278  	ctx, err := runValidateImageMetadata(c, s.store,
   279  		"-p", "openstack", "-s", "raring", "-r", "region-2",
   280  		"-u", "some-auth-url", "-d", s.metadataDir,
   281  	)
   282  	c.Assert(err, jc.ErrorIsNil)
   283  	errOut := cmdtesting.Stdout(ctx)
   284  	strippedOut := strings.Replace(errOut, "\n", "", -1)
   285  	c.Check(
   286  		strippedOut, gc.Matches,
   287  		`ImageIds:.*"1234".*Region:.*region-2.*Resolve Metadata:.*source: local metadata directory.*`)
   288  }
   289  
   290  func (s *ValidateImageMetadataSuite) TestOpenstackLocalMetadataNoMatch(c *gc.C) {
   291  	s.makeLocalMetadata(c, "1234", "region-2", "raring", "some-auth-url", "")
   292  	_, err := runValidateImageMetadata(c, s.store,
   293  		"-p", "openstack", "-s", "precise", "-r", "region-2",
   294  		"-u", "some-auth-url", "-d", s.metadataDir,
   295  	)
   296  	c.Check(err, gc.ErrorMatches, "(.|\n)*Resolve Metadata:(.|\n)*")
   297  	_, err = runValidateImageMetadata(c, s.store,
   298  		"-p", "openstack", "-s", "raring", "-r", "region-3",
   299  		"-u", "some-auth-url", "-d", s.metadataDir,
   300  	)
   301  	c.Check(err, gc.ErrorMatches, "(.|\n)*Resolve Metadata:(.|\n)*")
   302  }
   303  
   304  func (s *ValidateImageMetadataSuite) TestImagesDataSourceHasKey(c *gc.C) {
   305  	ds := imagesDataSources("test.me")
   306  	// This data source does not require to contain signed data.
   307  	// However, it may still contain it.
   308  	// Since we will always try to read signed data first,
   309  	// we want to be able to try to read this signed data
   310  	// with a user provided public key. For this test, none is provided.
   311  	// Bugs #1542127, #1542131
   312  	c.Assert(ds[0].PublicSigningKey(), gc.Equals, "")
   313  }