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

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package cloudinit_test
     5  
     6  import (
     7  	"regexp"
     8  
     9  	"github.com/juju/packaging"
    10  	jc "github.com/juju/testing/checkers"
    11  	"github.com/juju/version"
    12  	gc "gopkg.in/check.v1"
    13  
    14  	"github.com/juju/juju/api"
    15  	"github.com/juju/juju/apiserver/params"
    16  	"github.com/juju/juju/cloudconfig"
    17  	"github.com/juju/juju/cloudconfig/cloudinit"
    18  	"github.com/juju/juju/cloudconfig/instancecfg"
    19  	"github.com/juju/juju/core/constraints"
    20  	"github.com/juju/juju/environs"
    21  	"github.com/juju/juju/environs/config"
    22  	"github.com/juju/juju/environs/imagemetadata"
    23  	"github.com/juju/juju/mongo"
    24  	"github.com/juju/juju/state/multiwatcher"
    25  	coretesting "github.com/juju/juju/testing"
    26  	"github.com/juju/juju/tools"
    27  )
    28  
    29  type configureSuite struct {
    30  	coretesting.BaseSuite
    31  }
    32  
    33  var _ = gc.Suite(&configureSuite{})
    34  
    35  type testProvider struct {
    36  	environs.CloudEnvironProvider
    37  }
    38  
    39  func init() {
    40  	environs.RegisterProvider("sshinit_test", &testProvider{})
    41  }
    42  
    43  func testConfig(c *gc.C, controller bool, vers version.Binary) *config.Config {
    44  	testConfig, err := config.New(config.UseDefaults, coretesting.FakeConfig())
    45  	c.Assert(err, jc.ErrorIsNil)
    46  	testConfig, err = testConfig.Apply(map[string]interface{}{
    47  		"type":           "sshinit_test",
    48  		"default-series": vers.Series,
    49  		"agent-version":  vers.Number.String(),
    50  	})
    51  	c.Assert(err, jc.ErrorIsNil)
    52  	return testConfig
    53  }
    54  
    55  func (s *configureSuite) getCloudConfig(c *gc.C, controller bool, vers version.Binary) cloudinit.CloudConfig {
    56  	var icfg *instancecfg.InstanceConfig
    57  	var err error
    58  	modelConfig := testConfig(c, controller, vers)
    59  	if controller {
    60  		icfg, err = instancecfg.NewBootstrapInstanceConfig(
    61  			coretesting.FakeControllerConfig(),
    62  			constraints.Value{}, constraints.Value{},
    63  			vers.Series, "",
    64  		)
    65  		c.Assert(err, jc.ErrorIsNil)
    66  		icfg.APIInfo = &api.Info{
    67  			Password: "password",
    68  			CACert:   coretesting.CACert,
    69  			ModelTag: coretesting.ModelTag,
    70  		}
    71  		icfg.Controller.MongoInfo = &mongo.MongoInfo{
    72  			Password: "password", Info: mongo.Info{CACert: coretesting.CACert},
    73  		}
    74  		icfg.Bootstrap.ControllerModelConfig = modelConfig
    75  		icfg.Bootstrap.BootstrapMachineInstanceId = "instance-id"
    76  		icfg.Bootstrap.HostedModelConfig = map[string]interface{}{
    77  			"name": "hosted-model",
    78  		}
    79  		icfg.Bootstrap.StateServingInfo = params.StateServingInfo{
    80  			Cert:         coretesting.ServerCert,
    81  			PrivateKey:   coretesting.ServerKey,
    82  			CAPrivateKey: coretesting.CAKey,
    83  			StatePort:    123,
    84  			APIPort:      456,
    85  		}
    86  		icfg.Jobs = []multiwatcher.MachineJob{multiwatcher.JobManageModel, multiwatcher.JobHostUnits}
    87  		icfg.Bootstrap.StateServingInfo = params.StateServingInfo{
    88  			Cert:         coretesting.ServerCert,
    89  			PrivateKey:   coretesting.ServerKey,
    90  			CAPrivateKey: coretesting.CAKey,
    91  			StatePort:    123,
    92  			APIPort:      456,
    93  		}
    94  	} else {
    95  		icfg, err = instancecfg.NewInstanceConfig(coretesting.ControllerTag, "0", "ya", imagemetadata.ReleasedStream, vers.Series, nil)
    96  		c.Assert(err, jc.ErrorIsNil)
    97  		icfg.Jobs = []multiwatcher.MachineJob{multiwatcher.JobHostUnits}
    98  	}
    99  	err = icfg.SetTools(tools.List{
   100  		&tools.Tools{
   101  			Version: vers,
   102  			URL:     "http://testing.invalid/tools.tar.gz",
   103  		},
   104  	})
   105  	err = instancecfg.FinishInstanceConfig(icfg, modelConfig)
   106  	c.Assert(err, jc.ErrorIsNil)
   107  	cloudcfg, err := cloudinit.New(icfg.Series)
   108  	c.Assert(err, jc.ErrorIsNil)
   109  	udata, err := cloudconfig.NewUserdataConfig(icfg, cloudcfg)
   110  	c.Assert(err, jc.ErrorIsNil)
   111  	err = udata.Configure()
   112  	c.Assert(err, jc.ErrorIsNil)
   113  	return cloudcfg
   114  }
   115  
   116  var allSeries = []string{"precise", "quantal", "raring", "saucy"}
   117  
   118  func checkIff(checker gc.Checker, condition bool) gc.Checker {
   119  	if condition {
   120  		return checker
   121  	}
   122  	return gc.Not(checker)
   123  }
   124  
   125  var aptgetRegexp = "(.|\n)*" + regexp.QuoteMeta("apt-get --option=Dpkg::Options::=--force-confold --option=Dpkg::options::=--force-unsafe-io --assume-yes --quiet ")
   126  
   127  func (s *configureSuite) TestAptSources(c *gc.C) {
   128  	for _, series := range allSeries {
   129  		vers := version.MustParseBinary("1.16.0-" + series + "-amd64")
   130  		script, err := s.getCloudConfig(c, true, vers).RenderScript()
   131  		c.Assert(err, jc.ErrorIsNil)
   132  
   133  		// Only Precise requires the cloud-tools pocket.
   134  		//
   135  		// The only source we add that requires an explicitly
   136  		// specified key is cloud-tools.
   137  		needsCloudTools := series == "precise"
   138  		c.Assert(
   139  			script,
   140  			checkIff(gc.Matches, needsCloudTools),
   141  			"(.|\n)*apt-key add.*(.|\n)*",
   142  		)
   143  		c.Assert(
   144  			script,
   145  			checkIff(gc.Matches, needsCloudTools),
   146  			"(.|\n)*add-apt-repository.*cloud-tools(.|\n)*",
   147  		)
   148  		c.Assert(
   149  			script,
   150  			checkIff(gc.Matches, needsCloudTools),
   151  			"(.|\n)*Pin: release n=precise-updates/cloud-tools\nPin-Priority: 400(.|\n)*",
   152  		)
   153  		c.Assert(
   154  			script,
   155  			checkIff(gc.Matches, needsCloudTools),
   156  			"(.|\n)*install -D -m 644 /dev/null '/etc/apt/preferences.d/50-cloud-tools'(.|\n)*",
   157  		)
   158  
   159  		// Only install software-properties-common (add-apt-repository)
   160  		// if we need to.
   161  		c.Assert(
   162  			script,
   163  			checkIff(gc.Matches, needsCloudTools),
   164  			aptgetRegexp+"install.*software-properties-common(.|\n)*",
   165  		)
   166  	}
   167  }
   168  
   169  func assertScriptMatches(c *gc.C, cfg cloudinit.CloudConfig, pattern string, match bool) {
   170  	script, err := cfg.RenderScript()
   171  	c.Assert(err, jc.ErrorIsNil)
   172  	checker := gc.Matches
   173  	if !match {
   174  		checker = gc.Not(checker)
   175  	}
   176  	c.Assert(script, checker, pattern)
   177  }
   178  
   179  func (s *configureSuite) TestAptUpdate(c *gc.C) {
   180  	// apt-get update is run only if AptUpdate is set.
   181  	aptGetUpdatePattern := aptgetRegexp + "update(.|\n)*"
   182  	cfg, err := cloudinit.New("quantal")
   183  	c.Assert(err, jc.ErrorIsNil)
   184  
   185  	c.Assert(cfg.SystemUpdate(), jc.IsFalse)
   186  	c.Assert(cfg.PackageSources(), gc.HasLen, 0)
   187  	assertScriptMatches(c, cfg, aptGetUpdatePattern, false)
   188  
   189  	cfg.SetSystemUpdate(true)
   190  	assertScriptMatches(c, cfg, aptGetUpdatePattern, true)
   191  
   192  	// If we add sources, but disable updates, display an error.
   193  	cfg.SetSystemUpdate(false)
   194  	source := packaging.PackageSource{
   195  		Name: "source",
   196  		URL:  "source",
   197  		Key:  "key",
   198  	}
   199  	cfg.AddPackageSource(source)
   200  	_, err = cfg.RenderScript()
   201  	c.Check(err, gc.ErrorMatches, "update sources were specified, but OS updates have been disabled.")
   202  }
   203  
   204  func (s *configureSuite) TestAptUpgrade(c *gc.C) {
   205  	// apt-get upgrade is only run if AptUpgrade is set.
   206  	aptGetUpgradePattern := aptgetRegexp + "upgrade(.|\n)*"
   207  	cfg, err := cloudinit.New("quantal")
   208  	c.Assert(err, jc.ErrorIsNil)
   209  	cfg.SetSystemUpdate(true)
   210  	source := packaging.PackageSource{
   211  		Name: "source",
   212  		URL:  "source",
   213  		Key:  "key",
   214  	}
   215  	cfg.AddPackageSource(source)
   216  	assertScriptMatches(c, cfg, aptGetUpgradePattern, false)
   217  	cfg.SetSystemUpgrade(true)
   218  	assertScriptMatches(c, cfg, aptGetUpgradePattern, true)
   219  }
   220  
   221  func (s *configureSuite) TestAptMirrorWrapper(c *gc.C) {
   222  	expectedCommands := regexp.QuoteMeta(`
   223  echo 'Changing apt mirror to http://woat.com' >&$JUJU_PROGRESS_FD
   224  old_mirror=$(awk "/^deb .* $(lsb_release -sc) .*main.*\$/{print \$2;exit}" /etc/apt/sources.list)
   225  new_mirror=http://woat.com
   226  sed -i s,$old_mirror,$new_mirror, /etc/apt/sources.list
   227  old_prefix=/var/lib/apt/lists/$(echo $old_mirror | sed 's,.*://,,' | sed 's,/$,,' | tr / _)
   228  new_prefix=/var/lib/apt/lists/$(echo $new_mirror | sed 's,.*://,,' | sed 's,/$,,' | tr / _)
   229  [ "$old_prefix" != "$new_prefix" ] &&
   230  for old in ${old_prefix}_*; do
   231      new=$(echo $old | sed s,^$old_prefix,$new_prefix,)
   232      mv $old $new
   233  done`)
   234  	aptMirrorRegexp := "(.|\n)*" + expectedCommands + "(.|\n)*"
   235  	cfg, err := cloudinit.New("quantal")
   236  	c.Assert(err, jc.ErrorIsNil)
   237  	cfg.SetPackageMirror("http://woat.com")
   238  	assertScriptMatches(c, cfg, aptMirrorRegexp, true)
   239  }