github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/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.v2" 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 DNSSearchDomains: []string{"foo", "bar"}, 52 GatewayAddress: network.NewAddress("0.1.2.1"), 53 MACAddress: "aa:bb:cc:dd:ee:f0", 54 }, { 55 InterfaceName: "eth1", 56 CIDR: "0.1.2.0/24", 57 ConfigType: network.ConfigStatic, 58 NoAutoStart: false, 59 Address: network.NewAddress("0.1.2.4"), 60 DNSServers: network.NewAddresses("ns1.invalid", "ns2.invalid"), 61 DNSSearchDomains: []string{"foo", "bar"}, 62 GatewayAddress: network.NewAddress("0.1.2.1"), 63 MACAddress: "aa:bb:cc:dd:ee:f0", 64 }, { 65 InterfaceName: "eth2", 66 ConfigType: network.ConfigDHCP, 67 NoAutoStart: true, 68 }} 69 s.expectedNetConfig = ` 70 auto lo 71 iface lo inet loopback 72 73 auto eth0 74 iface eth0 inet manual 75 dns-nameservers ns1.invalid ns2.invalid 76 dns-search foo bar 77 pre-up ip address add 0.1.2.3/24 dev eth0 || true 78 up ip route replace 0.1.2.0/24 dev eth0 || true 79 down ip route del 0.1.2.0/24 dev eth0 || true 80 post-down address del 0.1.2.3/24 dev eth0 || true 81 up ip route replace default via 0.1.2.1 || true 82 down ip route del default via 0.1.2.1 || true 83 84 auto eth1 85 iface eth1 inet manual 86 dns-nameservers ns1.invalid ns2.invalid 87 dns-search foo bar 88 pre-up ip address add 0.1.2.4/24 dev eth1 || true 89 up ip route replace 0.1.2.0/24 dev eth1 || true 90 down ip route del 0.1.2.0/24 dev eth1 || true 91 post-down address del 0.1.2.4/24 dev eth1 || true 92 93 iface eth2 inet manual 94 pre-up ip address add dev eth2 || true 95 up ip route replace dev eth2 || true 96 down ip route del dev eth2 || true 97 post-down address del dev eth2 || true 98 99 ` 100 s.PatchValue(containerinit.NetworkInterfacesFile, s.networkInterfacesFile) 101 } 102 103 func (s *UserDataSuite) TestGenerateNetworkConfig(c *gc.C) { 104 // No config or no interfaces - no error, but also noting to generate. 105 data, err := containerinit.GenerateNetworkConfig(nil) 106 c.Assert(err, jc.ErrorIsNil) 107 c.Assert(data, gc.HasLen, 0) 108 netConfig := container.BridgeNetworkConfig("foo", 0, nil) 109 data, err = containerinit.GenerateNetworkConfig(netConfig) 110 c.Assert(err, jc.ErrorIsNil) 111 c.Assert(data, gc.HasLen, 0) 112 113 // Test with all interface types. 114 netConfig = container.BridgeNetworkConfig("foo", 0, s.fakeInterfaces) 115 data, err = containerinit.GenerateNetworkConfig(netConfig) 116 c.Assert(err, jc.ErrorIsNil) 117 c.Assert(data, gc.Equals, s.expectedNetConfig) 118 } 119 120 func (s *UserDataSuite) TestNewCloudInitConfigWithNetworks(c *gc.C) { 121 netConfig := container.BridgeNetworkConfig("foo", 0, s.fakeInterfaces) 122 cloudConf, err := containerinit.NewCloudInitConfigWithNetworks("quantal", netConfig) 123 c.Assert(err, jc.ErrorIsNil) 124 // We need to indent expectNetConfig to make it valid YAML, 125 // dropping the last new line and using unindented blank lines. 126 lines := strings.Split(s.expectedNetConfig, "\n") 127 indentedNetConfig := strings.Join(lines[:len(lines)-2], "\n ") 128 indentedNetConfig = strings.Replace(indentedNetConfig, "\n \n", "\n\n", -1) + "\n" 129 expected := ` 130 #cloud-config 131 bootcmd: 132 - install -D -m 644 /dev/null '`[1:] + s.networkInterfacesFile + `' 133 - |- 134 printf '%s\n' '` + indentedNetConfig + ` 135 ' > '` + s.networkInterfacesFile + `' 136 runcmd: 137 - ifup -a || true 138 ` 139 assertUserData(c, cloudConf, expected) 140 } 141 142 func (s *UserDataSuite) TestNewCloudInitConfigWithNetworksNoConfig(c *gc.C) { 143 netConfig := container.BridgeNetworkConfig("foo", 0, nil) 144 cloudConf, err := containerinit.NewCloudInitConfigWithNetworks("quantal", netConfig) 145 c.Assert(err, jc.ErrorIsNil) 146 expected := "#cloud-config\n{}\n" 147 assertUserData(c, cloudConf, expected) 148 } 149 150 func (s *UserDataSuite) TestCloudInitUserData(c *gc.C) { 151 instanceConfig, err := containertesting.MockMachineConfig("1/lxc/0") 152 c.Assert(err, jc.ErrorIsNil) 153 networkConfig := container.BridgeNetworkConfig("foo", 0, nil) 154 data, err := containerinit.CloudInitUserData(instanceConfig, networkConfig) 155 c.Assert(err, jc.ErrorIsNil) 156 // No need to test the exact contents here, as they are already 157 // tested separately. 158 c.Assert(string(data), jc.HasPrefix, "#cloud-config\n") 159 } 160 161 func assertUserData(c *gc.C, cloudConf cloudinit.CloudConfig, expected string) { 162 data, err := cloudConf.RenderYAML() 163 c.Assert(err, jc.ErrorIsNil) 164 c.Assert(string(data), gc.Equals, expected) 165 // Make sure it's valid YAML as well. 166 out := make(map[string]interface{}) 167 err = yaml.Unmarshal(data, &out) 168 c.Assert(err, jc.ErrorIsNil) 169 if len(cloudConf.BootCmds()) > 0 { 170 outcmds := out["bootcmd"].([]interface{}) 171 confcmds := cloudConf.BootCmds() 172 c.Assert(len(outcmds), gc.Equals, len(confcmds)) 173 for i, _ := range outcmds { 174 c.Assert(outcmds[i].(string), gc.Equals, confcmds[i]) 175 } 176 } else { 177 c.Assert(out["bootcmd"], gc.IsNil) 178 } 179 } 180 181 func (s *UserDataSuite) TestShutdownInitCommandsUpstart(c *gc.C) { 182 s.SetFeatureFlags(feature.AddressAllocation) 183 cmds, err := containerinit.ShutdownInitCommands(service.InitSystemUpstart, "trusty") 184 c.Assert(err, jc.ErrorIsNil) 185 186 filename := "/etc/init/juju-template-restart.conf" 187 script := ` 188 description "juju shutdown job" 189 author "Juju Team <juju@lists.ubuntu.com>" 190 start on stopped cloud-final 191 192 script 193 /bin/cat > /etc/network/interfaces << EOC 194 # loopback interface 195 auto lo 196 iface lo inet loopback 197 198 # primary interface 199 auto eth0 200 iface eth0 inet dhcp 201 EOC 202 /bin/rm -fr /var/lib/dhcp/dhclient* /var/log/cloud-init*.log 203 /sbin/shutdown -h now 204 end script 205 206 post-stop script 207 rm /etc/init/juju-template-restart.conf 208 end script 209 `[1:] 210 c.Check(cmds, gc.HasLen, 1) 211 testing.CheckWriteFileCommand(c, cmds[0], filename, script, nil) 212 } 213 214 func (s *UserDataSuite) TestShutdownInitCommandsSystemd(c *gc.C) { 215 s.SetFeatureFlags(feature.AddressAllocation) 216 commands, err := containerinit.ShutdownInitCommands(service.InitSystemSystemd, "vivid") 217 c.Assert(err, jc.ErrorIsNil) 218 219 test := systemdtesting.WriteConfTest{ 220 Service: "juju-template-restart", 221 DataDir: "/var/lib/juju", 222 Expected: ` 223 [Unit] 224 Description=juju shutdown job 225 After=syslog.target 226 After=network.target 227 After=systemd-user-sessions.service 228 After=cloud-config.target 229 230 [Service] 231 ExecStart=/var/lib/juju/init/juju-template-restart/exec-start.sh 232 ExecStopPost=/bin/systemctl disable juju-template-restart.service 233 234 [Install] 235 WantedBy=multi-user.target 236 `[1:], 237 Script: ` 238 /bin/cat > /etc/network/interfaces << EOC 239 # loopback interface 240 auto lo 241 iface lo inet loopback 242 243 # primary interface 244 auto eth0 245 iface eth0 inet dhcp 246 EOC 247 /bin/rm -fr /var/lib/dhcp/dhclient* /var/log/cloud-init*.log 248 /sbin/shutdown -h now`[1:], 249 } 250 test.CheckInstallAndStartCommands(c, commands) 251 }