github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cloudconfig/machinecloudconfig_test.go (about)

     1  package cloudconfig_test
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"path"
     7  
     8  	"github.com/juju/errors"
     9  	"github.com/juju/loggo"
    10  	utilsseries "github.com/juju/os/series"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	"github.com/juju/juju/cloudconfig"
    14  	"github.com/juju/juju/testing"
    15  )
    16  
    17  type fromHostSuite struct {
    18  	testing.BaseSuite
    19  
    20  	tempCloudCfgDir  string
    21  	tempCloudInitDir string
    22  }
    23  
    24  var _ = gc.Suite(&fromHostSuite{})
    25  
    26  func (s *fromHostSuite) SetUpSuite(c *gc.C) {
    27  	s.BaseSuite.SetUpSuite(c)
    28  
    29  	// Pre-seed /etc/cloud/cloud.cfg.d replacement for testing
    30  	s.tempCloudCfgDir = c.MkDir() // will clean up
    31  	ioutil.WriteFile(path.Join(s.tempCloudCfgDir, "90_dpkg_local_cloud_config.cfg"), []byte(dpkgLocalCloudConfig078), 0644)
    32  	ioutil.WriteFile(path.Join(s.tempCloudCfgDir, "50-curtin-networking.cfg"), []byte(curtinNetworking), 0644)
    33  	ioutil.WriteFile(path.Join(s.tempCloudCfgDir, "10_random.cfg"), []byte(otherConfig), 0644)
    34  	ioutil.WriteFile(path.Join(s.tempCloudCfgDir, "Readme"), []byte(readmeFile), 0644)
    35  
    36  	// Pre-seed /var/lib/cloud/instance replacement for testing
    37  	s.tempCloudInitDir = c.MkDir()
    38  	ioutil.WriteFile(path.Join(s.tempCloudInitDir, "vendor-data.txt"), []byte(vendorData), 0644)
    39  }
    40  
    41  func (s *fromHostSuite) SetUpTest(c *gc.C) {
    42  	s.PatchValue(&cloudconfig.CloudInitCfgDir, func(_ string) (string, error) { return s.tempCloudCfgDir, nil })
    43  	s.PatchValue(&cloudconfig.MachineCloudInitDir, func(string) (string, error) { return s.tempCloudInitDir, nil })
    44  	s.PatchValue(&utilsseries.MustHostSeries, func() string { return "xenial" })
    45  }
    46  
    47  func (s *fromHostSuite) TestGetMachineCloudInitData(c *gc.C) {
    48  	obtained, err := cloudconfig.GetMachineCloudInitData("xenial")
    49  	c.Assert(err, gc.IsNil)
    50  	c.Assert(obtained, gc.DeepEquals, expectedResult078)
    51  }
    52  
    53  type cloudinitDataVerifyTest struct {
    54  	description     string
    55  	machineSeries   string
    56  	containerSeries string
    57  	err             string
    58  	result          map[string]interface{}
    59  }
    60  
    61  var cloudinitDataVerifyTests = []cloudinitDataVerifyTest{
    62  	{
    63  		description:     "xenial on xenial",
    64  		machineSeries:   "xenial",
    65  		containerSeries: "xenial",
    66  		result:          expectedResult078,
    67  	},
    68  	{
    69  		description:     "trusty on trusty",
    70  		machineSeries:   "trusty",
    71  		containerSeries: "trusty",
    72  		result:          expectedResult078,
    73  	},
    74  	{
    75  		description:     "xenial on trusty",
    76  		machineSeries:   "trusty",
    77  		containerSeries: "xenial",
    78  	},
    79  	{
    80  		description:     "opensuseleap on opensuseleap",
    81  		machineSeries:   "opensuseleap",
    82  		containerSeries: "opensuseleap",
    83  		result:          expectedResult078,
    84  	},
    85  	{
    86  		description:     "centos7 on centos7",
    87  		machineSeries:   "centos7",
    88  		containerSeries: "centos7",
    89  		result:          expectedResult078,
    90  	},
    91  	{
    92  		description:     "win2012 on win2012",
    93  		machineSeries:   "win2012",
    94  		containerSeries: "win2012",
    95  	},
    96  	{
    97  		description:     "highsierra on highsierra",
    98  		machineSeries:   "highsierra",
    99  		containerSeries: "highsierra",
   100  	},
   101  }
   102  
   103  func (s *fromHostSuite) TestGetMachineCloudInitDataVerifySeries(c *gc.C) {
   104  	for i, test := range cloudinitDataVerifyTests {
   105  		c.Logf("Test %d of %d: %s", i, len(cloudinitDataVerifyTests), test.description)
   106  		s.PatchValue(&utilsseries.MustHostSeries, func() string { return test.machineSeries })
   107  		obtained, err := cloudconfig.GetMachineCloudInitData(test.containerSeries)
   108  		c.Assert(err, gc.IsNil)
   109  		if test.result != nil {
   110  			c.Assert(obtained, gc.DeepEquals, expectedResult078)
   111  		} else {
   112  			c.Assert(obtained, gc.IsNil)
   113  		}
   114  	}
   115  }
   116  
   117  func (s *fromHostSuite) TestMissingVendorDataFile(c *gc.C) {
   118  	dir := c.MkDir()
   119  	s.PatchValue(&cloudconfig.MachineCloudInitDir, func(string) (string, error) { return dir, nil })
   120  	obtained, err := cloudconfig.GetMachineData("xenial", "vendor-data.txt")
   121  	c.Assert(err, gc.ErrorMatches, "cannot read \"vendor-data.txt\" from machine.*")
   122  	c.Assert(obtained, gc.IsNil)
   123  }
   124  
   125  func (s *fromHostSuite) TestMissingVendorDataFileTrusty(c *gc.C) {
   126  	ioutil.WriteFile(path.Join(s.tempCloudInitDir, "vendor-data.txt"), []byte(vendorDataTrusty), 0644)
   127  	obtained, err := cloudconfig.GetMachineData("trusty", "vendor-data.txt")
   128  	c.Assert(err, gc.IsNil)
   129  	c.Assert(obtained, gc.IsNil)
   130  }
   131  
   132  func (s *fromHostSuite) TestGetMachineCloudCfgDirDataReadDirFailed(c *gc.C) {
   133  	dir := c.MkDir()
   134  	os.RemoveAll(dir)
   135  	s.PatchValue(&cloudconfig.CloudInitCfgDir, func(string) (string, error) { return dir, nil })
   136  	obtained, err := cloudconfig.GetMachineCloudCfgDirData("xenial")
   137  	c.Assert(err, gc.ErrorMatches, "cannot determine files in CloudInitCfgDir for the machine: .* no such file or directory")
   138  	c.Assert(obtained, gc.IsNil)
   139  }
   140  
   141  func (s *fromHostSuite) TestGetMachineCloudCfgDirDataReadDirNotFound(c *gc.C) {
   142  	s.PatchValue(&cloudconfig.CloudInitCfgDir, func(string) (string, error) { return "", errors.New("test failure") })
   143  	obtained, err := cloudconfig.GetMachineCloudCfgDirData("xenial")
   144  	c.Assert(err, gc.ErrorMatches, "cannot determine CloudInitCfgDir for the machine: test failure")
   145  	c.Assert(obtained, gc.IsNil)
   146  }
   147  
   148  func (s *fromHostSuite) TestGetMachineDataReadDirNotFound(c *gc.C) {
   149  	s.PatchValue(&cloudconfig.MachineCloudInitDir, func(string) (string, error) { return "", errors.New("test failure") })
   150  	obtained, err := cloudconfig.GetMachineData("xenial", "")
   151  	c.Assert(err, gc.ErrorMatches, "cannot determine MachineCloudInitDir for the machine: test failure")
   152  	c.Assert(obtained, gc.IsNil)
   153  }
   154  
   155  func (s *fromHostSuite) TestCloudConfigVersionV078(c *gc.C) {
   156  	obtained, err := cloudconfig.GetMachineCloudInitData("xenial")
   157  	c.Assert(err, gc.IsNil)
   158  	c.Assert(obtained, gc.DeepEquals, expectedResult078)
   159  
   160  	resultMap := cloudconfig.CloudConfigByVersionFunc("xenial")("apt-primary,ca-certs,apt-security", obtained,
   161  		loggo.GetLogger("juju.machinecloudconfig"))
   162  	c.Assert(resultMap, gc.DeepEquals,
   163  		map[string]interface{}{
   164  			"apt": map[string]interface{}{
   165  				"primary": []interface{}{
   166  					map[interface{}]interface{}{
   167  						"arches": []interface{}{"default"},
   168  						"uri":    "http://archive.ubuntu.com/ubuntu",
   169  					},
   170  				},
   171  				"security": []interface{}{
   172  					map[interface{}]interface{}{
   173  						"arches": []interface{}{"default"},
   174  						"uri":    "http://archive.ubuntu.com/ubuntu",
   175  					},
   176  				},
   177  			},
   178  			"ca-certs": map[interface{}]interface{}{
   179  				"remove-defaults": true,
   180  				"trusted":         []interface{}{"-----BEGIN CERTIFICATE-----\nYOUR-ORGS-TRUSTED-CA-CERT-HERE\n-----END CERTIFICATE-----\n"},
   181  			},
   182  		})
   183  }
   184  
   185  func (s *fromHostSuite) TestCloudConfigVersionNoContainerInheritPropertiesV078(c *gc.C) {
   186  	resultMap := cloudconfig.CloudConfigByVersionFunc("xenial")("", nil, loggo.GetLogger("juju.machinecloudconfig"))
   187  	c.Assert(resultMap, gc.IsNil)
   188  }
   189  
   190  func (s *fromHostSuite) TestCloudConfigVersionV077(c *gc.C) {
   191  	s.PatchValue(&utilsseries.MustHostSeries, func() string { return "trusty" })
   192  	obtained, err := cloudconfig.GetMachineCloudInitData("trusty")
   193  	c.Assert(err, gc.IsNil)
   194  	c.Assert(obtained, gc.DeepEquals, expectedResult078)
   195  
   196  	resultMap := cloudconfig.CloudConfigByVersionFunc("xenial")("apt-primary,ca-certs,apt-security", obtained,
   197  		loggo.GetLogger("juju.machinecloudconfig"))
   198  	c.Assert(resultMap, gc.DeepEquals,
   199  		map[string]interface{}{
   200  			"apt": map[string]interface{}{
   201  				"primary": []interface{}{
   202  					map[interface{}]interface{}{
   203  						"arches": []interface{}{"default"},
   204  						"uri":    "http://archive.ubuntu.com/ubuntu",
   205  					},
   206  				},
   207  				"security": []interface{}{
   208  					map[interface{}]interface{}{
   209  						"arches": []interface{}{"default"},
   210  						"uri":    "http://archive.ubuntu.com/ubuntu",
   211  					},
   212  				},
   213  			},
   214  			"ca-certs": map[interface{}]interface{}{
   215  				"remove-defaults": true,
   216  				"trusted":         []interface{}{"-----BEGIN CERTIFICATE-----\nYOUR-ORGS-TRUSTED-CA-CERT-HERE\n-----END CERTIFICATE-----\n"},
   217  			},
   218  		})
   219  }
   220  
   221  func (s *fromHostSuite) TestCloudConfigVersionNoContainerInheritPropertiesV077(c *gc.C) {
   222  	resultMap := cloudconfig.CloudConfigByVersionFunc("trusty")("", nil, loggo.GetLogger("juju.machinecloudconfig"))
   223  	c.Assert(resultMap, gc.IsNil)
   224  }
   225  
   226  var dpkgLocalCloudConfig077 = `
   227  # cloud-init/local-cloud-config
   228  apt_mirror: http://archive.ubuntu.com/ubuntu
   229  apt_mirror_search:
   230   - http://local-mirror.mydomain
   231   - http://archive.ubuntu.com
   232  apt_mirror_search_dns: False
   233  apt_sources:
   234   - source: "deb http://apt.opscode.com/ $RELEASE-0.10 main"
   235     key: |
   236       -----BEGIN PGP PUBLIC KEY BLOCK-----
   237       Version: GnuPG v1.4.9 (GNU/Linux)
   238       -----END PGP PUBLIC KEY BLOCK-----
   239  apt_preserve_sources_list: true
   240  reporting:
   241    maas: {consumer_key: mpU9YZLWDG7ZQubksN, endpoint: 'http://10.10.101.2/MAAS/metadata/status/cmfcxx',
   242      token_key: tgEn5v5TcakKwWKwCf, token_secret: jzLdPTuh7hHqHTG9kGEHSG7F25GMAmzJ,
   243      type: webhook}
   244  system_info:
   245    package_mirrors:
   246    - arches: [i386, amd64]
   247      failsafe: {primary: 'http://archive.ubuntu.com/ubuntu', security: 'http://security.ubuntu.com/ubuntu'}
   248      search:
   249        primary: ['http://archive.ubuntu.com/ubuntu']
   250        security: ['http://archive.ubuntu.com/ubuntu']
   251    - arches: [default]
   252      failsafe: {primary: 'http://ports.ubuntu.com/ubuntu-ports', security: 'http://ports.ubuntu.com/ubuntu-ports'}
   253      search:
   254        primary: ['http://ports.ubuntu.com/ubuntu-ports']
   255        security: ['http://ports.ubuntu.com/ubuntu-ports']
   256  `[1:]
   257  
   258  var dpkgLocalCloudConfig078 = `
   259  # cloud-init/local-cloud-config
   260  apt:
   261    preserve_sources_list: false
   262    primary:
   263    - arches: [default]
   264      uri: http://archive.ubuntu.com/ubuntu
   265    security:
   266    - arches: [default]
   267      uri: http://archive.ubuntu.com/ubuntu
   268  apt_preserve_sources_list: true
   269  reporting:
   270    maas: {consumer_key: mpU9YZLWDG7ZQubksN, endpoint: 'http://10.10.101.2/MAAS/metadata/status/cmfcxx',
   271      token_key: tgEn5v5TcakKwWKwCf, token_secret: jzLdPTuh7hHqHTG9kGEHSG7F25GMAmzJ,
   272      type: webhook}
   273  system_info:
   274    package_mirrors:
   275    - arches: [i386, amd64]
   276      failsafe: {primary: 'http://archive.ubuntu.com/ubuntu', security: 'http://security.ubuntu.com/ubuntu'}
   277      search:
   278        primary: ['http://archive.ubuntu.com/ubuntu']
   279        security: ['http://archive.ubuntu.com/ubuntu']
   280    - arches: [default]
   281      failsafe: {primary: 'http://ports.ubuntu.com/ubuntu-ports', security: 'http://ports.ubuntu.com/ubuntu-ports'}
   282      search:
   283        primary: ['http://ports.ubuntu.com/ubuntu-ports']
   284        security: ['http://ports.ubuntu.com/ubuntu-ports']
   285  `[1:]
   286  
   287  var curtinNetworking = `
   288  network:
   289    config:
   290    - id: ens3
   291      mac_address: 52:54:00:0c:xx:e0
   292      mtu: 1500
   293      name: ens3
   294      subnets:
   295      - address: 10.10.76.124/24
   296        dns_nameservers:
   297        - 10.10.76.45
   298        gateway: 10.10.76.1
   299        type: static
   300      type: physical
   301  `[1:]
   302  
   303  var otherConfig = `
   304  #cloud-config
   305  packages:
   306    - ‘python-novaclient’
   307  write_files:
   308    - path: /tmp/juju-test
   309      permissions: 0644
   310      content: |
   311        Hello World!
   312  apt_preserve_sources_list: false
   313  ca-certs:
   314    remove-defaults: true
   315    trusted:
   316    - |
   317     -----BEGIN CERTIFICATE-----
   318     YOUR-ORGS-TRUSTED-CA-CERT-HERE
   319     -----END CERTIFICATE-----
   320  `[1:]
   321  
   322  var vendorData = `
   323  #cloud-config
   324  ntp:
   325    pools: []
   326    servers: [10.10.76.2]
   327  `[1:]
   328  
   329  var vendorDataTrusty = `
   330  None
   331  `[1:]
   332  
   333  var readmeFile = `
   334  # All files in this directory will be read by cloud-init
   335  # They are read in lexical order.  Later files overwrite values in
   336  # earlier files.
   337  `[1:]
   338  
   339  var expectedResult078 = map[string]interface{}{
   340  	"apt": map[interface{}]interface{}{
   341  		"preserve_sources_list": false,
   342  		"primary": []interface{}{
   343  			map[interface{}]interface{}{
   344  				"arches": []interface{}{"default"},
   345  				"uri":    "http://archive.ubuntu.com/ubuntu",
   346  			},
   347  		},
   348  		"security": []interface{}{
   349  			map[interface{}]interface{}{
   350  				"arches": []interface{}{"default"},
   351  				"uri":    "http://archive.ubuntu.com/ubuntu",
   352  			},
   353  		},
   354  	},
   355  	"reporting": map[interface{}]interface{}{
   356  		"maas": map[interface{}]interface{}{
   357  			"endpoint":     "http://10.10.101.2/MAAS/metadata/status/cmfcxx",
   358  			"token_key":    "tgEn5v5TcakKwWKwCf",
   359  			"token_secret": "jzLdPTuh7hHqHTG9kGEHSG7F25GMAmzJ",
   360  			"type":         "webhook",
   361  			"consumer_key": "mpU9YZLWDG7ZQubksN",
   362  		},
   363  	},
   364  	"system_info": map[interface{}]interface{}{
   365  		"package_mirrors": []interface{}{map[interface{}]interface{}{
   366  			"arches": []interface{}{"i386", "amd64"},
   367  			"failsafe": map[interface{}]interface{}{
   368  				"primary":  "http://archive.ubuntu.com/ubuntu",
   369  				"security": "http://security.ubuntu.com/ubuntu",
   370  			},
   371  			"search": map[interface{}]interface{}{
   372  				"primary":  []interface{}{"http://archive.ubuntu.com/ubuntu"},
   373  				"security": []interface{}{"http://archive.ubuntu.com/ubuntu"},
   374  			},
   375  		},
   376  			map[interface{}]interface{}{
   377  				"arches": []interface{}{"default"},
   378  				"failsafe": map[interface{}]interface{}{
   379  					"primary":  "http://ports.ubuntu.com/ubuntu-ports",
   380  					"security": "http://ports.ubuntu.com/ubuntu-ports",
   381  				},
   382  				"search": map[interface{}]interface{}{
   383  					"primary":  []interface{}{"http://ports.ubuntu.com/ubuntu-ports"},
   384  					"security": []interface{}{"http://ports.ubuntu.com/ubuntu-ports"},
   385  				},
   386  			},
   387  		},
   388  	},
   389  	"ntp": map[interface{}]interface{}{
   390  		"servers": []interface{}{"10.10.76.2"},
   391  		"pools":   []interface{}{},
   392  	},
   393  	"write_files": []interface{}{
   394  		map[interface{}]interface{}{
   395  			"path":        "/tmp/juju-test",
   396  			"permissions": 420,
   397  			"content":     "Hello World!\n",
   398  		}},
   399  	"apt_preserve_sources_list": true,
   400  	"packages":                  []interface{}{"‘python-novaclient’"},
   401  	"ca-certs": map[interface{}]interface{}{
   402  		"remove-defaults": true,
   403  		"trusted":         []interface{}{"-----BEGIN CERTIFICATE-----\nYOUR-ORGS-TRUSTED-CA-CERT-HERE\n-----END CERTIFICATE-----\n"},
   404  	},
   405  	"network": map[interface{}]interface{}{
   406  		"config": []interface{}{map[interface{}]interface{}{
   407  			"mtu":  1500,
   408  			"name": "ens3",
   409  			"subnets": []interface{}{
   410  				map[interface{}]interface{}{
   411  					"type":            "static",
   412  					"address":         "10.10.76.124/24",
   413  					"dns_nameservers": []interface{}{"10.10.76.45"},
   414  					"gateway":         "10.10.76.1",
   415  				},
   416  			},
   417  			"type":        "physical",
   418  			"id":          "ens3",
   419  			"mac_address": "52:54:00:0c:xx:e0"},
   420  		},
   421  	},
   422  }