github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/cloudconfig/containerinit/container_userdata_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Copyright 2015 Cloudbase Solutions SRL
     3  // Licensed under the AGPLv3, see LICENCE file for details.
     4  
     5  package containerinit_test
     6  
     7  import (
     8  	"path/filepath"
     9  	"strings"
    10  	stdtesting "testing"
    11  
    12  	jc "github.com/juju/testing/checkers"
    13  	gc "gopkg.in/check.v1"
    14  	"gopkg.in/yaml.v1"
    15  
    16  	"github.com/juju/juju/cloudconfig/cloudinit"
    17  	"github.com/juju/juju/cloudconfig/containerinit"
    18  	"github.com/juju/juju/container"
    19  	containertesting "github.com/juju/juju/container/testing"
    20  	"github.com/juju/juju/feature"
    21  	"github.com/juju/juju/network"
    22  	"github.com/juju/juju/service"
    23  	systemdtesting "github.com/juju/juju/service/systemd/testing"
    24  	"github.com/juju/juju/testing"
    25  )
    26  
    27  func Test(t *stdtesting.T) {
    28  	gc.TestingT(t)
    29  }
    30  
    31  type UserDataSuite struct {
    32  	testing.BaseSuite
    33  
    34  	networkInterfacesFile string
    35  	fakeInterfaces        []network.InterfaceInfo
    36  	expectedNetConfig     string
    37  }
    38  
    39  var _ = gc.Suite(&UserDataSuite{})
    40  
    41  func (s *UserDataSuite) SetUpTest(c *gc.C) {
    42  	s.BaseSuite.SetUpTest(c)
    43  	s.networkInterfacesFile = filepath.Join(c.MkDir(), "interfaces")
    44  	s.fakeInterfaces = []network.InterfaceInfo{{
    45  		InterfaceName:  "eth0",
    46  		CIDR:           "0.1.2.0/24",
    47  		ConfigType:     network.ConfigStatic,
    48  		NoAutoStart:    false,
    49  		Address:        network.NewAddress("0.1.2.3"),
    50  		DNSServers:     network.NewAddresses("ns1.invalid", "ns2.invalid"),
    51  		DNSSearch:      "foo.bar",
    52  		GatewayAddress: network.NewAddress("0.1.2.1"),
    53  	}, {
    54  		InterfaceName: "eth1",
    55  		ConfigType:    network.ConfigDHCP,
    56  		NoAutoStart:   true,
    57  	}}
    58  	s.expectedNetConfig = `
    59  # loopback interface
    60  auto lo
    61  iface lo inet loopback
    62  
    63  # interface "eth0"
    64  auto eth0
    65  iface eth0 inet manual
    66      dns-nameservers ns1.invalid ns2.invalid
    67      dns-search foo.bar
    68      pre-up ip address add 0.1.2.3/32 dev eth0 &> /dev/null || true
    69      up ip route replace 0.1.2.1 dev eth0
    70      up ip route replace default via 0.1.2.1
    71      down ip route del default via 0.1.2.1 &> /dev/null || true
    72      down ip route del 0.1.2.1 dev eth0 &> /dev/null || true
    73      post-down ip address del 0.1.2.3/32 dev eth0 &> /dev/null || true
    74  
    75  # interface "eth1"
    76  iface eth1 inet dhcp
    77  `
    78  	s.PatchValue(containerinit.NetworkInterfacesFile, s.networkInterfacesFile)
    79  }
    80  
    81  func (s *UserDataSuite) TestGenerateNetworkConfig(c *gc.C) {
    82  	// No config or no interfaces - no error, but also noting to generate.
    83  	data, err := containerinit.GenerateNetworkConfig(nil)
    84  	c.Assert(err, jc.ErrorIsNil)
    85  	c.Assert(data, gc.HasLen, 0)
    86  	netConfig := container.BridgeNetworkConfig("foo", 0, nil)
    87  	data, err = containerinit.GenerateNetworkConfig(netConfig)
    88  	c.Assert(err, jc.ErrorIsNil)
    89  	c.Assert(data, gc.HasLen, 0)
    90  
    91  	// Test with all interface types.
    92  	netConfig = container.BridgeNetworkConfig("foo", 0, s.fakeInterfaces)
    93  	data, err = containerinit.GenerateNetworkConfig(netConfig)
    94  	c.Assert(err, jc.ErrorIsNil)
    95  	c.Assert(data, gc.Equals, s.expectedNetConfig)
    96  }
    97  
    98  func (s *UserDataSuite) TestNewCloudInitConfigWithNetworks(c *gc.C) {
    99  	netConfig := container.BridgeNetworkConfig("foo", 0, s.fakeInterfaces)
   100  	cloudConf, err := containerinit.NewCloudInitConfigWithNetworks("quantal", netConfig)
   101  	c.Assert(err, jc.ErrorIsNil)
   102  	// We need to indent expectNetConfig to make it valid YAML,
   103  	// dropping the last new line and using unindented blank lines.
   104  	lines := strings.Split(s.expectedNetConfig, "\n")
   105  	indentedNetConfig := strings.Join(lines[:len(lines)-1], "\n  ")
   106  	indentedNetConfig = strings.Replace(indentedNetConfig, "\n  \n", "\n\n", -1)
   107  	expected := `
   108  #cloud-config
   109  bootcmd:
   110  - install -D -m 644 /dev/null '`[1:] + s.networkInterfacesFile + `'
   111  - |-
   112    printf '%s\n' '` + indentedNetConfig + `
   113    ' > '` + s.networkInterfacesFile + `'
   114  `
   115  	assertUserData(c, cloudConf, expected)
   116  }
   117  
   118  func (s *UserDataSuite) TestNewCloudInitConfigWithNetworksNoConfig(c *gc.C) {
   119  	netConfig := container.BridgeNetworkConfig("foo", 0, nil)
   120  	cloudConf, err := containerinit.NewCloudInitConfigWithNetworks("quantal", netConfig)
   121  	c.Assert(err, jc.ErrorIsNil)
   122  	expected := "#cloud-config\n{}\n"
   123  	assertUserData(c, cloudConf, expected)
   124  }
   125  
   126  func (s *UserDataSuite) TestCloudInitUserData(c *gc.C) {
   127  	instanceConfig, err := containertesting.MockMachineConfig("1/lxc/0")
   128  	c.Assert(err, jc.ErrorIsNil)
   129  	networkConfig := container.BridgeNetworkConfig("foo", 0, nil)
   130  	data, err := containerinit.CloudInitUserData(instanceConfig, networkConfig)
   131  	c.Assert(err, jc.ErrorIsNil)
   132  	// No need to test the exact contents here, as they are already
   133  	// tested separately.
   134  	c.Assert(string(data), jc.HasPrefix, "#cloud-config\n")
   135  }
   136  
   137  func assertUserData(c *gc.C, cloudConf cloudinit.CloudConfig, expected string) {
   138  	data, err := cloudConf.RenderYAML()
   139  	c.Assert(err, jc.ErrorIsNil)
   140  	c.Assert(string(data), gc.Equals, expected)
   141  	// Make sure it's valid YAML as well.
   142  	out := make(map[string]interface{})
   143  	err = yaml.Unmarshal(data, &out)
   144  	c.Assert(err, jc.ErrorIsNil)
   145  	if len(cloudConf.BootCmds()) > 0 {
   146  		outcmds := out["bootcmd"].([]interface{})
   147  		confcmds := cloudConf.BootCmds()
   148  		c.Assert(len(outcmds), gc.Equals, len(confcmds))
   149  		for i, _ := range outcmds {
   150  			c.Assert(outcmds[i].(string), gc.Equals, confcmds[i])
   151  		}
   152  	} else {
   153  		c.Assert(out["bootcmd"], gc.IsNil)
   154  	}
   155  }
   156  
   157  func (s *UserDataSuite) TestShutdownInitCommandsUpstart(c *gc.C) {
   158  	s.SetFeatureFlags(feature.AddressAllocation)
   159  	cmds, err := containerinit.ShutdownInitCommands(service.InitSystemUpstart, "trusty")
   160  	c.Assert(err, jc.ErrorIsNil)
   161  
   162  	filename := "/etc/init/juju-template-restart.conf"
   163  	script := `
   164  description "juju shutdown job"
   165  author "Juju Team <juju@lists.ubuntu.com>"
   166  start on stopped cloud-final
   167  
   168  script
   169    /bin/cat > /etc/network/interfaces << EOC
   170  # loopback interface
   171  auto lo
   172  iface lo inet loopback
   173  
   174  # primary interface
   175  auto eth0
   176  iface eth0 inet dhcp
   177  EOC
   178    /bin/rm -fr /var/lib/dhcp/dhclient* /var/log/cloud-init*.log
   179    /sbin/shutdown -h now
   180  end script
   181  
   182  post-stop script
   183    rm /etc/init/juju-template-restart.conf
   184  end script
   185  `[1:]
   186  	c.Check(cmds, gc.HasLen, 1)
   187  	testing.CheckWriteFileCommand(c, cmds[0], filename, script, nil)
   188  }
   189  
   190  func (s *UserDataSuite) TestShutdownInitCommandsSystemd(c *gc.C) {
   191  	s.SetFeatureFlags(feature.AddressAllocation)
   192  	commands, err := containerinit.ShutdownInitCommands(service.InitSystemSystemd, "vivid")
   193  	c.Assert(err, jc.ErrorIsNil)
   194  
   195  	test := systemdtesting.WriteConfTest{
   196  		Service: "juju-template-restart",
   197  		DataDir: "/var/lib/juju",
   198  		Expected: `
   199  [Unit]
   200  Description=juju shutdown job
   201  After=syslog.target
   202  After=network.target
   203  After=systemd-user-sessions.service
   204  After=cloud-config.target
   205  
   206  [Service]
   207  ExecStart=/var/lib/juju/init/juju-template-restart/exec-start.sh
   208  ExecStopPost=/bin/systemctl disable juju-template-restart.service
   209  
   210  [Install]
   211  WantedBy=multi-user.target
   212  `[1:],
   213  		Script: `
   214  /bin/cat > /etc/network/interfaces << EOC
   215  # loopback interface
   216  auto lo
   217  iface lo inet loopback
   218  
   219  # primary interface
   220  auto eth0
   221  iface eth0 inet dhcp
   222  EOC
   223    /bin/rm -fr /var/lib/dhcp/dhclient* /var/log/cloud-init*.log
   224    /sbin/shutdown -h now`[1:],
   225  	}
   226  	test.CheckInstallAndStartCommands(c, commands)
   227  }