summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/__init__.py0
-rw-r--r--tests/configs/sample1.yaml52
-rw-r--r--tests/data/filter_cloud_multipart.yaml30
-rw-r--r--tests/data/filter_cloud_multipart_1.email11
-rw-r--r--tests/data/filter_cloud_multipart_2.email39
-rw-r--r--tests/data/filter_cloud_multipart_header.email11
-rw-r--r--tests/data/merge_sources/expected1.yaml1
-rw-r--r--tests/data/merge_sources/expected10.yaml7
-rw-r--r--tests/data/merge_sources/expected11.yaml5
-rw-r--r--tests/data/merge_sources/expected12.yaml5
-rw-r--r--tests/data/merge_sources/expected2.yaml3
-rw-r--r--tests/data/merge_sources/expected3.yaml1
-rw-r--r--tests/data/merge_sources/expected4.yaml2
-rw-r--r--tests/data/merge_sources/expected5.yaml7
-rw-r--r--tests/data/merge_sources/expected6.yaml9
-rw-r--r--tests/data/merge_sources/expected7.yaml38
-rw-r--r--tests/data/merge_sources/expected8.yaml7
-rw-r--r--tests/data/merge_sources/expected9.yaml5
-rw-r--r--tests/data/merge_sources/source1-1.yaml3
-rw-r--r--tests/data/merge_sources/source1-2.yaml5
-rw-r--r--tests/data/merge_sources/source10-1.yaml6
-rw-r--r--tests/data/merge_sources/source10-2.yaml6
-rw-r--r--tests/data/merge_sources/source11-1.yaml5
-rw-r--r--tests/data/merge_sources/source11-2.yaml3
-rw-r--r--tests/data/merge_sources/source11-3.yaml3
-rw-r--r--tests/data/merge_sources/source12-1.yaml8
-rw-r--r--tests/data/merge_sources/source12-2.yaml5
-rw-r--r--tests/data/merge_sources/source2-1.yaml6
-rw-r--r--tests/data/merge_sources/source2-2.yaml5
-rw-r--r--tests/data/merge_sources/source3-1.yaml4
-rw-r--r--tests/data/merge_sources/source3-2.yaml4
-rw-r--r--tests/data/merge_sources/source4-1.yaml3
-rw-r--r--tests/data/merge_sources/source4-2.yaml6
-rw-r--r--tests/data/merge_sources/source5-1.yaml6
-rw-r--r--tests/data/merge_sources/source5-2.yaml8
-rw-r--r--tests/data/merge_sources/source6-1.yaml5
-rw-r--r--tests/data/merge_sources/source6-2.yaml8
-rw-r--r--tests/data/merge_sources/source7-1.yaml27
-rw-r--r--tests/data/merge_sources/source7-2.yaml17
-rw-r--r--tests/data/merge_sources/source8-1.yaml7
-rw-r--r--tests/data/merge_sources/source8-2.yaml6
-rw-r--r--tests/data/merge_sources/source9-1.yaml5
-rw-r--r--tests/data/merge_sources/source9-2.yaml6
-rw-r--r--tests/data/mountinfo_precise_ext4.txt24
-rw-r--r--tests/data/mountinfo_raring_btrfs.txt13
-rw-r--r--tests/data/roots/simple_ubuntu/etc/networks/interfaces3
-rw-r--r--tests/data/user_data.1.txt15
-rw-r--r--tests/data/vmware/cust-dhcp-2nic.cfg34
-rw-r--r--tests/data/vmware/cust-static-2nic.cfg39
-rw-r--r--tests/unittests/__init__.py0
-rw-r--r--tests/unittests/helpers.py291
-rw-r--r--tests/unittests/test__init__.py211
-rw-r--r--tests/unittests/test_builtin_handlers.py73
-rw-r--r--tests/unittests/test_cli.py34
-rw-r--r--tests/unittests/test_cs_util.py63
-rw-r--r--tests/unittests/test_data.py576
-rw-r--r--tests/unittests/test_datasource/__init__.py0
-rw-r--r--tests/unittests/test_datasource/test_altcloud.py452
-rw-r--r--tests/unittests/test_datasource/test_azure.py640
-rw-r--r--tests/unittests/test_datasource/test_azure_helper.py412
-rw-r--r--tests/unittests/test_datasource/test_cloudsigma.py99
-rw-r--r--tests/unittests/test_datasource/test_cloudstack.py78
-rw-r--r--tests/unittests/test_datasource/test_configdrive.py597
-rw-r--r--tests/unittests/test_datasource/test_digitalocean.py127
-rw-r--r--tests/unittests/test_datasource/test_gce.py166
-rw-r--r--tests/unittests/test_datasource/test_maas.py163
-rw-r--r--tests/unittests/test_datasource/test_nocloud.py178
-rw-r--r--tests/unittests/test_datasource/test_opennebula.py300
-rw-r--r--tests/unittests/test_datasource/test_openstack.py347
-rw-r--r--tests/unittests/test_datasource/test_smartos.py543
-rw-r--r--tests/unittests/test_distros/__init__.py0
-rw-r--r--tests/unittests/test_distros/test_generic.py233
-rw-r--r--tests/unittests/test_distros/test_hostname.py38
-rw-r--r--tests/unittests/test_distros/test_hosts.py41
-rw-r--r--tests/unittests/test_distros/test_netconfig.py381
-rw-r--r--tests/unittests/test_distros/test_resolv.py67
-rw-r--r--tests/unittests/test_distros/test_sysconfig.py82
-rw-r--r--tests/unittests/test_distros/test_user_data_normalize.py297
-rw-r--r--tests/unittests/test_ec2_util.py139
-rw-r--r--tests/unittests/test_filters/__init__.py0
-rw-r--r--tests/unittests/test_filters/test_launch_index.py132
-rw-r--r--tests/unittests/test_handler/__init__.py0
-rw-r--r--tests/unittests/test_handler/test_handler_apt_configure.py109
-rw-r--r--tests/unittests/test_handler/test_handler_apt_configure_sources_list.py180
-rw-r--r--tests/unittests/test_handler/test_handler_apt_source.py516
-rw-r--r--tests/unittests/test_handler/test_handler_ca_certs.py271
-rw-r--r--tests/unittests/test_handler/test_handler_chef.py192
-rw-r--r--tests/unittests/test_handler/test_handler_debug.py81
-rw-r--r--tests/unittests/test_handler/test_handler_disk_setup.py30
-rw-r--r--tests/unittests/test_handler/test_handler_growpart.py220
-rw-r--r--tests/unittests/test_handler/test_handler_locale.py67
-rw-r--r--tests/unittests/test_handler/test_handler_lxd.py134
-rw-r--r--tests/unittests/test_handler/test_handler_mcollective.py148
-rw-r--r--tests/unittests/test_handler/test_handler_mounts.py133
-rw-r--r--tests/unittests/test_handler/test_handler_power_state.py127
-rw-r--r--tests/unittests/test_handler/test_handler_rsyslog.py174
-rw-r--r--tests/unittests/test_handler/test_handler_seed_random.py227
-rw-r--r--tests/unittests/test_handler/test_handler_set_hostname.py72
-rw-r--r--tests/unittests/test_handler/test_handler_snappy.py306
-rw-r--r--tests/unittests/test_handler/test_handler_timezone.py76
-rw-r--r--tests/unittests/test_handler/test_handler_write_files.py112
-rw-r--r--tests/unittests/test_handler/test_handler_yum_add_repo.py68
-rw-r--r--tests/unittests/test_helpers.py33
-rw-r--r--tests/unittests/test_merging.py257
-rw-r--r--tests/unittests/test_net.py689
-rw-r--r--tests/unittests/test_pathprefix2dict.py44
-rw-r--r--tests/unittests/test_registry.py28
-rw-r--r--tests/unittests/test_reporting.py371
-rw-r--r--tests/unittests/test_rh_subscription.py226
-rw-r--r--tests/unittests/test_runs/__init__.py0
-rw-r--r--tests/unittests/test_runs/test_merge_run.py54
-rw-r--r--tests/unittests/test_runs/test_simple_run.py81
-rw-r--r--tests/unittests/test_sshutil.py171
-rw-r--r--tests/unittests/test_templating.py119
-rw-r--r--tests/unittests/test_util.py489
-rw-r--r--tests/unittests/test_vmware_config_file.py103
116 files changed, 0 insertions, 13196 deletions
diff --git a/tests/__init__.py b/tests/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/__init__.py
+++ /dev/null
diff --git a/tests/configs/sample1.yaml b/tests/configs/sample1.yaml
deleted file mode 100644
index 6231f293..00000000
--- a/tests/configs/sample1.yaml
+++ /dev/null
@@ -1,52 +0,0 @@
-#cloud-config
-#apt_update: false
-#apt_upgrade: true
-packages: [ bzr, pastebinit, ubuntu-dev-tools, ccache, bzr-builddeb, vim-nox, git-core, lftp ]
-
-#apt_sources:
-# - source: ppa:smoser/ppa
-
-#disable_root: False
-
-# mounts:
-# - [ ephemeral0, /mnt ]
-# - [ swap, none, swap, sw, 0, 0 ]
-
-ssh_import_id: [smoser ]
-
-#!/bin/sh
-
-output: {all: '| tee -a /var/log/cloud-init-output.log'}
-
-sm_misc:
- - &user_setup |
- set -x; exec > ~/user_setup.log 2>&1
- echo "starting at $(date -R)"
- echo "set -o vi" >> ~/.bashrc
- cat >> ~/.profile <<"EOF"
- export EDITOR=vi
- export DEB_BUILD_OPTIONS=parallel=4
- export PATH=/usr/lib/ccache:$PATH
- EOF
-
- mkdir ~/bin
- chmod 755 ~/bin
- cat > ~/bin/mdebuild <<"EOF"
- #!/bin/sh
- exec debuild --prepend-path /usr/lib/ccache "$@"
- EOF
- chmod 755 ~/bin/*
-
- #byobu-launcher-install
- byobu-ctrl-a screen 2>&1 || :
-
- echo "pinging 8.8.8.8"
- ping -c 4 8.8.8.8
-
-runcmd:
- - [ sudo, -Hu, ubuntu, sh, -c, '[ -e /var/log/cloud-init.log ] || exit 0; grep "cloud-init.*running" /var/log/cloud-init.log > ~/runcmd.log' ]
- - [ sudo, -Hu, ubuntu, sh, -c, 'read up sleep < /proc/uptime; echo $(date): runcmd up at $up | tee -a ~/runcmd.log' ]
- - [ sudo, -Hu, ubuntu, sh, -c, *user_setup ]
-
-
-byobu_by_default: user
diff --git a/tests/data/filter_cloud_multipart.yaml b/tests/data/filter_cloud_multipart.yaml
deleted file mode 100644
index 7acc2b9d..00000000
--- a/tests/data/filter_cloud_multipart.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
-#cloud-config-archive
----
-- content: "\n blah: true\n launch-index: 3\n"
- type: text/cloud-config
-- content: "\n blah: true\n launch-index: 4\n"
- type: text/cloud-config
-- content: The quick brown fox jumps over the lazy dog
- filename: b0.txt
- launch-index: 0
- type: plain/text
-- content: The quick brown fox jumps over the lazy dog
- filename: b3.txt
- launch-index: 3
- type: plain/text
-- content: The quick brown fox jumps over the lazy dog
- filename: b2.txt
- launch-index: 2
- type: plain/text
-- content: '#!/bin/bash \n echo "stuff"'
- filename: b2.txt
- launch-index: 2
-- content: '#!/bin/bash \n echo "stuff"'
- filename: b2.txt
- launch-index: 1
-- content: '#!/bin/bash \n echo "stuff"'
- filename: b2.txt
- # Use a string to see if conversion works
- launch-index: "1"
-...
-
diff --git a/tests/data/filter_cloud_multipart_1.email b/tests/data/filter_cloud_multipart_1.email
deleted file mode 100644
index 6d93b1f1..00000000
--- a/tests/data/filter_cloud_multipart_1.email
+++ /dev/null
@@ -1,11 +0,0 @@
-From nobody Fri Aug 31 17:17:00 2012
-Content-Type: text/plain; charset="us-ascii"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-
-
-#cloud-config
-b: c
-launch-index: 2
-
-
diff --git a/tests/data/filter_cloud_multipart_2.email b/tests/data/filter_cloud_multipart_2.email
deleted file mode 100644
index b04068c5..00000000
--- a/tests/data/filter_cloud_multipart_2.email
+++ /dev/null
@@ -1,39 +0,0 @@
-From nobody Fri Aug 31 17:43:04 2012
-Content-Type: multipart/mixed; boundary="===============1668325974=="
-MIME-Version: 1.0
-
---===============1668325974==
-Content-Type: text/cloud-config; charset="us-ascii"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-
-
-#cloud-config
-b: c
-launch-index: 2
-
-
---===============1668325974==
-Content-Type: text/plain; charset="us-ascii"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-
-
-#cloud-config-archive
-- content: The quick brown fox jumps over the lazy dog
- filename: b3.txt
- launch-index: 3
- type: plain/text
-
---===============1668325974==
-Content-Type: text/plain; charset="us-ascii"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-
-
-#cloud-config
-b: c
-launch-index: 2
-
-
---===============1668325974==--
diff --git a/tests/data/filter_cloud_multipart_header.email b/tests/data/filter_cloud_multipart_header.email
deleted file mode 100644
index 770f7ef1..00000000
--- a/tests/data/filter_cloud_multipart_header.email
+++ /dev/null
@@ -1,11 +0,0 @@
-From nobody Fri Aug 31 17:17:00 2012
-Content-Type: text/plain; charset="us-ascii"
-MIME-Version: 1.0
-Launch-Index: 5
-Content-Transfer-Encoding: 7bit
-
-
-#cloud-config
-b: c
-
-
diff --git a/tests/data/merge_sources/expected1.yaml b/tests/data/merge_sources/expected1.yaml
deleted file mode 100644
index 640d282b..00000000
--- a/tests/data/merge_sources/expected1.yaml
+++ /dev/null
@@ -1 +0,0 @@
-Blah: ['blah2', 'b']
diff --git a/tests/data/merge_sources/expected10.yaml b/tests/data/merge_sources/expected10.yaml
deleted file mode 100644
index b865db16..00000000
--- a/tests/data/merge_sources/expected10.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-#cloud-config
-
-power_state:
- delay: 30
- mode: poweroff
- message: [Bye, Bye, Pew, Pew]
-
diff --git a/tests/data/merge_sources/expected11.yaml b/tests/data/merge_sources/expected11.yaml
deleted file mode 100644
index c0530dc3..00000000
--- a/tests/data/merge_sources/expected11.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-#cloud-config
-
-a: 22
-b: 4
-c: 3
diff --git a/tests/data/merge_sources/expected12.yaml b/tests/data/merge_sources/expected12.yaml
deleted file mode 100644
index 0421d2c8..00000000
--- a/tests/data/merge_sources/expected12.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-#cloud-config
-
-a:
- e:
- y: 2
diff --git a/tests/data/merge_sources/expected2.yaml b/tests/data/merge_sources/expected2.yaml
deleted file mode 100644
index 6eccc2cf..00000000
--- a/tests/data/merge_sources/expected2.yaml
+++ /dev/null
@@ -1,3 +0,0 @@
-Blah: 3
-Blah2: 2
-Blah3: [1]
diff --git a/tests/data/merge_sources/expected3.yaml b/tests/data/merge_sources/expected3.yaml
deleted file mode 100644
index 32d9ad48..00000000
--- a/tests/data/merge_sources/expected3.yaml
+++ /dev/null
@@ -1 +0,0 @@
-Blah: [blah2, 'blah1']
diff --git a/tests/data/merge_sources/expected4.yaml b/tests/data/merge_sources/expected4.yaml
deleted file mode 100644
index d88d8f73..00000000
--- a/tests/data/merge_sources/expected4.yaml
+++ /dev/null
@@ -1,2 +0,0 @@
-#cloud-config
-Blah: {}
diff --git a/tests/data/merge_sources/expected5.yaml b/tests/data/merge_sources/expected5.yaml
deleted file mode 100644
index 628f5878..00000000
--- a/tests/data/merge_sources/expected5.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-#cloud-config
-
-Blah: 3
-Blah2: 2
-Blah3: [1]
-
-
diff --git a/tests/data/merge_sources/expected6.yaml b/tests/data/merge_sources/expected6.yaml
deleted file mode 100644
index 7afe1d7c..00000000
--- a/tests/data/merge_sources/expected6.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-#cloud-config
-
-run_cmds:
- - bash
- - top
- - ps
- - vi
- - emacs
-
diff --git a/tests/data/merge_sources/expected7.yaml b/tests/data/merge_sources/expected7.yaml
deleted file mode 100644
index 25284f04..00000000
--- a/tests/data/merge_sources/expected7.yaml
+++ /dev/null
@@ -1,38 +0,0 @@
-#cloud-config
-
-users:
- - default
- - name: foobar
- gecos: Foo B. Bar
- primary-group: foobar
- groups: users
- selinux-user: staff_u
- expiredate: 2012-09-01
- ssh-import-id: foobar
- lock-passwd: false
- passwd: $6$j212wezy$7H/1LT4f9/N3wpgNunhsIqtMj62OKiS3nyNwuizouQc3u7MbYCarYeAHWYPYb2FT.lbioDm2RrkJPb9BZMN1O/
- - name: barfoo
- gecos: Bar B. Foo
- sudo: ALL=(ALL) NOPASSWD:ALL
- groups: users, admin
- ssh-import-id: None
- lock-passwd: true
- ssh-authorized-keys:
- - <ssh pub key 1>
- - <ssh pub key 2>
- - name: cloudy
- gecos: Magic Cloud App Daemon User
- inactive: true
- system: true
- - bob
- - joe
- - sue
- - name: foobar_jr
- gecos: Foo B. Bar Jr
- primary-group: foobar
- groups: users
- selinux-user: staff_u
- expiredate: 2012-09-01
- ssh-import-id: foobar
- lock-passwd: false
- passwd: $6$j212wezy$7H/1LT4f9/N3wpgNunhsIqtMj62OKiS3nyNwuizouQc3u7MbYCarYeAHWYPYb2FT.lbioDm2RrkJPb9BZMN1O/
diff --git a/tests/data/merge_sources/expected8.yaml b/tests/data/merge_sources/expected8.yaml
deleted file mode 100644
index 69ca562d..00000000
--- a/tests/data/merge_sources/expected8.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-#cloud-config
-
-mounts:
- - [ ephemeral22, /mnt, auto, "defaults,noexec" ]
- - [ sdc, /opt/data ]
- - [ xvdh, /opt/data, "auto", "defaults,nobootwait", "0", "0" ]
- - [ dd, /dev/zero ]
diff --git a/tests/data/merge_sources/expected9.yaml b/tests/data/merge_sources/expected9.yaml
deleted file mode 100644
index 00f91ca0..00000000
--- a/tests/data/merge_sources/expected9.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-#cloud-config
-
-phone_home:
- url: http://my.example.com/$INSTANCE_ID/$BLAH_BLAH
- post: [ pub_key_dsa, pub_key_rsa, pub_key_ecdsa, instance_id ]
diff --git a/tests/data/merge_sources/source1-1.yaml b/tests/data/merge_sources/source1-1.yaml
deleted file mode 100644
index 38e4e5e0..00000000
--- a/tests/data/merge_sources/source1-1.yaml
+++ /dev/null
@@ -1,3 +0,0 @@
-#cloud-config
-Blah: ['blah2']
-
diff --git a/tests/data/merge_sources/source1-2.yaml b/tests/data/merge_sources/source1-2.yaml
deleted file mode 100644
index 2cd0e0e5..00000000
--- a/tests/data/merge_sources/source1-2.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-#cloud-config
-
-Blah: ['b']
-
-merge_how: 'dict(recurse_array,no_replace)+list(append)'
diff --git a/tests/data/merge_sources/source10-1.yaml b/tests/data/merge_sources/source10-1.yaml
deleted file mode 100644
index 6ae72a13..00000000
--- a/tests/data/merge_sources/source10-1.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-#cloud-config
-
-power_state:
- delay: 30
- mode: poweroff
- message: [Bye, Bye]
diff --git a/tests/data/merge_sources/source10-2.yaml b/tests/data/merge_sources/source10-2.yaml
deleted file mode 100644
index a38cf1c5..00000000
--- a/tests/data/merge_sources/source10-2.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-#cloud-config
-
-power_state:
- message: [Pew, Pew]
-
-merge_how: 'dict(recurse_list)+list(append)'
diff --git a/tests/data/merge_sources/source11-1.yaml b/tests/data/merge_sources/source11-1.yaml
deleted file mode 100644
index ee29d681..00000000
--- a/tests/data/merge_sources/source11-1.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-#cloud-config
-
-a: 1
-b: 2
-c: 3
diff --git a/tests/data/merge_sources/source11-2.yaml b/tests/data/merge_sources/source11-2.yaml
deleted file mode 100644
index a9914c34..00000000
--- a/tests/data/merge_sources/source11-2.yaml
+++ /dev/null
@@ -1,3 +0,0 @@
-#cloud-config
-
-b: 4
diff --git a/tests/data/merge_sources/source11-3.yaml b/tests/data/merge_sources/source11-3.yaml
deleted file mode 100644
index 8f2b8944..00000000
--- a/tests/data/merge_sources/source11-3.yaml
+++ /dev/null
@@ -1,3 +0,0 @@
-#cloud-config
-
-a: 22
diff --git a/tests/data/merge_sources/source12-1.yaml b/tests/data/merge_sources/source12-1.yaml
deleted file mode 100644
index 09e7c899..00000000
--- a/tests/data/merge_sources/source12-1.yaml
+++ /dev/null
@@ -1,8 +0,0 @@
-#cloud-config
-
-a:
- c: 1
- d: 2
- e:
- z: a
- y: b
diff --git a/tests/data/merge_sources/source12-2.yaml b/tests/data/merge_sources/source12-2.yaml
deleted file mode 100644
index 0421d2c8..00000000
--- a/tests/data/merge_sources/source12-2.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-#cloud-config
-
-a:
- e:
- y: 2
diff --git a/tests/data/merge_sources/source2-1.yaml b/tests/data/merge_sources/source2-1.yaml
deleted file mode 100644
index c7a33aaa..00000000
--- a/tests/data/merge_sources/source2-1.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-#cloud-config
-
-
-Blah: 1
-Blah2: 2
-Blah3: 3
diff --git a/tests/data/merge_sources/source2-2.yaml b/tests/data/merge_sources/source2-2.yaml
deleted file mode 100644
index 8f2fdc1a..00000000
--- a/tests/data/merge_sources/source2-2.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-#cloud-config
-
-Blah: 3
-Blah2: 2
-Blah3: [1]
diff --git a/tests/data/merge_sources/source3-1.yaml b/tests/data/merge_sources/source3-1.yaml
deleted file mode 100644
index 2303e906..00000000
--- a/tests/data/merge_sources/source3-1.yaml
+++ /dev/null
@@ -1,4 +0,0 @@
-#cloud-config
-Blah: ['blah1']
-
-
diff --git a/tests/data/merge_sources/source3-2.yaml b/tests/data/merge_sources/source3-2.yaml
deleted file mode 100644
index dca2ad10..00000000
--- a/tests/data/merge_sources/source3-2.yaml
+++ /dev/null
@@ -1,4 +0,0 @@
-#cloud-config
-Blah: ['blah2']
-
-merge_how: 'dict(recurse_array,no_replace)+list(prepend)'
diff --git a/tests/data/merge_sources/source4-1.yaml b/tests/data/merge_sources/source4-1.yaml
deleted file mode 100644
index e5b16872..00000000
--- a/tests/data/merge_sources/source4-1.yaml
+++ /dev/null
@@ -1,3 +0,0 @@
-#cloud-config
-Blah:
- b: 1
diff --git a/tests/data/merge_sources/source4-2.yaml b/tests/data/merge_sources/source4-2.yaml
deleted file mode 100644
index 1844e0f8..00000000
--- a/tests/data/merge_sources/source4-2.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-#cloud-config
-Blah:
- b: null
-
-
-merge_how: 'dict(allow_delete,no_replace)+list()'
diff --git a/tests/data/merge_sources/source5-1.yaml b/tests/data/merge_sources/source5-1.yaml
deleted file mode 100644
index c7a33aaa..00000000
--- a/tests/data/merge_sources/source5-1.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-#cloud-config
-
-
-Blah: 1
-Blah2: 2
-Blah3: 3
diff --git a/tests/data/merge_sources/source5-2.yaml b/tests/data/merge_sources/source5-2.yaml
deleted file mode 100644
index f61c96a2..00000000
--- a/tests/data/merge_sources/source5-2.yaml
+++ /dev/null
@@ -1,8 +0,0 @@
-#cloud-config
-
-Blah: 3
-Blah2: 2
-Blah3: [1]
-
-
-merge_how: 'dict(replace)+list(append)'
diff --git a/tests/data/merge_sources/source6-1.yaml b/tests/data/merge_sources/source6-1.yaml
deleted file mode 100644
index 519f7309..00000000
--- a/tests/data/merge_sources/source6-1.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-#cloud-config
-
-run_cmds:
- - bash
- - top
diff --git a/tests/data/merge_sources/source6-2.yaml b/tests/data/merge_sources/source6-2.yaml
deleted file mode 100644
index d8fac446..00000000
--- a/tests/data/merge_sources/source6-2.yaml
+++ /dev/null
@@ -1,8 +0,0 @@
-#cloud-config
-
-run_cmds:
- - ps
- - vi
- - emacs
-
-merge_type: 'list(append)+dict(recurse_array)+str()'
diff --git a/tests/data/merge_sources/source7-1.yaml b/tests/data/merge_sources/source7-1.yaml
deleted file mode 100644
index 8fb9b32a..00000000
--- a/tests/data/merge_sources/source7-1.yaml
+++ /dev/null
@@ -1,27 +0,0 @@
-#cloud-config
-
-users:
- - default
- - name: foobar
- gecos: Foo B. Bar
- primary-group: foobar
- groups: users
- selinux-user: staff_u
- expiredate: 2012-09-01
- ssh-import-id: foobar
- lock-passwd: false
- passwd: $6$j212wezy$7H/1LT4f9/N3wpgNunhsIqtMj62OKiS3nyNwuizouQc3u7MbYCarYeAHWYPYb2FT.lbioDm2RrkJPb9BZMN1O/
- - name: barfoo
- gecos: Bar B. Foo
- sudo: ALL=(ALL) NOPASSWD:ALL
- groups: users, admin
- ssh-import-id: None
- lock-passwd: true
- ssh-authorized-keys:
- - <ssh pub key 1>
- - <ssh pub key 2>
- - name: cloudy
- gecos: Magic Cloud App Daemon User
- inactive: true
- system: true
-
diff --git a/tests/data/merge_sources/source7-2.yaml b/tests/data/merge_sources/source7-2.yaml
deleted file mode 100644
index 1e26201b..00000000
--- a/tests/data/merge_sources/source7-2.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-#cloud-config
-
-users:
- - bob
- - joe
- - sue
- - name: foobar_jr
- gecos: Foo B. Bar Jr
- primary-group: foobar
- groups: users
- selinux-user: staff_u
- expiredate: 2012-09-01
- ssh-import-id: foobar
- lock-passwd: false
- passwd: $6$j212wezy$7H/1LT4f9/N3wpgNunhsIqtMj62OKiS3nyNwuizouQc3u7MbYCarYeAHWYPYb2FT.lbioDm2RrkJPb9BZMN1O/
-
-merge_how: "dict(recurse_array)+list(append)"
diff --git a/tests/data/merge_sources/source8-1.yaml b/tests/data/merge_sources/source8-1.yaml
deleted file mode 100644
index 5ea51c2c..00000000
--- a/tests/data/merge_sources/source8-1.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-#cloud-config
-
-mounts:
- - [ ephemeral0, /mnt, auto, "defaults,noexec" ]
- - [ sdc, /opt/data ]
- - [ xvdh, /opt/data, "auto", "defaults,nobootwait", "0", "0" ]
- - [ dd, /dev/zero ]
diff --git a/tests/data/merge_sources/source8-2.yaml b/tests/data/merge_sources/source8-2.yaml
deleted file mode 100644
index 7fa3262b..00000000
--- a/tests/data/merge_sources/source8-2.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-#cloud-config
-
-mounts:
- - [ ephemeral22, /mnt, auto, "defaults,noexec" ]
-
-merge_how: 'dict(recurse_array)+list(recurse_list,recurse_str)+str()'
diff --git a/tests/data/merge_sources/source9-1.yaml b/tests/data/merge_sources/source9-1.yaml
deleted file mode 100644
index 0b102ba6..00000000
--- a/tests/data/merge_sources/source9-1.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-#cloud-config
-
-phone_home:
- url: http://my.example.com/$INSTANCE_ID/
- post: [ pub_key_dsa, pub_key_rsa, pub_key_ecdsa, instance_id ]
diff --git a/tests/data/merge_sources/source9-2.yaml b/tests/data/merge_sources/source9-2.yaml
deleted file mode 100644
index ac85afc6..00000000
--- a/tests/data/merge_sources/source9-2.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-#cloud-config
-
-phone_home:
- url: $BLAH_BLAH
-
-merge_how: 'dict(recurse_str)+str(append)'
diff --git a/tests/data/mountinfo_precise_ext4.txt b/tests/data/mountinfo_precise_ext4.txt
deleted file mode 100644
index a7a1db67..00000000
--- a/tests/data/mountinfo_precise_ext4.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-15 20 0:14 / /sys rw,nosuid,nodev,noexec,relatime - sysfs sysfs rw
-16 20 0:3 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw
-17 20 0:5 / /dev rw,relatime - devtmpfs udev rw,size=16422216k,nr_inodes=4105554,mode=755
-18 17 0:11 / /dev/pts rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=000
-19 20 0:15 / /run rw,nosuid,relatime - tmpfs tmpfs rw,size=6572812k,mode=755
-20 1 252:1 / / rw,relatime - ext4 /dev/mapper/vg0-root rw,errors=remount-ro,data=ordered
-21 15 0:16 / /sys/fs/cgroup rw,relatime - tmpfs cgroup rw,mode=755
-22 15 0:17 / /sys/fs/fuse/connections rw,relatime - fusectl none rw
-23 15 0:6 / /sys/kernel/debug rw,relatime - debugfs none rw
-25 15 0:10 / /sys/kernel/security rw,relatime - securityfs none rw
-26 19 0:19 / /run/lock rw,nosuid,nodev,noexec,relatime - tmpfs none rw,size=5120k
-27 19 0:20 / /run/shm rw,nosuid,nodev,relatime - tmpfs none rw
-28 19 0:21 / /run/user rw,nosuid,nodev,noexec,relatime - tmpfs none rw,size=102400k,mode=755
-24 21 0:18 / /sys/fs/cgroup/cpuset rw,relatime - cgroup cgroup rw,cpuset
-29 21 0:22 / /sys/fs/cgroup/cpu rw,relatime - cgroup cgroup rw,cpu
-30 21 0:23 / /sys/fs/cgroup/cpuacct rw,relatime - cgroup cgroup rw,cpuacct
-31 21 0:24 / /sys/fs/cgroup/memory rw,relatime - cgroup cgroup rw,memory
-32 21 0:25 / /sys/fs/cgroup/devices rw,relatime - cgroup cgroup rw,devices
-33 21 0:26 / /sys/fs/cgroup/freezer rw,relatime - cgroup cgroup rw,freezer
-34 21 0:27 / /sys/fs/cgroup/blkio rw,relatime - cgroup cgroup rw,blkio
-35 21 0:28 / /sys/fs/cgroup/perf_event rw,relatime - cgroup cgroup rw,perf_event
-36 20 9:0 / /boot rw,relatime - ext4 /dev/md0 rw,data=ordered
-37 16 0:29 / /proc/sys/fs/binfmt_misc rw,nosuid,nodev,noexec,relatime - binfmt_misc binfmt_misc rw
-39 28 0:30 / /run/user/foobar/gvfs rw,nosuid,nodev,relatime - fuse.gvfsd-fuse gvfsd-fuse rw,user_id=1000,group_id=1000
diff --git a/tests/data/mountinfo_raring_btrfs.txt b/tests/data/mountinfo_raring_btrfs.txt
deleted file mode 100644
index c5795636..00000000
--- a/tests/data/mountinfo_raring_btrfs.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-15 20 0:14 / /sys rw,nosuid,nodev,noexec,relatime - sysfs sysfs rw
-16 20 0:3 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw
-17 20 0:5 / /dev rw,relatime - devtmpfs udev rw,size=865556k,nr_inodes=216389,mode=755
-18 17 0:11 / /dev/pts rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=000
-19 20 0:15 / /run rw,nosuid,relatime - tmpfs tmpfs rw,size=348196k,mode=755
-20 1 0:16 /@ / rw,relatime - btrfs /dev/vda1 rw,compress=lzo,space_cache
-21 15 0:19 / /sys/fs/fuse/connections rw,relatime - fusectl none rw
-22 15 0:6 / /sys/kernel/debug rw,relatime - debugfs none rw
-23 15 0:10 / /sys/kernel/security rw,relatime - securityfs none rw
-24 19 0:20 / /run/lock rw,nosuid,nodev,noexec,relatime - tmpfs none rw,size=5120k
-25 19 0:21 / /run/shm rw,nosuid,nodev,relatime - tmpfs none rw
-26 19 0:22 / /run/user rw,nosuid,nodev,noexec,relatime - tmpfs none rw,size=102400k,mode=755
-27 20 0:16 /@home /home rw,relatime - btrfs /dev/vda1 rw,compress=lzo,space_cache
diff --git a/tests/data/roots/simple_ubuntu/etc/networks/interfaces b/tests/data/roots/simple_ubuntu/etc/networks/interfaces
deleted file mode 100644
index 77efa67d..00000000
--- a/tests/data/roots/simple_ubuntu/etc/networks/interfaces
+++ /dev/null
@@ -1,3 +0,0 @@
-auto lo
-iface lo inet loopback
-
diff --git a/tests/data/user_data.1.txt b/tests/data/user_data.1.txt
deleted file mode 100644
index 4c4543de..00000000
--- a/tests/data/user_data.1.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-#cloud-config
-write_files:
-- content: blah
- path: /etc/blah.ini
- permissions: 493
-
-system_info:
- package_mirrors:
- - arches: [i386, amd64, blah]
- failsafe:
- primary: http://my.archive.mydomain.com/ubuntu
- security: http://my.security.mydomain.com/ubuntu
- search:
- primary: []
- security: []
diff --git a/tests/data/vmware/cust-dhcp-2nic.cfg b/tests/data/vmware/cust-dhcp-2nic.cfg
deleted file mode 100644
index f687311a..00000000
--- a/tests/data/vmware/cust-dhcp-2nic.cfg
+++ /dev/null
@@ -1,34 +0,0 @@
-[NETWORK]
-NETWORKING = yes
-BOOTPROTO = dhcp
-HOSTNAME = myhost1
-DOMAINNAME = eng.vmware.com
-
-[NIC-CONFIG]
-NICS = NIC1,NIC2
-
-[NIC1]
-MACADDR = 00:50:56:a6:8c:08
-ONBOOT = yes
-IPv4_MODE = BACKWARDS_COMPATIBLE
-BOOTPROTO = dhcp
-
-[NIC2]
-MACADDR = 00:50:56:a6:5a:de
-ONBOOT = yes
-IPv4_MODE = BACKWARDS_COMPATIBLE
-BOOTPROTO = dhcp
-
-# some random comment
-
-[PASSWORD]
-# secret
--PASS = c2VjcmV0Cg==
-
-[DNS]
-DNSFROMDHCP=yes
-SUFFIX|1 = eng.vmware.com
-
-[DATETIME]
-TIMEZONE = Africa/Abidjan
-UTC = yes
diff --git a/tests/data/vmware/cust-static-2nic.cfg b/tests/data/vmware/cust-static-2nic.cfg
deleted file mode 100644
index 0d80c2c4..00000000
--- a/tests/data/vmware/cust-static-2nic.cfg
+++ /dev/null
@@ -1,39 +0,0 @@
-[NETWORK]
-NETWORKING = yes
-BOOTPROTO = dhcp
-HOSTNAME = myhost1
-DOMAINNAME = eng.vmware.com
-
-[NIC-CONFIG]
-NICS = NIC1,NIC2
-
-[NIC1]
-MACADDR = 00:50:56:a6:8c:08
-ONBOOT = yes
-IPv4_MODE = BACKWARDS_COMPATIBLE
-BOOTPROTO = static
-IPADDR = 10.20.87.154
-NETMASK = 255.255.252.0
-GATEWAY = 10.20.87.253, 10.20.87.105
-IPv6ADDR|1 = fc00:10:20:87::154
-IPv6NETMASK|1 = 64
-IPv6GATEWAY|1 = fc00:10:20:87::253
-[NIC2]
-MACADDR = 00:50:56:a6:ef:7d
-ONBOOT = yes
-IPv4_MODE = BACKWARDS_COMPATIBLE
-BOOTPROTO = static
-IPADDR = 192.168.6.102
-NETMASK = 255.255.0.0
-GATEWAY = 192.168.0.10
-
-[DNS]
-DNSFROMDHCP=no
-SUFFIX|1 = eng.vmware.com
-SUFFIX|2 = proxy.vmware.com
-NAMESERVER|1 = 10.20.145.1
-NAMESERVER|2 = 10.20.145.2
-
-[DATETIME]
-TIMEZONE = Africa/Abidjan
-UTC = yes
diff --git a/tests/unittests/__init__.py b/tests/unittests/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/unittests/__init__.py
+++ /dev/null
diff --git a/tests/unittests/helpers.py b/tests/unittests/helpers.py
deleted file mode 100644
index 972245df..00000000
--- a/tests/unittests/helpers.py
+++ /dev/null
@@ -1,291 +0,0 @@
-from __future__ import print_function
-
-import functools
-import os
-import shutil
-import sys
-import tempfile
-import unittest
-
-import mock
-import six
-import unittest2
-
-try:
- from contextlib import ExitStack
-except ImportError:
- from contextlib2 import ExitStack
-
-from cloudinit import helpers as ch
-from cloudinit import util
-
-# Used for skipping tests
-SkipTest = unittest2.SkipTest
-
-# Used for detecting different python versions
-PY2 = False
-PY26 = False
-PY27 = False
-PY3 = False
-FIX_HTTPRETTY = False
-
-_PY_VER = sys.version_info
-_PY_MAJOR, _PY_MINOR, _PY_MICRO = _PY_VER[0:3]
-if (_PY_MAJOR, _PY_MINOR) <= (2, 6):
- if (_PY_MAJOR, _PY_MINOR) == (2, 6):
- PY26 = True
- if (_PY_MAJOR, _PY_MINOR) >= (2, 0):
- PY2 = True
-else:
- if (_PY_MAJOR, _PY_MINOR) == (2, 7):
- PY27 = True
- PY2 = True
- if (_PY_MAJOR, _PY_MINOR) >= (3, 0):
- PY3 = True
- if _PY_MINOR == 4 and _PY_MICRO < 3:
- FIX_HTTPRETTY = True
-
-
-# Makes the old path start
-# with new base instead of whatever
-# it previously had
-def rebase_path(old_path, new_base):
- if old_path.startswith(new_base):
- # Already handled...
- return old_path
- # Retarget the base of that path
- # to the new base instead of the
- # old one...
- path = os.path.join(new_base, old_path.lstrip("/"))
- path = os.path.abspath(path)
- return path
-
-
-# Can work on anything that takes a path as arguments
-def retarget_many_wrapper(new_base, am, old_func):
- def wrapper(*args, **kwds):
- n_args = list(args)
- nam = am
- if am == -1:
- nam = len(n_args)
- for i in range(0, nam):
- path = args[i]
- # patchOS() wraps various os and os.path functions, however in
- # Python 3 some of these now accept file-descriptors (integers).
- # That breaks rebase_path() so in lieu of a better solution, just
- # don't rebase if we get a fd.
- if isinstance(path, six.string_types):
- n_args[i] = rebase_path(path, new_base)
- return old_func(*n_args, **kwds)
- return wrapper
-
-
-class TestCase(unittest2.TestCase):
- pass
-
-
-class ResourceUsingTestCase(TestCase):
- def setUp(self):
- super(ResourceUsingTestCase, self).setUp()
- self.resource_path = None
-
- def resourceLocation(self, subname=None):
- if self.resource_path is None:
- paths = [
- os.path.join('tests', 'data'),
- os.path.join('data'),
- os.path.join(os.pardir, 'tests', 'data'),
- os.path.join(os.pardir, 'data'),
- ]
- for p in paths:
- if os.path.isdir(p):
- self.resource_path = p
- break
- self.assertTrue((self.resource_path and
- os.path.isdir(self.resource_path)),
- msg="Unable to locate test resource data path!")
- if not subname:
- return self.resource_path
- return os.path.join(self.resource_path, subname)
-
- def readResource(self, name):
- where = self.resourceLocation(name)
- with open(where, 'r') as fh:
- return fh.read()
-
- def getCloudPaths(self, ds=None):
- tmpdir = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, tmpdir)
- cp = ch.Paths({'cloud_dir': tmpdir,
- 'templates_dir': self.resourceLocation()},
- ds=ds)
- return cp
-
-
-class FilesystemMockingTestCase(ResourceUsingTestCase):
- def setUp(self):
- super(FilesystemMockingTestCase, self).setUp()
- self.patched_funcs = ExitStack()
-
- def tearDown(self):
- self.patched_funcs.close()
- ResourceUsingTestCase.tearDown(self)
-
- def replicateTestRoot(self, example_root, target_root):
- real_root = self.resourceLocation()
- real_root = os.path.join(real_root, 'roots', example_root)
- for (dir_path, _dirnames, filenames) in os.walk(real_root):
- real_path = dir_path
- make_path = rebase_path(real_path[len(real_root):], target_root)
- util.ensure_dir(make_path)
- for f in filenames:
- real_path = util.abs_join(real_path, f)
- make_path = util.abs_join(make_path, f)
- shutil.copy(real_path, make_path)
-
- def patchUtils(self, new_root):
- patch_funcs = {
- util: [('write_file', 1),
- ('append_file', 1),
- ('load_file', 1),
- ('ensure_dir', 1),
- ('chmod', 1),
- ('delete_dir_contents', 1),
- ('del_file', 1),
- ('sym_link', -1),
- ('copy', -1)],
- }
- for (mod, funcs) in patch_funcs.items():
- for (f, am) in funcs:
- func = getattr(mod, f)
- trap_func = retarget_many_wrapper(new_root, am, func)
- self.patched_funcs.enter_context(
- mock.patch.object(mod, f, trap_func))
-
- # Handle subprocess calls
- func = getattr(util, 'subp')
-
- def nsubp(*_args, **_kwargs):
- return ('', '')
-
- self.patched_funcs.enter_context(
- mock.patch.object(util, 'subp', nsubp))
-
- def null_func(*_args, **_kwargs):
- return None
-
- for f in ['chownbyid', 'chownbyname']:
- self.patched_funcs.enter_context(
- mock.patch.object(util, f, null_func))
-
- def patchOS(self, new_root):
- patch_funcs = {
- os.path: [('isfile', 1), ('exists', 1),
- ('islink', 1), ('isdir', 1)],
- os: [('listdir', 1), ('mkdir', 1),
- ('lstat', 1), ('symlink', 2)],
- }
- for (mod, funcs) in patch_funcs.items():
- for f, nargs in funcs:
- func = getattr(mod, f)
- trap_func = retarget_many_wrapper(new_root, nargs, func)
- self.patched_funcs.enter_context(
- mock.patch.object(mod, f, trap_func))
-
- def patchOpen(self, new_root):
- trap_func = retarget_many_wrapper(new_root, 1, open)
- name = 'builtins.open' if PY3 else '__builtin__.open'
- self.patched_funcs.enter_context(mock.patch(name, trap_func))
-
- def patchStdoutAndStderr(self, stdout=None, stderr=None):
- if stdout is not None:
- self.patched_funcs.enter_context(
- mock.patch.object(sys, 'stdout', stdout))
- if stderr is not None:
- self.patched_funcs.enter_context(
- mock.patch.object(sys, 'stderr', stderr))
-
-
-def import_httpretty():
- """Import HTTPretty and monkey patch Python 3.4 issue.
- See https://github.com/gabrielfalcao/HTTPretty/pull/193 and
- as well as https://github.com/gabrielfalcao/HTTPretty/issues/221.
-
- Lifted from
- https://github.com/inveniosoftware/datacite/blob/master/tests/helpers.py
- """
- if not FIX_HTTPRETTY:
- import httpretty
- else:
- import socket
- old_SocketType = socket.SocketType
-
- import httpretty
- from httpretty import core
-
- def sockettype_patch(f):
- @functools.wraps(f)
- def inner(*args, **kwargs):
- f(*args, **kwargs)
- socket.SocketType = old_SocketType
- socket.__dict__['SocketType'] = old_SocketType
- return inner
-
- core.httpretty.disable = sockettype_patch(
- httpretty.httpretty.disable
- )
- return httpretty
-
-
-class HttprettyTestCase(TestCase):
- # necessary as http_proxy gets in the way of httpretty
- # https://github.com/gabrielfalcao/HTTPretty/issues/122
- def setUp(self):
- self.restore_proxy = os.environ.get('http_proxy')
- if self.restore_proxy is not None:
- del os.environ['http_proxy']
- super(HttprettyTestCase, self).setUp()
-
- def tearDown(self):
- if self.restore_proxy:
- os.environ['http_proxy'] = self.restore_proxy
- super(HttprettyTestCase, self).tearDown()
-
-
-def populate_dir(path, files):
- if not os.path.exists(path):
- os.makedirs(path)
- for (name, content) in files.items():
- with open(os.path.join(path, name), "wb") as fp:
- if isinstance(content, six.binary_type):
- fp.write(content)
- else:
- fp.write(content.encode('utf-8'))
- fp.close()
-
-
-def dir2dict(startdir, prefix=None):
- flist = {}
- if prefix is None:
- prefix = startdir
- for root, dirs, files in os.walk(startdir):
- for fname in files:
- fpath = os.path.join(root, fname)
- key = fpath[len(prefix):]
- flist[key] = util.load_file(fpath)
- return flist
-
-
-try:
- skipIf = unittest.skipIf
-except AttributeError:
- # Python 2.6. Doesn't have to be high fidelity.
- def skipIf(condition, reason):
- def decorator(func):
- def wrapper(*args, **kws):
- if condition:
- return func(*args, **kws)
- else:
- print(reason, file=sys.stderr)
- return wrapper
- return decorator
diff --git a/tests/unittests/test__init__.py b/tests/unittests/test__init__.py
deleted file mode 100644
index 0154784a..00000000
--- a/tests/unittests/test__init__.py
+++ /dev/null
@@ -1,211 +0,0 @@
-import os
-import shutil
-import tempfile
-
-from cloudinit import handlers
-from cloudinit import helpers
-from cloudinit import settings
-from cloudinit import url_helper
-from cloudinit import util
-
-from .helpers import TestCase, ExitStack, mock
-
-
-class FakeModule(handlers.Handler):
- def __init__(self):
- handlers.Handler.__init__(self, settings.PER_ALWAYS)
- self.types = []
-
- def list_types(self):
- return self.types
-
- def handle_part(self, data, ctype, filename, payload, frequency):
- pass
-
-
-class TestWalkerHandleHandler(TestCase):
-
- def setUp(self):
- super(TestWalkerHandleHandler, self).setUp()
- tmpdir = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, tmpdir)
-
- self.data = {
- "handlercount": 0,
- "frequency": "",
- "handlerdir": tmpdir,
- "handlers": helpers.ContentHandlers(),
- "data": None}
-
- self.expected_module_name = "part-handler-%03d" % (
- self.data["handlercount"],)
- expected_file_name = "%s.py" % self.expected_module_name
- self.expected_file_fullname = os.path.join(
- self.data["handlerdir"], expected_file_name)
- self.module_fake = FakeModule()
- self.ctype = None
- self.filename = None
- self.payload = "dummy payload"
-
- # Mock the write_file() function. We'll assert that it got called as
- # expected in each of the individual tests.
- resources = ExitStack()
- self.addCleanup(resources.close)
- self.write_file_mock = resources.enter_context(
- mock.patch('cloudinit.util.write_file'))
-
- def test_no_errors(self):
- """Payload gets written to file and added to C{pdata}."""
- with mock.patch('cloudinit.importer.import_module',
- return_value=self.module_fake) as mockobj:
- handlers.walker_handle_handler(self.data, self.ctype,
- self.filename, self.payload)
- mockobj.assert_called_once_with(self.expected_module_name)
- self.write_file_mock.assert_called_once_with(
- self.expected_file_fullname, self.payload, 0o600)
- self.assertEqual(self.data['handlercount'], 1)
-
- def test_import_error(self):
- """Module import errors are logged. No handler added to C{pdata}."""
- with mock.patch('cloudinit.importer.import_module',
- side_effect=ImportError) as mockobj:
- handlers.walker_handle_handler(self.data, self.ctype,
- self.filename, self.payload)
- mockobj.assert_called_once_with(self.expected_module_name)
- self.write_file_mock.assert_called_once_with(
- self.expected_file_fullname, self.payload, 0o600)
- self.assertEqual(self.data['handlercount'], 0)
-
- def test_attribute_error(self):
- """Attribute errors are logged. No handler added to C{pdata}."""
- with mock.patch('cloudinit.importer.import_module',
- side_effect=AttributeError,
- return_value=self.module_fake) as mockobj:
- handlers.walker_handle_handler(self.data, self.ctype,
- self.filename, self.payload)
- mockobj.assert_called_once_with(self.expected_module_name)
- self.write_file_mock.assert_called_once_with(
- self.expected_file_fullname, self.payload, 0o600)
- self.assertEqual(self.data['handlercount'], 0)
-
-
-class TestHandlerHandlePart(TestCase):
-
- def setUp(self):
- super(TestHandlerHandlePart, self).setUp()
- self.data = "fake data"
- self.ctype = "fake ctype"
- self.filename = "fake filename"
- self.payload = "fake payload"
- self.frequency = settings.PER_INSTANCE
- self.headers = {
- 'Content-Type': self.ctype,
- }
-
- def test_normal_version_1(self):
- """
- C{handle_part} is called without C{frequency} for
- C{handler_version} == 1.
- """
- mod_mock = mock.Mock(frequency=settings.PER_INSTANCE,
- handler_version=1)
- handlers.run_part(mod_mock, self.data, self.filename, self.payload,
- self.frequency, self.headers)
- # Assert that the handle_part() method of the mock object got
- # called with the expected arguments.
- mod_mock.handle_part.assert_called_once_with(
- self.data, self.ctype, self.filename, self.payload)
-
- def test_normal_version_2(self):
- """
- C{handle_part} is called with C{frequency} for
- C{handler_version} == 2.
- """
- mod_mock = mock.Mock(frequency=settings.PER_INSTANCE,
- handler_version=2)
- handlers.run_part(mod_mock, self.data, self.filename, self.payload,
- self.frequency, self.headers)
- # Assert that the handle_part() method of the mock object got
- # called with the expected arguments.
- mod_mock.handle_part.assert_called_once_with(
- self.data, self.ctype, self.filename, self.payload,
- settings.PER_INSTANCE)
-
- def test_modfreq_per_always(self):
- """
- C{handle_part} is called regardless of frequency if nofreq is always.
- """
- self.frequency = "once"
- mod_mock = mock.Mock(frequency=settings.PER_ALWAYS,
- handler_version=1)
- handlers.run_part(mod_mock, self.data, self.filename, self.payload,
- self.frequency, self.headers)
- # Assert that the handle_part() method of the mock object got
- # called with the expected arguments.
- mod_mock.handle_part.assert_called_once_with(
- self.data, self.ctype, self.filename, self.payload)
-
- def test_no_handle_when_modfreq_once(self):
- """C{handle_part} is not called if frequency is once."""
- self.frequency = "once"
- mod_mock = mock.Mock(frequency=settings.PER_ONCE)
- handlers.run_part(mod_mock, self.data, self.filename, self.payload,
- self.frequency, self.headers)
- self.assertEqual(0, mod_mock.handle_part.call_count)
-
- def test_exception_is_caught(self):
- """Exceptions within C{handle_part} are caught and logged."""
- mod_mock = mock.Mock(frequency=settings.PER_INSTANCE,
- handler_version=1)
- mod_mock.handle_part.side_effect = Exception
- try:
- handlers.run_part(mod_mock, self.data, self.filename,
- self.payload, self.frequency, self.headers)
- except Exception:
- self.fail("Exception was not caught in handle_part")
-
- mod_mock.handle_part.assert_called_once_with(
- self.data, self.ctype, self.filename, self.payload)
-
-
-class TestCmdlineUrl(TestCase):
- def test_invalid_content(self):
- url = "http://example.com/foo"
- key = "mykey"
- payload = b"0"
- cmdline = "ro %s=%s bar=1" % (key, url)
-
- with mock.patch('cloudinit.url_helper.readurl',
- return_value=url_helper.StringResponse(payload)):
- self.assertEqual(
- util.get_cmdline_url(names=[key], starts="xxxxxx",
- cmdline=cmdline),
- (key, url, None))
-
- def test_valid_content(self):
- url = "http://example.com/foo"
- key = "mykey"
- payload = b"xcloud-config\nmydata: foo\nbar: wark\n"
- cmdline = "ro %s=%s bar=1" % (key, url)
-
- with mock.patch('cloudinit.url_helper.readurl',
- return_value=url_helper.StringResponse(payload)):
- self.assertEqual(
- util.get_cmdline_url(names=[key], starts=b"xcloud-config",
- cmdline=cmdline),
- (key, url, payload))
-
- def test_no_key_found(self):
- url = "http://example.com/foo"
- key = "mykey"
- cmdline = "ro %s=%s bar=1" % (key, url)
-
- with mock.patch('cloudinit.url_helper.readurl',
- return_value=url_helper.StringResponse(b'')):
- self.assertEqual(
- util.get_cmdline_url(names=["does-not-appear"],
- starts="#cloud-config", cmdline=cmdline),
- (None, None, None))
-
-
-# vi: ts=4 expandtab
diff --git a/tests/unittests/test_builtin_handlers.py b/tests/unittests/test_builtin_handlers.py
deleted file mode 100644
index dea908d7..00000000
--- a/tests/unittests/test_builtin_handlers.py
+++ /dev/null
@@ -1,73 +0,0 @@
-"""Tests of the built-in user data handlers."""
-
-import os
-import shutil
-import tempfile
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-
-from . import helpers as test_helpers
-
-from cloudinit import handlers
-from cloudinit import helpers
-from cloudinit import util
-
-from cloudinit.handlers import upstart_job
-
-from cloudinit.settings import (PER_ALWAYS, PER_INSTANCE)
-
-
-class TestBuiltins(test_helpers.FilesystemMockingTestCase):
- def test_upstart_frequency_no_out(self):
- c_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, c_root)
- up_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, up_root)
- paths = helpers.Paths({
- 'cloud_dir': c_root,
- 'upstart_dir': up_root,
- })
- freq = PER_ALWAYS
- h = upstart_job.UpstartJobPartHandler(paths)
- # No files should be written out when
- # the frequency is ! per-instance
- h.handle_part('', handlers.CONTENT_START,
- None, None, None)
- h.handle_part('blah', 'text/upstart-job',
- 'test.conf', 'blah', freq)
- h.handle_part('', handlers.CONTENT_END,
- None, None, None)
- self.assertEqual(0, len(os.listdir(up_root)))
-
- def test_upstart_frequency_single(self):
- # files should be written out when frequency is ! per-instance
- new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, new_root)
- freq = PER_INSTANCE
-
- self.patchOS(new_root)
- self.patchUtils(new_root)
- paths = helpers.Paths({
- 'upstart_dir': "/etc/upstart",
- })
-
- upstart_job.SUITABLE_UPSTART = True
- util.ensure_dir("/run")
- util.ensure_dir("/etc/upstart")
-
- with mock.patch.object(util, 'subp') as mockobj:
- h = upstart_job.UpstartJobPartHandler(paths)
- h.handle_part('', handlers.CONTENT_START,
- None, None, None)
- h.handle_part('blah', 'text/upstart-job',
- 'test.conf', 'blah', freq)
- h.handle_part('', handlers.CONTENT_END,
- None, None, None)
-
- self.assertEqual(len(os.listdir('/etc/upstart')), 1)
-
- mockobj.assert_called_once_with(
- ['initctl', 'reload-configuration'], capture=False)
diff --git a/tests/unittests/test_cli.py b/tests/unittests/test_cli.py
deleted file mode 100644
index 5fa252f7..00000000
--- a/tests/unittests/test_cli.py
+++ /dev/null
@@ -1,34 +0,0 @@
-import six
-
-from . import helpers as test_helpers
-
-from cloudinit.cmd import main as cli
-
-mock = test_helpers.mock
-
-
-class TestCLI(test_helpers.FilesystemMockingTestCase):
-
- def setUp(self):
- super(TestCLI, self).setUp()
- self.stderr = six.StringIO()
- self.patchStdoutAndStderr(stderr=self.stderr)
-
- def _call_main(self, sysv_args=None):
- if not sysv_args:
- sysv_args = ['cloud-init']
- try:
- return cli.main(sysv_args=sysv_args)
- except SystemExit as e:
- return e.code
-
- def test_no_arguments_shows_usage(self):
- exit_code = self._call_main()
- self.assertIn('usage: cloud-init', self.stderr.getvalue())
- self.assertEqual(2, exit_code)
-
- def test_no_arguments_shows_error_message(self):
- exit_code = self._call_main()
- self.assertIn('cloud-init: error: too few arguments',
- self.stderr.getvalue())
- self.assertEqual(2, exit_code)
diff --git a/tests/unittests/test_cs_util.py b/tests/unittests/test_cs_util.py
deleted file mode 100644
index 56c9ce9e..00000000
--- a/tests/unittests/test_cs_util.py
+++ /dev/null
@@ -1,63 +0,0 @@
-from __future__ import print_function
-
-from . import helpers as test_helpers
-
-from cloudinit.cs_utils import Cepko
-
-
-SERVER_CONTEXT = {
- "cpu": 1000,
- "cpus_instead_of_cores": False,
- "global_context": {"some_global_key": "some_global_val"},
- "mem": 1073741824,
- "meta": {"ssh_public_key": "ssh-rsa AAAAB3NzaC1yc2E.../hQ5D5 john@doe"},
- "name": "test_server",
- "requirements": [],
- "smp": 1,
- "tags": ["much server", "very performance"],
- "uuid": "65b2fb23-8c03-4187-a3ba-8b7c919e889",
- "vnc_password": "9e84d6cb49e46379"
-}
-
-
-class CepkoMock(Cepko):
- def all(self):
- return SERVER_CONTEXT
-
- def get(self, key="", request_pattern=None):
- return SERVER_CONTEXT['tags']
-
-
-# 2015-01-22 BAW: This test is completely useless because it only ever tests
-# the CepkoMock object. Even in its original form, I don't think it ever
-# touched the underlying Cepko class methods.
-class CepkoResultTests(test_helpers.TestCase):
- def setUp(self):
- raise test_helpers.SkipTest('This test is completely useless')
-
- def test_getitem(self):
- result = self.c.all()
- self.assertEqual("65b2fb23-8c03-4187-a3ba-8b7c919e889", result['uuid'])
- self.assertEqual([], result['requirements'])
- self.assertEqual("much server", result['tags'][0])
- self.assertEqual(1, result['smp'])
-
- def test_len(self):
- self.assertEqual(len(SERVER_CONTEXT), len(self.c.all()))
-
- def test_contains(self):
- result = self.c.all()
- self.assertTrue('uuid' in result)
- self.assertFalse('uid' in result)
- self.assertTrue('meta' in result)
- self.assertFalse('ssh_public_key' in result)
-
- def test_iter(self):
- self.assertEqual(sorted(SERVER_CONTEXT.keys()),
- sorted([key for key in self.c.all()]))
-
- def test_with_list_as_result(self):
- result = self.c.get('tags')
- self.assertEqual('much server', result[0])
- self.assertTrue('very performance' in result)
- self.assertEqual(2, len(result))
diff --git a/tests/unittests/test_data.py b/tests/unittests/test_data.py
deleted file mode 100644
index 13db8a4c..00000000
--- a/tests/unittests/test_data.py
+++ /dev/null
@@ -1,576 +0,0 @@
-"""Tests for handling of userdata within cloud init."""
-
-import gzip
-import logging
-import os
-import shutil
-import tempfile
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-
-from six import BytesIO, StringIO
-
-from email import encoders
-from email.mime.application import MIMEApplication
-from email.mime.base import MIMEBase
-from email.mime.multipart import MIMEMultipart
-
-from cloudinit import handlers
-from cloudinit import helpers as c_helpers
-from cloudinit import log
-from cloudinit.settings import (PER_INSTANCE)
-from cloudinit import sources
-from cloudinit import stages
-from cloudinit import user_data as ud
-from cloudinit import util
-
-from . import helpers
-
-
-INSTANCE_ID = "i-testing"
-
-
-class FakeDataSource(sources.DataSource):
-
- def __init__(self, userdata=None, vendordata=None):
- sources.DataSource.__init__(self, {}, None, None)
- self.metadata = {'instance-id': INSTANCE_ID}
- self.userdata_raw = userdata
- self.vendordata_raw = vendordata
-
-
-def count_messages(root):
- am = 0
- for m in root.walk():
- if ud.is_skippable(m):
- continue
- am += 1
- return am
-
-
-def gzip_text(text):
- contents = BytesIO()
- f = gzip.GzipFile(fileobj=contents, mode='wb')
- f.write(util.encode_text(text))
- f.flush()
- f.close()
- return contents.getvalue()
-
-
-# FIXME: these tests shouldn't be checking log output??
-# Weirddddd...
-class TestConsumeUserData(helpers.FilesystemMockingTestCase):
-
- def setUp(self):
- super(TestConsumeUserData, self).setUp()
- self._log = None
- self._log_file = None
- self._log_handler = None
-
- def tearDown(self):
- if self._log_handler and self._log:
- self._log.removeHandler(self._log_handler)
- helpers.FilesystemMockingTestCase.tearDown(self)
-
- def _patchIn(self, root):
- self.patchOS(root)
- self.patchUtils(root)
-
- def capture_log(self, lvl=logging.DEBUG):
- log_file = StringIO()
- self._log_handler = logging.StreamHandler(log_file)
- self._log_handler.setLevel(lvl)
- self._log = log.getLogger()
- self._log.addHandler(self._log_handler)
- return log_file
-
- def test_simple_jsonp(self):
- blob = '''
-#cloud-config-jsonp
-[
- { "op": "add", "path": "/baz", "value": "qux" },
- { "op": "add", "path": "/bar", "value": "qux2" }
-]
-'''
-
- ci = stages.Init()
- ci.datasource = FakeDataSource(blob)
- new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, new_root)
- self.patchUtils(new_root)
- self.patchOS(new_root)
- ci.fetch()
- ci.consume_data()
- cc_contents = util.load_file(ci.paths.get_ipath("cloud_config"))
- cc = util.load_yaml(cc_contents)
- self.assertEqual(2, len(cc))
- self.assertEqual('qux', cc['baz'])
- self.assertEqual('qux2', cc['bar'])
-
- def test_simple_jsonp_vendor_and_user(self):
- # test that user-data wins over vendor
- user_blob = '''
-#cloud-config-jsonp
-[
- { "op": "add", "path": "/baz", "value": "qux" },
- { "op": "add", "path": "/bar", "value": "qux2" }
-]
-'''
- vendor_blob = '''
-#cloud-config-jsonp
-[
- { "op": "add", "path": "/baz", "value": "quxA" },
- { "op": "add", "path": "/bar", "value": "quxB" },
- { "op": "add", "path": "/foo", "value": "quxC" }
-]
-'''
- new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, new_root)
- self._patchIn(new_root)
- initer = stages.Init()
- initer.datasource = FakeDataSource(user_blob, vendordata=vendor_blob)
- initer.read_cfg()
- initer.initialize()
- initer.fetch()
- initer.instancify()
- initer.update()
- initer.cloudify().run('consume_data',
- initer.consume_data,
- args=[PER_INSTANCE],
- freq=PER_INSTANCE)
- mods = stages.Modules(initer)
- (_which_ran, _failures) = mods.run_section('cloud_init_modules')
- cfg = mods.cfg
- self.assertIn('vendor_data', cfg)
- self.assertEqual('qux', cfg['baz'])
- self.assertEqual('qux2', cfg['bar'])
- self.assertEqual('quxC', cfg['foo'])
-
- def test_simple_jsonp_no_vendor_consumed(self):
- # make sure that vendor data is not consumed
- user_blob = '''
-#cloud-config-jsonp
-[
- { "op": "add", "path": "/baz", "value": "qux" },
- { "op": "add", "path": "/bar", "value": "qux2" },
- { "op": "add", "path": "/vendor_data", "value": {"enabled": "false"}}
-]
-'''
- vendor_blob = '''
-#cloud-config-jsonp
-[
- { "op": "add", "path": "/baz", "value": "quxA" },
- { "op": "add", "path": "/bar", "value": "quxB" },
- { "op": "add", "path": "/foo", "value": "quxC" }
-]
-'''
- new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, new_root)
- self._patchIn(new_root)
- initer = stages.Init()
- initer.datasource = FakeDataSource(user_blob, vendordata=vendor_blob)
- initer.read_cfg()
- initer.initialize()
- initer.fetch()
- initer.instancify()
- initer.update()
- initer.cloudify().run('consume_data',
- initer.consume_data,
- args=[PER_INSTANCE],
- freq=PER_INSTANCE)
- mods = stages.Modules(initer)
- (_which_ran, _failures) = mods.run_section('cloud_init_modules')
- cfg = mods.cfg
- self.assertEqual('qux', cfg['baz'])
- self.assertEqual('qux2', cfg['bar'])
- self.assertNotIn('foo', cfg)
-
- def test_mixed_cloud_config(self):
- blob_cc = '''
-#cloud-config
-a: b
-c: d
-'''
- message_cc = MIMEBase("text", "cloud-config")
- message_cc.set_payload(blob_cc)
-
- blob_jp = '''
-#cloud-config-jsonp
-[
- { "op": "replace", "path": "/a", "value": "c" },
- { "op": "remove", "path": "/c" }
-]
-'''
-
- message_jp = MIMEBase('text', "cloud-config-jsonp")
- message_jp.set_payload(blob_jp)
-
- message = MIMEMultipart()
- message.attach(message_cc)
- message.attach(message_jp)
-
- ci = stages.Init()
- ci.datasource = FakeDataSource(str(message))
- new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, new_root)
- self.patchUtils(new_root)
- self.patchOS(new_root)
- ci.fetch()
- ci.consume_data()
- cc_contents = util.load_file(ci.paths.get_ipath("cloud_config"))
- cc = util.load_yaml(cc_contents)
- self.assertEqual(1, len(cc))
- self.assertEqual('c', cc['a'])
-
- def test_vendor_user_yaml_cloud_config(self):
- vendor_blob = '''
-#cloud-config
-a: b
-name: vendor
-run:
- - x
- - y
-'''
-
- user_blob = '''
-#cloud-config
-a: c
-vendor_data:
- enabled: True
- prefix: /bin/true
-name: user
-run:
- - z
-'''
- new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, new_root)
- self._patchIn(new_root)
- initer = stages.Init()
- initer.datasource = FakeDataSource(user_blob, vendordata=vendor_blob)
- initer.read_cfg()
- initer.initialize()
- initer.fetch()
- initer.instancify()
- initer.update()
- initer.cloudify().run('consume_data',
- initer.consume_data,
- args=[PER_INSTANCE],
- freq=PER_INSTANCE)
- mods = stages.Modules(initer)
- (_which_ran, _failures) = mods.run_section('cloud_init_modules')
- cfg = mods.cfg
- self.assertIn('vendor_data', cfg)
- self.assertEqual('c', cfg['a'])
- self.assertEqual('user', cfg['name'])
- self.assertNotIn('x', cfg['run'])
- self.assertNotIn('y', cfg['run'])
- self.assertIn('z', cfg['run'])
-
- def test_vendordata_script(self):
- vendor_blob = '''
-#!/bin/bash
-echo "test"
-'''
-
- user_blob = '''
-#cloud-config
-vendor_data:
- enabled: True
- prefix: /bin/true
-'''
- new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, new_root)
- self._patchIn(new_root)
- initer = stages.Init()
- initer.datasource = FakeDataSource(user_blob, vendordata=vendor_blob)
- initer.read_cfg()
- initer.initialize()
- initer.fetch()
- initer.instancify()
- initer.update()
- initer.cloudify().run('consume_data',
- initer.consume_data,
- args=[PER_INSTANCE],
- freq=PER_INSTANCE)
- mods = stages.Modules(initer)
- (_which_ran, _failures) = mods.run_section('cloud_init_modules')
- vendor_script = initer.paths.get_ipath_cur('vendor_scripts')
- vendor_script_fns = "%s%s/part-001" % (new_root, vendor_script)
- self.assertTrue(os.path.exists(vendor_script_fns))
-
- def test_merging_cloud_config(self):
- blob = '''
-#cloud-config
-a: b
-e: f
-run:
- - b
- - c
-'''
- message1 = MIMEBase("text", "cloud-config")
- message1.set_payload(blob)
-
- blob2 = '''
-#cloud-config
-a: e
-e: g
-run:
- - stuff
- - morestuff
-'''
- message2 = MIMEBase("text", "cloud-config")
- message2['X-Merge-Type'] = ('dict(recurse_array,'
- 'recurse_str)+list(append)+str(append)')
- message2.set_payload(blob2)
-
- blob3 = '''
-#cloud-config
-e:
- - 1
- - 2
- - 3
-p: 1
-'''
- message3 = MIMEBase("text", "cloud-config")
- message3.set_payload(blob3)
-
- messages = [message1, message2, message3]
-
- paths = c_helpers.Paths({}, ds=FakeDataSource(''))
- cloud_cfg = handlers.cloud_config.CloudConfigPartHandler(paths)
-
- new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, new_root)
- self.patchUtils(new_root)
- self.patchOS(new_root)
- cloud_cfg.handle_part(None, handlers.CONTENT_START, None, None, None,
- None)
- for i, m in enumerate(messages):
- headers = dict(m)
- fn = "part-%s" % (i + 1)
- payload = m.get_payload(decode=True)
- cloud_cfg.handle_part(None, headers['Content-Type'],
- fn, payload, None, headers)
- cloud_cfg.handle_part(None, handlers.CONTENT_END, None, None, None,
- None)
- contents = util.load_file(paths.get_ipath('cloud_config'))
- contents = util.load_yaml(contents)
- self.assertEqual(contents['run'], ['b', 'c', 'stuff', 'morestuff'])
- self.assertEqual(contents['a'], 'be')
- self.assertEqual(contents['e'], [1, 2, 3])
- self.assertEqual(contents['p'], 1)
-
- def test_unhandled_type_warning(self):
- """Raw text without magic is ignored but shows warning."""
- ci = stages.Init()
- data = "arbitrary text\n"
- ci.datasource = FakeDataSource(data)
-
- with mock.patch('cloudinit.util.write_file') as mockobj:
- log_file = self.capture_log(logging.WARNING)
- ci.fetch()
- ci.consume_data()
- self.assertIn(
- "Unhandled non-multipart (text/x-not-multipart) userdata:",
- log_file.getvalue())
-
- mockobj.assert_called_once_with(
- ci.paths.get_ipath("cloud_config"), "", 0o600)
-
- def test_mime_gzip_compressed(self):
- """Tests that individual message gzip encoding works."""
-
- def gzip_part(text):
- return MIMEApplication(gzip_text(text), 'gzip')
-
- base_content1 = '''
-#cloud-config
-a: 2
-'''
-
- base_content2 = '''
-#cloud-config
-b: 3
-c: 4
-'''
-
- message = MIMEMultipart('test')
- message.attach(gzip_part(base_content1))
- message.attach(gzip_part(base_content2))
- ci = stages.Init()
- ci.datasource = FakeDataSource(str(message))
- new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, new_root)
- self.patchUtils(new_root)
- self.patchOS(new_root)
- ci.fetch()
- ci.consume_data()
- contents = util.load_file(ci.paths.get_ipath("cloud_config"))
- contents = util.load_yaml(contents)
- self.assertTrue(isinstance(contents, dict))
- self.assertEqual(3, len(contents))
- self.assertEqual(2, contents['a'])
- self.assertEqual(3, contents['b'])
- self.assertEqual(4, contents['c'])
-
- def test_mime_text_plain(self):
- """Mime message of type text/plain is ignored but shows warning."""
- ci = stages.Init()
- message = MIMEBase("text", "plain")
- message.set_payload("Just text")
- ci.datasource = FakeDataSource(message.as_string().encode())
-
- with mock.patch('cloudinit.util.write_file') as mockobj:
- log_file = self.capture_log(logging.WARNING)
- ci.fetch()
- ci.consume_data()
- self.assertIn(
- "Unhandled unknown content-type (text/plain)",
- log_file.getvalue())
- mockobj.assert_called_once_with(
- ci.paths.get_ipath("cloud_config"), "", 0o600)
-
- def test_shellscript(self):
- """Raw text starting #!/bin/sh is treated as script."""
- ci = stages.Init()
- script = "#!/bin/sh\necho hello\n"
- ci.datasource = FakeDataSource(script)
-
- outpath = os.path.join(ci.paths.get_ipath_cur("scripts"), "part-001")
-
- with mock.patch('cloudinit.util.write_file') as mockobj:
- log_file = self.capture_log(logging.WARNING)
- ci.fetch()
- ci.consume_data()
- self.assertEqual("", log_file.getvalue())
-
- mockobj.assert_has_calls([
- mock.call(outpath, script, 0o700),
- mock.call(ci.paths.get_ipath("cloud_config"), "", 0o600)])
-
- def test_mime_text_x_shellscript(self):
- """Mime message of type text/x-shellscript is treated as script."""
- ci = stages.Init()
- script = "#!/bin/sh\necho hello\n"
- message = MIMEBase("text", "x-shellscript")
- message.set_payload(script)
- ci.datasource = FakeDataSource(message.as_string())
-
- outpath = os.path.join(ci.paths.get_ipath_cur("scripts"), "part-001")
-
- with mock.patch('cloudinit.util.write_file') as mockobj:
- log_file = self.capture_log(logging.WARNING)
- ci.fetch()
- ci.consume_data()
- self.assertEqual("", log_file.getvalue())
-
- mockobj.assert_has_calls([
- mock.call(outpath, script, 0o700),
- mock.call(ci.paths.get_ipath("cloud_config"), "", 0o600)])
-
- def test_mime_text_plain_shell(self):
- """Mime type text/plain starting #!/bin/sh is treated as script."""
- ci = stages.Init()
- script = "#!/bin/sh\necho hello\n"
- message = MIMEBase("text", "plain")
- message.set_payload(script)
- ci.datasource = FakeDataSource(message.as_string())
-
- outpath = os.path.join(ci.paths.get_ipath_cur("scripts"), "part-001")
-
- with mock.patch('cloudinit.util.write_file') as mockobj:
- log_file = self.capture_log(logging.WARNING)
- ci.fetch()
- ci.consume_data()
- self.assertEqual("", log_file.getvalue())
-
- mockobj.assert_has_calls([
- mock.call(outpath, script, 0o700),
- mock.call(ci.paths.get_ipath("cloud_config"), "", 0o600)])
-
- def test_mime_application_octet_stream(self):
- """Mime type application/octet-stream is ignored but shows warning."""
- ci = stages.Init()
- message = MIMEBase("application", "octet-stream")
- message.set_payload(b'\xbf\xe6\xb2\xc3\xd3\xba\x13\xa4\xd8\xa1\xcc')
- encoders.encode_base64(message)
- ci.datasource = FakeDataSource(message.as_string().encode())
-
- with mock.patch('cloudinit.util.write_file') as mockobj:
- log_file = self.capture_log(logging.WARNING)
- ci.fetch()
- ci.consume_data()
- self.assertIn(
- "Unhandled unknown content-type (application/octet-stream)",
- log_file.getvalue())
- mockobj.assert_called_once_with(
- ci.paths.get_ipath("cloud_config"), "", 0o600)
-
- def test_cloud_config_archive(self):
- non_decodable = b'\x11\xc9\xb4gTH\xee\x12'
- data = [{'content': '#cloud-config\npassword: gocubs\n'},
- {'content': '#cloud-config\nlocale: chicago\n'},
- {'content': non_decodable}]
- message = b'#cloud-config-archive\n' + util.yaml_dumps(data).encode()
-
- ci = stages.Init()
- ci.datasource = FakeDataSource(message)
-
- fs = {}
-
- def fsstore(filename, content, mode=0o0644, omode="wb"):
- fs[filename] = content
-
- # consuming the user-data provided should write 'cloud_config' file
- # which will have our yaml in it.
- with mock.patch('cloudinit.util.write_file') as mockobj:
- mockobj.side_effect = fsstore
- ci.fetch()
- ci.consume_data()
-
- cfg = util.load_yaml(fs[ci.paths.get_ipath("cloud_config")])
- self.assertEqual(cfg.get('password'), 'gocubs')
- self.assertEqual(cfg.get('locale'), 'chicago')
-
-
-class TestUDProcess(helpers.ResourceUsingTestCase):
-
- def test_bytes_in_userdata(self):
- msg = b'#cloud-config\napt_update: True\n'
- ud_proc = ud.UserDataProcessor(self.getCloudPaths())
- message = ud_proc.process(msg)
- self.assertTrue(count_messages(message) == 1)
-
- def test_string_in_userdata(self):
- msg = '#cloud-config\napt_update: True\n'
-
- ud_proc = ud.UserDataProcessor(self.getCloudPaths())
- message = ud_proc.process(msg)
- self.assertTrue(count_messages(message) == 1)
-
- def test_compressed_in_userdata(self):
- msg = gzip_text('#cloud-config\napt_update: True\n')
-
- ud_proc = ud.UserDataProcessor(self.getCloudPaths())
- message = ud_proc.process(msg)
- self.assertTrue(count_messages(message) == 1)
-
-
-class TestConvertString(helpers.TestCase):
- def test_handles_binary_non_utf8_decodable(self):
- blob = b'\x32\x99'
- msg = ud.convert_string(blob)
- self.assertEqual(blob, msg.get_payload(decode=True))
-
- def test_handles_binary_utf8_decodable(self):
- blob = b'\x32\x32'
- msg = ud.convert_string(blob)
- self.assertEqual(blob, msg.get_payload(decode=True))
-
- def test_handle_headers(self):
- text = "hi mom"
- msg = ud.convert_string(text)
- self.assertEqual(text, msg.get_payload(decode=False))
diff --git a/tests/unittests/test_datasource/__init__.py b/tests/unittests/test_datasource/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/unittests/test_datasource/__init__.py
+++ /dev/null
diff --git a/tests/unittests/test_datasource/test_altcloud.py b/tests/unittests/test_datasource/test_altcloud.py
deleted file mode 100644
index 12966563..00000000
--- a/tests/unittests/test_datasource/test_altcloud.py
+++ /dev/null
@@ -1,452 +0,0 @@
-# vi: ts=4 expandtab
-#
-# Copyright (C) 2009-2010 Canonical Ltd.
-# Copyright (C) 2012 Hewlett-Packard Development Company, L.P.
-# Copyright (C) 2012 Yahoo! Inc.
-#
-# Author: Joe VLcek <JVLcek@RedHat.com>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 3, as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-'''
-This test file exercises the code in sources DataSourceAltCloud.py
-'''
-
-import os
-import shutil
-import tempfile
-
-from cloudinit import helpers
-from cloudinit import util
-from unittest import TestCase
-
-# Get the cloudinit.sources.DataSourceAltCloud import items needed.
-import cloudinit.sources.DataSourceAltCloud
-from cloudinit.sources.DataSourceAltCloud import DataSourceAltCloud
-from cloudinit.sources.DataSourceAltCloud import read_user_data_callback
-
-OS_UNAME_ORIG = getattr(os, 'uname')
-
-
-def _write_cloud_info_file(value):
- '''
- Populate the CLOUD_INFO_FILE which would be populated
- with a cloud backend identifier ImageFactory when building
- an image with ImageFactory.
- '''
- cifile = open(cloudinit.sources.DataSourceAltCloud.CLOUD_INFO_FILE, 'w')
- cifile.write(value)
- cifile.close()
- os.chmod(cloudinit.sources.DataSourceAltCloud.CLOUD_INFO_FILE, 0o664)
-
-
-def _remove_cloud_info_file():
- '''
- Remove the test CLOUD_INFO_FILE
- '''
- os.remove(cloudinit.sources.DataSourceAltCloud.CLOUD_INFO_FILE)
-
-
-def _write_user_data_files(mount_dir, value):
- '''
- Populate the deltacloud_user_data_file the user_data_file
- which would be populated with user data.
- '''
- deltacloud_user_data_file = mount_dir + '/deltacloud-user-data.txt'
- user_data_file = mount_dir + '/user-data.txt'
-
- udfile = open(deltacloud_user_data_file, 'w')
- udfile.write(value)
- udfile.close()
- os.chmod(deltacloud_user_data_file, 0o664)
-
- udfile = open(user_data_file, 'w')
- udfile.write(value)
- udfile.close()
- os.chmod(user_data_file, 0o664)
-
-
-def _remove_user_data_files(mount_dir,
- dc_file=True,
- non_dc_file=True):
- '''
- Remove the test files: deltacloud_user_data_file and
- user_data_file
- '''
- deltacloud_user_data_file = mount_dir + '/deltacloud-user-data.txt'
- user_data_file = mount_dir + '/user-data.txt'
-
- # Ignore any failures removeing files that are already gone.
- if dc_file:
- try:
- os.remove(deltacloud_user_data_file)
- except OSError:
- pass
-
- if non_dc_file:
- try:
- os.remove(user_data_file)
- except OSError:
- pass
-
-
-def _dmi_data(expected):
- '''
- Spoof the data received over DMI
- '''
- def _data(key):
- return expected
-
- return _data
-
-
-class TestGetCloudType(TestCase):
- '''
- Test to exercise method: DataSourceAltCloud.get_cloud_type()
- '''
-
- def setUp(self):
- '''Set up.'''
- self.paths = helpers.Paths({'cloud_dir': '/tmp'})
- self.dmi_data = util.read_dmi_data
- # We have a different code path for arm to deal with LP1243287
- # We have to switch arch to x86_64 to avoid test failure
- force_arch('x86_64')
-
- def tearDown(self):
- # Reset
- util.read_dmi_data = self.dmi_data
- force_arch()
-
- def test_rhev(self):
- '''
- Test method get_cloud_type() for RHEVm systems.
- Forcing read_dmi_data return to match a RHEVm system: RHEV Hypervisor
- '''
- util.read_dmi_data = _dmi_data('RHEV')
- dsrc = DataSourceAltCloud({}, None, self.paths)
- self.assertEqual('RHEV', dsrc.get_cloud_type())
-
- def test_vsphere(self):
- '''
- Test method get_cloud_type() for vSphere systems.
- Forcing read_dmi_data return to match a vSphere system: RHEV Hypervisor
- '''
- util.read_dmi_data = _dmi_data('VMware Virtual Platform')
- dsrc = DataSourceAltCloud({}, None, self.paths)
- self.assertEqual('VSPHERE', dsrc.get_cloud_type())
-
- def test_unknown(self):
- '''
- Test method get_cloud_type() for unknown systems.
- Forcing read_dmi_data return to match an unrecognized return.
- '''
- util.read_dmi_data = _dmi_data('Unrecognized Platform')
- dsrc = DataSourceAltCloud({}, None, self.paths)
- self.assertEqual('UNKNOWN', dsrc.get_cloud_type())
-
-
-class TestGetDataCloudInfoFile(TestCase):
- '''
- Test to exercise method: DataSourceAltCloud.get_data()
- With a contrived CLOUD_INFO_FILE
- '''
- def setUp(self):
- '''Set up.'''
- self.paths = helpers.Paths({'cloud_dir': '/tmp'})
- self.cloud_info_file = tempfile.mkstemp()[1]
- self.dmi_data = util.read_dmi_data
- cloudinit.sources.DataSourceAltCloud.CLOUD_INFO_FILE = \
- self.cloud_info_file
-
- def tearDown(self):
- # Reset
-
- # Attempt to remove the temp file ignoring errors
- try:
- os.remove(self.cloud_info_file)
- except OSError:
- pass
-
- util.read_dmi_data = self.dmi_data
- cloudinit.sources.DataSourceAltCloud.CLOUD_INFO_FILE = \
- '/etc/sysconfig/cloud-info'
-
- def test_rhev(self):
- '''Success Test module get_data() forcing RHEV.'''
-
- _write_cloud_info_file('RHEV')
- dsrc = DataSourceAltCloud({}, None, self.paths)
- dsrc.user_data_rhevm = lambda: True
- self.assertEqual(True, dsrc.get_data())
-
- def test_vsphere(self):
- '''Success Test module get_data() forcing VSPHERE.'''
-
- _write_cloud_info_file('VSPHERE')
- dsrc = DataSourceAltCloud({}, None, self.paths)
- dsrc.user_data_vsphere = lambda: True
- self.assertEqual(True, dsrc.get_data())
-
- def test_fail_rhev(self):
- '''Failure Test module get_data() forcing RHEV.'''
-
- _write_cloud_info_file('RHEV')
- dsrc = DataSourceAltCloud({}, None, self.paths)
- dsrc.user_data_rhevm = lambda: False
- self.assertEqual(False, dsrc.get_data())
-
- def test_fail_vsphere(self):
- '''Failure Test module get_data() forcing VSPHERE.'''
-
- _write_cloud_info_file('VSPHERE')
- dsrc = DataSourceAltCloud({}, None, self.paths)
- dsrc.user_data_vsphere = lambda: False
- self.assertEqual(False, dsrc.get_data())
-
- def test_unrecognized(self):
- '''Failure Test module get_data() forcing unrecognized.'''
-
- _write_cloud_info_file('unrecognized')
- dsrc = DataSourceAltCloud({}, None, self.paths)
- self.assertEqual(False, dsrc.get_data())
-
-
-class TestGetDataNoCloudInfoFile(TestCase):
- '''
- Test to exercise method: DataSourceAltCloud.get_data()
- Without a CLOUD_INFO_FILE
- '''
- def setUp(self):
- '''Set up.'''
- self.paths = helpers.Paths({'cloud_dir': '/tmp'})
- self.dmi_data = util.read_dmi_data
- cloudinit.sources.DataSourceAltCloud.CLOUD_INFO_FILE = \
- 'no such file'
- # We have a different code path for arm to deal with LP1243287
- # We have to switch arch to x86_64 to avoid test failure
- force_arch('x86_64')
-
- def tearDown(self):
- # Reset
- cloudinit.sources.DataSourceAltCloud.CLOUD_INFO_FILE = \
- '/etc/sysconfig/cloud-info'
- util.read_dmi_data = self.dmi_data
- # Return back to original arch
- force_arch()
-
- def test_rhev_no_cloud_file(self):
- '''Test No cloud info file module get_data() forcing RHEV.'''
-
- util.read_dmi_data = _dmi_data('RHEV Hypervisor')
- dsrc = DataSourceAltCloud({}, None, self.paths)
- dsrc.user_data_rhevm = lambda: True
- self.assertEqual(True, dsrc.get_data())
-
- def test_vsphere_no_cloud_file(self):
- '''Test No cloud info file module get_data() forcing VSPHERE.'''
-
- util.read_dmi_data = _dmi_data('VMware Virtual Platform')
- dsrc = DataSourceAltCloud({}, None, self.paths)
- dsrc.user_data_vsphere = lambda: True
- self.assertEqual(True, dsrc.get_data())
-
- def test_failure_no_cloud_file(self):
- '''Test No cloud info file module get_data() forcing unrecognized.'''
-
- util.read_dmi_data = _dmi_data('Unrecognized Platform')
- dsrc = DataSourceAltCloud({}, None, self.paths)
- self.assertEqual(False, dsrc.get_data())
-
-
-class TestUserDataRhevm(TestCase):
- '''
- Test to exercise method: DataSourceAltCloud.user_data_rhevm()
- '''
- def setUp(self):
- '''Set up.'''
- self.paths = helpers.Paths({'cloud_dir': '/tmp'})
- self.mount_dir = tempfile.mkdtemp()
-
- _write_user_data_files(self.mount_dir, 'test user data')
-
- def tearDown(self):
- # Reset
-
- _remove_user_data_files(self.mount_dir)
-
- # Attempt to remove the temp dir ignoring errors
- try:
- shutil.rmtree(self.mount_dir)
- except OSError:
- pass
-
- cloudinit.sources.DataSourceAltCloud.CLOUD_INFO_FILE = \
- '/etc/sysconfig/cloud-info'
- cloudinit.sources.DataSourceAltCloud.CMD_PROBE_FLOPPY = \
- ['/sbin/modprobe', 'floppy']
- cloudinit.sources.DataSourceAltCloud.CMD_UDEVADM_SETTLE = \
- ['/sbin/udevadm', 'settle', '--quiet', '--timeout=5']
-
- def test_mount_cb_fails(self):
- '''Test user_data_rhevm() where mount_cb fails.'''
-
- cloudinit.sources.DataSourceAltCloud.CMD_PROBE_FLOPPY = \
- ['echo', 'modprobe floppy']
-
- dsrc = DataSourceAltCloud({}, None, self.paths)
-
- self.assertEqual(False, dsrc.user_data_rhevm())
-
- def test_modprobe_fails(self):
- '''Test user_data_rhevm() where modprobe fails.'''
-
- cloudinit.sources.DataSourceAltCloud.CMD_PROBE_FLOPPY = \
- ['ls', 'modprobe floppy']
-
- dsrc = DataSourceAltCloud({}, None, self.paths)
-
- self.assertEqual(False, dsrc.user_data_rhevm())
-
- def test_no_modprobe_cmd(self):
- '''Test user_data_rhevm() with no modprobe command.'''
-
- cloudinit.sources.DataSourceAltCloud.CMD_PROBE_FLOPPY = \
- ['bad command', 'modprobe floppy']
-
- dsrc = DataSourceAltCloud({}, None, self.paths)
-
- self.assertEqual(False, dsrc.user_data_rhevm())
-
- def test_udevadm_fails(self):
- '''Test user_data_rhevm() where udevadm fails.'''
-
- cloudinit.sources.DataSourceAltCloud.CMD_UDEVADM_SETTLE = \
- ['ls', 'udevadm floppy']
-
- dsrc = DataSourceAltCloud({}, None, self.paths)
-
- self.assertEqual(False, dsrc.user_data_rhevm())
-
- def test_no_udevadm_cmd(self):
- '''Test user_data_rhevm() with no udevadm command.'''
-
- cloudinit.sources.DataSourceAltCloud.CMD_UDEVADM_SETTLE = \
- ['bad command', 'udevadm floppy']
-
- dsrc = DataSourceAltCloud({}, None, self.paths)
-
- self.assertEqual(False, dsrc.user_data_rhevm())
-
-
-class TestUserDataVsphere(TestCase):
- '''
- Test to exercise method: DataSourceAltCloud.user_data_vsphere()
- '''
- def setUp(self):
- '''Set up.'''
- self.paths = helpers.Paths({'cloud_dir': '/tmp'})
- self.mount_dir = tempfile.mkdtemp()
-
- _write_user_data_files(self.mount_dir, 'test user data')
-
- def tearDown(self):
- # Reset
-
- _remove_user_data_files(self.mount_dir)
-
- # Attempt to remove the temp dir ignoring errors
- try:
- shutil.rmtree(self.mount_dir)
- except OSError:
- pass
-
- cloudinit.sources.DataSourceAltCloud.CLOUD_INFO_FILE = \
- '/etc/sysconfig/cloud-info'
-
- def test_user_data_vsphere(self):
- '''Test user_data_vsphere() where mount_cb fails.'''
-
- cloudinit.sources.DataSourceAltCloud.MEDIA_DIR = self.mount_dir
-
- dsrc = DataSourceAltCloud({}, None, self.paths)
-
- self.assertEqual(False, dsrc.user_data_vsphere())
-
-
-class TestReadUserDataCallback(TestCase):
- '''
- Test to exercise method: DataSourceAltCloud.read_user_data_callback()
- '''
- def setUp(self):
- '''Set up.'''
- self.paths = helpers.Paths({'cloud_dir': '/tmp'})
- self.mount_dir = tempfile.mkdtemp()
-
- _write_user_data_files(self.mount_dir, 'test user data')
-
- def tearDown(self):
- # Reset
-
- _remove_user_data_files(self.mount_dir)
-
- # Attempt to remove the temp dir ignoring errors
- try:
- shutil.rmtree(self.mount_dir)
- except OSError:
- pass
-
- def test_callback_both(self):
- '''Test read_user_data_callback() with both files.'''
-
- self.assertEqual('test user data',
- read_user_data_callback(self.mount_dir))
-
- def test_callback_dc(self):
- '''Test read_user_data_callback() with only DC file.'''
-
- _remove_user_data_files(self.mount_dir,
- dc_file=False,
- non_dc_file=True)
-
- self.assertEqual('test user data',
- read_user_data_callback(self.mount_dir))
-
- def test_callback_non_dc(self):
- '''Test read_user_data_callback() with only non-DC file.'''
-
- _remove_user_data_files(self.mount_dir,
- dc_file=True,
- non_dc_file=False)
-
- self.assertEqual('test user data',
- read_user_data_callback(self.mount_dir))
-
- def test_callback_none(self):
- '''Test read_user_data_callback() no files are found.'''
-
- _remove_user_data_files(self.mount_dir)
- self.assertEqual(None, read_user_data_callback(self.mount_dir))
-
-
-def force_arch(arch=None):
-
- def _os_uname():
- return ('LINUX', 'NODENAME', 'RELEASE', 'VERSION', arch)
-
- if arch:
- setattr(os, 'uname', _os_uname)
- elif arch is None:
- setattr(os, 'uname', OS_UNAME_ORIG)
-
-
-# vi: ts=4 expandtab
diff --git a/tests/unittests/test_datasource/test_azure.py b/tests/unittests/test_datasource/test_azure.py
deleted file mode 100644
index e90e903c..00000000
--- a/tests/unittests/test_datasource/test_azure.py
+++ /dev/null
@@ -1,640 +0,0 @@
-from cloudinit import helpers
-from cloudinit.util import b64e, decode_binary, load_file
-from cloudinit.sources import DataSourceAzure
-
-from ..helpers import TestCase, populate_dir, mock, ExitStack, PY26, SkipTest
-
-import crypt
-import os
-import shutil
-import stat
-import tempfile
-import xml.etree.ElementTree as ET
-import yaml
-
-
-def construct_valid_ovf_env(data=None, pubkeys=None, userdata=None):
- if data is None:
- data = {'HostName': 'FOOHOST'}
- if pubkeys is None:
- pubkeys = {}
-
- content = """<?xml version="1.0" encoding="utf-8"?>
-<Environment xmlns="http://schemas.dmtf.org/ovf/environment/1"
- xmlns:oe="http://schemas.dmtf.org/ovf/environment/1"
- xmlns:wa="http://schemas.microsoft.com/windowsazure"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-
- <wa:ProvisioningSection><wa:Version>1.0</wa:Version>
- <LinuxProvisioningConfigurationSet
- xmlns="http://schemas.microsoft.com/windowsazure"
- xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
- <ConfigurationSetType>LinuxProvisioningConfiguration</ConfigurationSetType>
- """
- for key, dval in data.items():
- if isinstance(dval, dict):
- val = dval.get('text')
- attrs = ' ' + ' '.join(["%s='%s'" % (k, v) for k, v in dval.items()
- if k != 'text'])
- else:
- val = dval
- attrs = ""
- content += "<%s%s>%s</%s>\n" % (key, attrs, val, key)
-
- if userdata:
- content += "<UserData>%s</UserData>\n" % (b64e(userdata))
-
- if pubkeys:
- content += "<SSH><PublicKeys>\n"
- for fp, path, value in pubkeys:
- content += " <PublicKey>"
- if fp and path:
- content += ("<Fingerprint>%s</Fingerprint><Path>%s</Path>" %
- (fp, path))
- if value:
- content += "<Value>%s</Value>" % value
- content += "</PublicKey>\n"
- content += "</PublicKeys></SSH>"
- content += """
- </LinuxProvisioningConfigurationSet>
- </wa:ProvisioningSection>
- <wa:PlatformSettingsSection><wa:Version>1.0</wa:Version>
- <PlatformSettings xmlns="http://schemas.microsoft.com/windowsazure"
- xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
- <KmsServerHostname>kms.core.windows.net</KmsServerHostname>
- <ProvisionGuestAgent>false</ProvisionGuestAgent>
- <GuestAgentPackageName i:nil="true" />
- </PlatformSettings></wa:PlatformSettingsSection>
-</Environment>
- """
-
- return content
-
-
-class TestAzureDataSource(TestCase):
-
- def setUp(self):
- super(TestAzureDataSource, self).setUp()
- if PY26:
- raise SkipTest("Does not work on python 2.6")
- self.tmp = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp)
-
- # patch cloud_dir, so our 'seed_dir' is guaranteed empty
- self.paths = helpers.Paths({'cloud_dir': self.tmp})
- self.waagent_d = os.path.join(self.tmp, 'var', 'lib', 'waagent')
-
- self.patches = ExitStack()
- self.addCleanup(self.patches.close)
-
- super(TestAzureDataSource, self).setUp()
-
- def apply_patches(self, patches):
- for module, name, new in patches:
- self.patches.enter_context(mock.patch.object(module, name, new))
-
- def _get_ds(self, data):
-
- def dsdevs():
- return data.get('dsdevs', [])
-
- def _invoke_agent(cmd):
- data['agent_invoked'] = cmd
-
- def _wait_for_files(flist, _maxwait=None, _naplen=None):
- data['waited'] = flist
- return []
-
- def _pubkeys_from_crt_files(flist):
- data['pubkey_files'] = flist
- return ["pubkey_from: %s" % f for f in flist]
-
- if data.get('ovfcontent') is not None:
- populate_dir(os.path.join(self.paths.seed_dir, "azure"),
- {'ovf-env.xml': data['ovfcontent']})
-
- mod = DataSourceAzure
- mod.BUILTIN_DS_CONFIG['data_dir'] = self.waagent_d
-
- self.get_metadata_from_fabric = mock.MagicMock(return_value={
- 'public-keys': [],
- })
-
- self.instance_id = 'test-instance-id'
-
- self.apply_patches([
- (mod, 'list_possible_azure_ds_devs', dsdevs),
- (mod, 'invoke_agent', _invoke_agent),
- (mod, 'wait_for_files', _wait_for_files),
- (mod, 'pubkeys_from_crt_files', _pubkeys_from_crt_files),
- (mod, 'perform_hostname_bounce', mock.MagicMock()),
- (mod, 'get_hostname', mock.MagicMock()),
- (mod, 'set_hostname', mock.MagicMock()),
- (mod, 'get_metadata_from_fabric', self.get_metadata_from_fabric),
- (mod.util, 'read_dmi_data', mock.MagicMock(
- return_value=self.instance_id)),
- ])
-
- dsrc = mod.DataSourceAzureNet(
- data.get('sys_cfg', {}), distro=None, paths=self.paths)
-
- return dsrc
-
- def xml_equals(self, oxml, nxml):
- """Compare two sets of XML to make sure they are equal"""
-
- def create_tag_index(xml):
- et = ET.fromstring(xml)
- ret = {}
- for x in et.iter():
- ret[x.tag] = x
- return ret
-
- def tags_exists(x, y):
- for tag in x.keys():
- self.assertIn(tag, y)
- for tag in y.keys():
- self.assertIn(tag, x)
-
- def tags_equal(x, y):
- for x_tag, x_val in x.items():
- y_val = y.get(x_val.tag)
- self.assertEqual(x_val.text, y_val.text)
-
- old_cnt = create_tag_index(oxml)
- new_cnt = create_tag_index(nxml)
- tags_exists(old_cnt, new_cnt)
- tags_equal(old_cnt, new_cnt)
-
- def xml_notequals(self, oxml, nxml):
- try:
- self.xml_equals(oxml, nxml)
- except AssertionError:
- return
- raise AssertionError("XML is the same")
-
- def test_basic_seed_dir(self):
- odata = {'HostName': "myhost", 'UserName': "myuser"}
- data = {'ovfcontent': construct_valid_ovf_env(data=odata),
- 'sys_cfg': {}}
-
- dsrc = self._get_ds(data)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertEqual(dsrc.userdata_raw, "")
- self.assertEqual(dsrc.metadata['local-hostname'], odata['HostName'])
- self.assertTrue(os.path.isfile(
- os.path.join(self.waagent_d, 'ovf-env.xml')))
-
- def test_waagent_d_has_0700_perms(self):
- # we expect /var/lib/waagent to be created 0700
- dsrc = self._get_ds({'ovfcontent': construct_valid_ovf_env()})
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertTrue(os.path.isdir(self.waagent_d))
- self.assertEqual(stat.S_IMODE(os.stat(self.waagent_d).st_mode), 0o700)
-
- def test_user_cfg_set_agent_command_plain(self):
- # set dscfg in via plaintext
- # we must have friendly-to-xml formatted plaintext in yaml_cfg
- # not all plaintext is expected to work.
- yaml_cfg = "{agent_command: my_command}\n"
- cfg = yaml.safe_load(yaml_cfg)
- odata = {'HostName': "myhost", 'UserName': "myuser",
- 'dscfg': {'text': yaml_cfg, 'encoding': 'plain'}}
- data = {'ovfcontent': construct_valid_ovf_env(data=odata)}
-
- dsrc = self._get_ds(data)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertEqual(data['agent_invoked'], cfg['agent_command'])
-
- def test_user_cfg_set_agent_command(self):
- # set dscfg in via base64 encoded yaml
- cfg = {'agent_command': "my_command"}
- odata = {'HostName': "myhost", 'UserName': "myuser",
- 'dscfg': {'text': b64e(yaml.dump(cfg)),
- 'encoding': 'base64'}}
- data = {'ovfcontent': construct_valid_ovf_env(data=odata)}
-
- dsrc = self._get_ds(data)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertEqual(data['agent_invoked'], cfg['agent_command'])
-
- def test_sys_cfg_set_agent_command(self):
- sys_cfg = {'datasource': {'Azure': {'agent_command': '_COMMAND'}}}
- data = {'ovfcontent': construct_valid_ovf_env(data={}),
- 'sys_cfg': sys_cfg}
-
- dsrc = self._get_ds(data)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertEqual(data['agent_invoked'], '_COMMAND')
-
- def test_username_used(self):
- odata = {'HostName': "myhost", 'UserName': "myuser"}
- data = {'ovfcontent': construct_valid_ovf_env(data=odata)}
-
- dsrc = self._get_ds(data)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertEqual(dsrc.cfg['system_info']['default_user']['name'],
- "myuser")
-
- def test_password_given(self):
- odata = {'HostName': "myhost", 'UserName': "myuser",
- 'UserPassword': "mypass"}
- data = {'ovfcontent': construct_valid_ovf_env(data=odata)}
-
- dsrc = self._get_ds(data)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertTrue('default_user' in dsrc.cfg['system_info'])
- defuser = dsrc.cfg['system_info']['default_user']
-
- # default user should be updated username and should not be locked.
- self.assertEqual(defuser['name'], odata['UserName'])
- self.assertFalse(defuser['lock_passwd'])
- # passwd is crypt formated string $id$salt$encrypted
- # encrypting plaintext with salt value of everything up to final '$'
- # should equal that after the '$'
- pos = defuser['passwd'].rfind("$") + 1
- self.assertEqual(defuser['passwd'],
- crypt.crypt(odata['UserPassword'],
- defuser['passwd'][0:pos]))
-
- def test_userdata_plain(self):
- mydata = "FOOBAR"
- odata = {'UserData': {'text': mydata, 'encoding': 'plain'}}
- data = {'ovfcontent': construct_valid_ovf_env(data=odata)}
-
- dsrc = self._get_ds(data)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertEqual(decode_binary(dsrc.userdata_raw), mydata)
-
- def test_userdata_found(self):
- mydata = "FOOBAR"
- odata = {'UserData': {'text': b64e(mydata), 'encoding': 'base64'}}
- data = {'ovfcontent': construct_valid_ovf_env(data=odata)}
-
- dsrc = self._get_ds(data)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertEqual(dsrc.userdata_raw, mydata.encode('utf-8'))
-
- def test_no_datasource_expected(self):
- # no source should be found if no seed_dir and no devs
- data = {}
- dsrc = self._get_ds({})
- ret = dsrc.get_data()
- self.assertFalse(ret)
- self.assertFalse('agent_invoked' in data)
-
- def test_cfg_has_pubkeys_fingerprint(self):
- odata = {'HostName': "myhost", 'UserName': "myuser"}
- mypklist = [{'fingerprint': 'fp1', 'path': 'path1', 'value': ''}]
- pubkeys = [(x['fingerprint'], x['path'], x['value']) for x in mypklist]
- data = {'ovfcontent': construct_valid_ovf_env(data=odata,
- pubkeys=pubkeys)}
-
- dsrc = self._get_ds(data)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- for mypk in mypklist:
- self.assertIn(mypk, dsrc.cfg['_pubkeys'])
- self.assertIn('pubkey_from', dsrc.metadata['public-keys'][-1])
-
- def test_cfg_has_pubkeys_value(self):
- # make sure that provided key is used over fingerprint
- odata = {'HostName': "myhost", 'UserName': "myuser"}
- mypklist = [{'fingerprint': 'fp1', 'path': 'path1', 'value': 'value1'}]
- pubkeys = [(x['fingerprint'], x['path'], x['value']) for x in mypklist]
- data = {'ovfcontent': construct_valid_ovf_env(data=odata,
- pubkeys=pubkeys)}
-
- dsrc = self._get_ds(data)
- ret = dsrc.get_data()
- self.assertTrue(ret)
-
- for mypk in mypklist:
- self.assertIn(mypk, dsrc.cfg['_pubkeys'])
- self.assertIn(mypk['value'], dsrc.metadata['public-keys'])
-
- def test_cfg_has_no_fingerprint_has_value(self):
- # test value is used when fingerprint not provided
- odata = {'HostName': "myhost", 'UserName': "myuser"}
- mypklist = [{'fingerprint': None, 'path': 'path1', 'value': 'value1'}]
- pubkeys = [(x['fingerprint'], x['path'], x['value']) for x in mypklist]
- data = {'ovfcontent': construct_valid_ovf_env(data=odata,
- pubkeys=pubkeys)}
-
- dsrc = self._get_ds(data)
- ret = dsrc.get_data()
- self.assertTrue(ret)
-
- for mypk in mypklist:
- self.assertIn(mypk['value'], dsrc.metadata['public-keys'])
-
- def test_default_ephemeral(self):
- # make sure the ephemeral device works
- odata = {}
- data = {'ovfcontent': construct_valid_ovf_env(data=odata),
- 'sys_cfg': {}}
-
- dsrc = self._get_ds(data)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- cfg = dsrc.get_config_obj()
-
- self.assertEqual(dsrc.device_name_to_device("ephemeral0"),
- "/dev/sdb")
- assert 'disk_setup' in cfg
- assert 'fs_setup' in cfg
- self.assertIsInstance(cfg['disk_setup'], dict)
- self.assertIsInstance(cfg['fs_setup'], list)
-
- def test_provide_disk_aliases(self):
- # Make sure that user can affect disk aliases
- dscfg = {'disk_aliases': {'ephemeral0': '/dev/sdc'}}
- odata = {'HostName': "myhost", 'UserName': "myuser",
- 'dscfg': {'text': b64e(yaml.dump(dscfg)),
- 'encoding': 'base64'}}
- usercfg = {'disk_setup': {'/dev/sdc': {'something': '...'},
- 'ephemeral0': False}}
- userdata = '#cloud-config' + yaml.dump(usercfg) + "\n"
-
- ovfcontent = construct_valid_ovf_env(data=odata, userdata=userdata)
- data = {'ovfcontent': ovfcontent, 'sys_cfg': {}}
-
- dsrc = self._get_ds(data)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- cfg = dsrc.get_config_obj()
- self.assertTrue(cfg)
-
- def test_userdata_arrives(self):
- userdata = "This is my user-data"
- xml = construct_valid_ovf_env(data={}, userdata=userdata)
- data = {'ovfcontent': xml}
- dsrc = self._get_ds(data)
- dsrc.get_data()
-
- self.assertEqual(userdata.encode('us-ascii'), dsrc.userdata_raw)
-
- def test_password_redacted_in_ovf(self):
- odata = {'HostName': "myhost", 'UserName': "myuser",
- 'UserPassword': "mypass"}
- data = {'ovfcontent': construct_valid_ovf_env(data=odata)}
- dsrc = self._get_ds(data)
- ret = dsrc.get_data()
-
- self.assertTrue(ret)
- ovf_env_path = os.path.join(self.waagent_d, 'ovf-env.xml')
-
- # The XML should not be same since the user password is redacted
- on_disk_ovf = load_file(ovf_env_path)
- self.xml_notequals(data['ovfcontent'], on_disk_ovf)
-
- # Make sure that the redacted password on disk is not used by CI
- self.assertNotEqual(dsrc.cfg.get('password'),
- DataSourceAzure.DEF_PASSWD_REDACTION)
-
- # Make sure that the password was really encrypted
- et = ET.fromstring(on_disk_ovf)
- for elem in et.iter():
- if 'UserPassword' in elem.tag:
- self.assertEqual(DataSourceAzure.DEF_PASSWD_REDACTION,
- elem.text)
-
- def test_ovf_env_arrives_in_waagent_dir(self):
- xml = construct_valid_ovf_env(data={}, userdata="FOODATA")
- dsrc = self._get_ds({'ovfcontent': xml})
- dsrc.get_data()
-
- # 'data_dir' is '/var/lib/waagent' (walinux-agent's state dir)
- # we expect that the ovf-env.xml file is copied there.
- ovf_env_path = os.path.join(self.waagent_d, 'ovf-env.xml')
- self.assertTrue(os.path.exists(ovf_env_path))
- self.xml_equals(xml, load_file(ovf_env_path))
-
- def test_ovf_can_include_unicode(self):
- xml = construct_valid_ovf_env(data={})
- xml = u'\ufeff{0}'.format(xml)
- dsrc = self._get_ds({'ovfcontent': xml})
- dsrc.get_data()
-
- def test_exception_fetching_fabric_data_doesnt_propagate(self):
- ds = self._get_ds({'ovfcontent': construct_valid_ovf_env()})
- ds.ds_cfg['agent_command'] = '__builtin__'
- self.get_metadata_from_fabric.side_effect = Exception
- self.assertFalse(ds.get_data())
-
- def test_fabric_data_included_in_metadata(self):
- ds = self._get_ds({'ovfcontent': construct_valid_ovf_env()})
- ds.ds_cfg['agent_command'] = '__builtin__'
- self.get_metadata_from_fabric.return_value = {'test': 'value'}
- ret = ds.get_data()
- self.assertTrue(ret)
- self.assertEqual('value', ds.metadata['test'])
-
- def test_instance_id_from_dmidecode_used(self):
- ds = self._get_ds({'ovfcontent': construct_valid_ovf_env()})
- ds.get_data()
- self.assertEqual(self.instance_id, ds.metadata['instance-id'])
-
- def test_instance_id_from_dmidecode_used_for_builtin(self):
- ds = self._get_ds({'ovfcontent': construct_valid_ovf_env()})
- ds.ds_cfg['agent_command'] = '__builtin__'
- ds.get_data()
- self.assertEqual(self.instance_id, ds.metadata['instance-id'])
-
-
-class TestAzureBounce(TestCase):
-
- def mock_out_azure_moving_parts(self):
- self.patches.enter_context(
- mock.patch.object(DataSourceAzure, 'invoke_agent'))
- self.patches.enter_context(
- mock.patch.object(DataSourceAzure, 'wait_for_files'))
- self.patches.enter_context(
- mock.patch.object(DataSourceAzure, 'list_possible_azure_ds_devs',
- mock.MagicMock(return_value=[])))
- self.patches.enter_context(
- mock.patch.object(DataSourceAzure,
- 'find_fabric_formatted_ephemeral_disk',
- mock.MagicMock(return_value=None)))
- self.patches.enter_context(
- mock.patch.object(DataSourceAzure,
- 'find_fabric_formatted_ephemeral_part',
- mock.MagicMock(return_value=None)))
- self.patches.enter_context(
- mock.patch.object(DataSourceAzure, 'get_metadata_from_fabric',
- mock.MagicMock(return_value={})))
- self.patches.enter_context(
- mock.patch.object(DataSourceAzure.util, 'read_dmi_data',
- mock.MagicMock(return_value='test-instance-id')))
-
- def setUp(self):
- super(TestAzureBounce, self).setUp()
- self.tmp = tempfile.mkdtemp()
- self.waagent_d = os.path.join(self.tmp, 'var', 'lib', 'waagent')
- self.paths = helpers.Paths({'cloud_dir': self.tmp})
- self.addCleanup(shutil.rmtree, self.tmp)
- DataSourceAzure.BUILTIN_DS_CONFIG['data_dir'] = self.waagent_d
- self.patches = ExitStack()
- self.mock_out_azure_moving_parts()
- self.get_hostname = self.patches.enter_context(
- mock.patch.object(DataSourceAzure, 'get_hostname'))
- self.set_hostname = self.patches.enter_context(
- mock.patch.object(DataSourceAzure, 'set_hostname'))
- self.subp = self.patches.enter_context(
- mock.patch('cloudinit.sources.DataSourceAzure.util.subp'))
-
- def tearDown(self):
- self.patches.close()
-
- def _get_ds(self, ovfcontent=None):
- if ovfcontent is not None:
- populate_dir(os.path.join(self.paths.seed_dir, "azure"),
- {'ovf-env.xml': ovfcontent})
- return DataSourceAzure.DataSourceAzureNet(
- {}, distro=None, paths=self.paths)
-
- def get_ovf_env_with_dscfg(self, hostname, cfg):
- odata = {
- 'HostName': hostname,
- 'dscfg': {
- 'text': b64e(yaml.dump(cfg)),
- 'encoding': 'base64'
- }
- }
- return construct_valid_ovf_env(data=odata)
-
- def test_disabled_bounce_does_not_change_hostname(self):
- cfg = {'hostname_bounce': {'policy': 'off'}}
- self._get_ds(self.get_ovf_env_with_dscfg('test-host', cfg)).get_data()
- self.assertEqual(0, self.set_hostname.call_count)
-
- @mock.patch('cloudinit.sources.DataSourceAzure.perform_hostname_bounce')
- def test_disabled_bounce_does_not_perform_bounce(
- self, perform_hostname_bounce):
- cfg = {'hostname_bounce': {'policy': 'off'}}
- self._get_ds(self.get_ovf_env_with_dscfg('test-host', cfg)).get_data()
- self.assertEqual(0, perform_hostname_bounce.call_count)
-
- def test_same_hostname_does_not_change_hostname(self):
- host_name = 'unchanged-host-name'
- self.get_hostname.return_value = host_name
- cfg = {'hostname_bounce': {'policy': 'yes'}}
- self._get_ds(self.get_ovf_env_with_dscfg(host_name, cfg)).get_data()
- self.assertEqual(0, self.set_hostname.call_count)
-
- @mock.patch('cloudinit.sources.DataSourceAzure.perform_hostname_bounce')
- def test_unchanged_hostname_does_not_perform_bounce(
- self, perform_hostname_bounce):
- host_name = 'unchanged-host-name'
- self.get_hostname.return_value = host_name
- cfg = {'hostname_bounce': {'policy': 'yes'}}
- self._get_ds(self.get_ovf_env_with_dscfg(host_name, cfg)).get_data()
- self.assertEqual(0, perform_hostname_bounce.call_count)
-
- @mock.patch('cloudinit.sources.DataSourceAzure.perform_hostname_bounce')
- def test_force_performs_bounce_regardless(self, perform_hostname_bounce):
- host_name = 'unchanged-host-name'
- self.get_hostname.return_value = host_name
- cfg = {'hostname_bounce': {'policy': 'force'}}
- self._get_ds(self.get_ovf_env_with_dscfg(host_name, cfg)).get_data()
- self.assertEqual(1, perform_hostname_bounce.call_count)
-
- def test_different_hostnames_sets_hostname(self):
- expected_hostname = 'azure-expected-host-name'
- self.get_hostname.return_value = 'default-host-name'
- self._get_ds(
- self.get_ovf_env_with_dscfg(expected_hostname, {})).get_data()
- self.assertEqual(expected_hostname,
- self.set_hostname.call_args_list[0][0][0])
-
- @mock.patch('cloudinit.sources.DataSourceAzure.perform_hostname_bounce')
- def test_different_hostnames_performs_bounce(
- self, perform_hostname_bounce):
- expected_hostname = 'azure-expected-host-name'
- self.get_hostname.return_value = 'default-host-name'
- self._get_ds(
- self.get_ovf_env_with_dscfg(expected_hostname, {})).get_data()
- self.assertEqual(1, perform_hostname_bounce.call_count)
-
- def test_different_hostnames_sets_hostname_back(self):
- initial_host_name = 'default-host-name'
- self.get_hostname.return_value = initial_host_name
- self._get_ds(
- self.get_ovf_env_with_dscfg('some-host-name', {})).get_data()
- self.assertEqual(initial_host_name,
- self.set_hostname.call_args_list[-1][0][0])
-
- @mock.patch('cloudinit.sources.DataSourceAzure.perform_hostname_bounce')
- def test_failure_in_bounce_still_resets_host_name(
- self, perform_hostname_bounce):
- perform_hostname_bounce.side_effect = Exception
- initial_host_name = 'default-host-name'
- self.get_hostname.return_value = initial_host_name
- self._get_ds(
- self.get_ovf_env_with_dscfg('some-host-name', {})).get_data()
- self.assertEqual(initial_host_name,
- self.set_hostname.call_args_list[-1][0][0])
-
- def test_environment_correct_for_bounce_command(self):
- interface = 'int0'
- hostname = 'my-new-host'
- old_hostname = 'my-old-host'
- self.get_hostname.return_value = old_hostname
- cfg = {'hostname_bounce': {'interface': interface, 'policy': 'force'}}
- data = self.get_ovf_env_with_dscfg(hostname, cfg)
- self._get_ds(data).get_data()
- self.assertEqual(1, self.subp.call_count)
- bounce_env = self.subp.call_args[1]['env']
- self.assertEqual(interface, bounce_env['interface'])
- self.assertEqual(hostname, bounce_env['hostname'])
- self.assertEqual(old_hostname, bounce_env['old_hostname'])
-
- def test_default_bounce_command_used_by_default(self):
- cmd = 'default-bounce-command'
- DataSourceAzure.BUILTIN_DS_CONFIG['hostname_bounce']['command'] = cmd
- cfg = {'hostname_bounce': {'policy': 'force'}}
- data = self.get_ovf_env_with_dscfg('some-hostname', cfg)
- self._get_ds(data).get_data()
- self.assertEqual(1, self.subp.call_count)
- bounce_args = self.subp.call_args[1]['args']
- self.assertEqual(cmd, bounce_args)
-
- @mock.patch('cloudinit.sources.DataSourceAzure.perform_hostname_bounce')
- def test_set_hostname_option_can_disable_bounce(
- self, perform_hostname_bounce):
- cfg = {'set_hostname': False, 'hostname_bounce': {'policy': 'force'}}
- data = self.get_ovf_env_with_dscfg('some-hostname', cfg)
- self._get_ds(data).get_data()
-
- self.assertEqual(0, perform_hostname_bounce.call_count)
-
- def test_set_hostname_option_can_disable_hostname_set(self):
- cfg = {'set_hostname': False, 'hostname_bounce': {'policy': 'force'}}
- data = self.get_ovf_env_with_dscfg('some-hostname', cfg)
- self._get_ds(data).get_data()
-
- self.assertEqual(0, self.set_hostname.call_count)
-
-
-class TestReadAzureOvf(TestCase):
- def test_invalid_xml_raises_non_azure_ds(self):
- invalid_xml = "<foo>" + construct_valid_ovf_env(data={})
- self.assertRaises(DataSourceAzure.BrokenAzureDataSource,
- DataSourceAzure.read_azure_ovf, invalid_xml)
-
- def test_load_with_pubkeys(self):
- mypklist = [{'fingerprint': 'fp1', 'path': 'path1', 'value': ''}]
- pubkeys = [(x['fingerprint'], x['path'], x['value']) for x in mypklist]
- content = construct_valid_ovf_env(pubkeys=pubkeys)
- (_md, _ud, cfg) = DataSourceAzure.read_azure_ovf(content)
- for mypk in mypklist:
- self.assertIn(mypk, cfg['_pubkeys'])
diff --git a/tests/unittests/test_datasource/test_azure_helper.py b/tests/unittests/test_datasource/test_azure_helper.py
deleted file mode 100644
index 65202ff0..00000000
--- a/tests/unittests/test_datasource/test_azure_helper.py
+++ /dev/null
@@ -1,412 +0,0 @@
-import os
-
-from cloudinit.sources.helpers import azure as azure_helper
-
-from ..helpers import ExitStack, mock, TestCase
-
-
-GOAL_STATE_TEMPLATE = """\
-<?xml version="1.0" encoding="utf-8"?>
-<GoalState xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="goalstate10.xsd">
- <Version>2012-11-30</Version>
- <Incarnation>{incarnation}</Incarnation>
- <Machine>
- <ExpectedState>Started</ExpectedState>
- <StopRolesDeadlineHint>300000</StopRolesDeadlineHint>
- <LBProbePorts>
- <Port>16001</Port>
- </LBProbePorts>
- <ExpectHealthReport>FALSE</ExpectHealthReport>
- </Machine>
- <Container>
- <ContainerId>{container_id}</ContainerId>
- <RoleInstanceList>
- <RoleInstance>
- <InstanceId>{instance_id}</InstanceId>
- <State>Started</State>
- <Configuration>
- <HostingEnvironmentConfig>
- http://100.86.192.70:80/...hostingEnvironmentConfig...
- </HostingEnvironmentConfig>
- <SharedConfig>http://100.86.192.70:80/..SharedConfig..</SharedConfig>
- <ExtensionsConfig>
- http://100.86.192.70:80/...extensionsConfig...
- </ExtensionsConfig>
- <FullConfig>http://100.86.192.70:80/...fullConfig...</FullConfig>
- <Certificates>{certificates_url}</Certificates>
- <ConfigName>68ce47.0.68ce47.0.utl-trusty--292258.1.xml</ConfigName>
- </Configuration>
- </RoleInstance>
- </RoleInstanceList>
- </Container>
-</GoalState>
-"""
-
-
-class TestFindEndpoint(TestCase):
-
- def setUp(self):
- super(TestFindEndpoint, self).setUp()
- patches = ExitStack()
- self.addCleanup(patches.close)
-
- self.load_file = patches.enter_context(
- mock.patch.object(azure_helper.util, 'load_file'))
-
- def test_missing_file(self):
- self.load_file.side_effect = IOError
- self.assertRaises(IOError,
- azure_helper.WALinuxAgentShim.find_endpoint)
-
- def test_missing_special_azure_line(self):
- self.load_file.return_value = ''
- self.assertRaises(ValueError,
- azure_helper.WALinuxAgentShim.find_endpoint)
-
- @staticmethod
- def _build_lease_content(encoded_address):
- return '\n'.join([
- 'lease {',
- ' interface "eth0";',
- ' option unknown-245 {0};'.format(encoded_address),
- '}'])
-
- def test_latest_lease_used(self):
- encoded_addresses = ['5:4:3:2', '4:3:2:1']
- file_content = '\n'.join([self._build_lease_content(encoded_address)
- for encoded_address in encoded_addresses])
- self.load_file.return_value = file_content
- self.assertEqual(encoded_addresses[-1].replace(':', '.'),
- azure_helper.WALinuxAgentShim.find_endpoint())
-
-
-class TestExtractIpAddressFromLeaseValue(TestCase):
-
- def test_hex_string(self):
- ip_address, encoded_address = '98.76.54.32', '62:4c:36:20'
- self.assertEqual(
- ip_address,
- azure_helper.WALinuxAgentShim.get_ip_from_lease_value(
- encoded_address
- ))
-
- def test_hex_string_with_single_character_part(self):
- ip_address, encoded_address = '4.3.2.1', '4:3:2:1'
- self.assertEqual(
- ip_address,
- azure_helper.WALinuxAgentShim.get_ip_from_lease_value(
- encoded_address
- ))
-
- def test_packed_string(self):
- ip_address, encoded_address = '98.76.54.32', 'bL6 '
- self.assertEqual(
- ip_address,
- azure_helper.WALinuxAgentShim.get_ip_from_lease_value(
- encoded_address
- ))
-
- def test_packed_string_with_escaped_quote(self):
- ip_address, encoded_address = '100.72.34.108', 'dH\\"l'
- self.assertEqual(
- ip_address,
- azure_helper.WALinuxAgentShim.get_ip_from_lease_value(
- encoded_address
- ))
-
- def test_packed_string_containing_a_colon(self):
- ip_address, encoded_address = '100.72.58.108', 'dH:l'
- self.assertEqual(
- ip_address,
- azure_helper.WALinuxAgentShim.get_ip_from_lease_value(
- encoded_address
- ))
-
-
-class TestGoalStateParsing(TestCase):
-
- default_parameters = {
- 'incarnation': 1,
- 'container_id': 'MyContainerId',
- 'instance_id': 'MyInstanceId',
- 'certificates_url': 'MyCertificatesUrl',
- }
-
- def _get_goal_state(self, http_client=None, **kwargs):
- if http_client is None:
- http_client = mock.MagicMock()
- parameters = self.default_parameters.copy()
- parameters.update(kwargs)
- xml = GOAL_STATE_TEMPLATE.format(**parameters)
- if parameters['certificates_url'] is None:
- new_xml_lines = []
- for line in xml.splitlines():
- if 'Certificates' in line:
- continue
- new_xml_lines.append(line)
- xml = '\n'.join(new_xml_lines)
- return azure_helper.GoalState(xml, http_client)
-
- def test_incarnation_parsed_correctly(self):
- incarnation = '123'
- goal_state = self._get_goal_state(incarnation=incarnation)
- self.assertEqual(incarnation, goal_state.incarnation)
-
- def test_container_id_parsed_correctly(self):
- container_id = 'TestContainerId'
- goal_state = self._get_goal_state(container_id=container_id)
- self.assertEqual(container_id, goal_state.container_id)
-
- def test_instance_id_parsed_correctly(self):
- instance_id = 'TestInstanceId'
- goal_state = self._get_goal_state(instance_id=instance_id)
- self.assertEqual(instance_id, goal_state.instance_id)
-
- def test_certificates_xml_parsed_and_fetched_correctly(self):
- http_client = mock.MagicMock()
- certificates_url = 'TestCertificatesUrl'
- goal_state = self._get_goal_state(
- http_client=http_client, certificates_url=certificates_url)
- certificates_xml = goal_state.certificates_xml
- self.assertEqual(1, http_client.get.call_count)
- self.assertEqual(certificates_url, http_client.get.call_args[0][0])
- self.assertTrue(http_client.get.call_args[1].get('secure', False))
- self.assertEqual(http_client.get.return_value.contents,
- certificates_xml)
-
- def test_missing_certificates_skips_http_get(self):
- http_client = mock.MagicMock()
- goal_state = self._get_goal_state(
- http_client=http_client, certificates_url=None)
- certificates_xml = goal_state.certificates_xml
- self.assertEqual(0, http_client.get.call_count)
- self.assertIsNone(certificates_xml)
-
-
-class TestAzureEndpointHttpClient(TestCase):
-
- regular_headers = {
- 'x-ms-agent-name': 'WALinuxAgent',
- 'x-ms-version': '2012-11-30',
- }
-
- def setUp(self):
- super(TestAzureEndpointHttpClient, self).setUp()
- patches = ExitStack()
- self.addCleanup(patches.close)
-
- self.read_file_or_url = patches.enter_context(
- mock.patch.object(azure_helper.util, 'read_file_or_url'))
-
- def test_non_secure_get(self):
- client = azure_helper.AzureEndpointHttpClient(mock.MagicMock())
- url = 'MyTestUrl'
- response = client.get(url, secure=False)
- self.assertEqual(1, self.read_file_or_url.call_count)
- self.assertEqual(self.read_file_or_url.return_value, response)
- self.assertEqual(mock.call(url, headers=self.regular_headers),
- self.read_file_or_url.call_args)
-
- def test_secure_get(self):
- url = 'MyTestUrl'
- certificate = mock.MagicMock()
- expected_headers = self.regular_headers.copy()
- expected_headers.update({
- "x-ms-cipher-name": "DES_EDE3_CBC",
- "x-ms-guest-agent-public-x509-cert": certificate,
- })
- client = azure_helper.AzureEndpointHttpClient(certificate)
- response = client.get(url, secure=True)
- self.assertEqual(1, self.read_file_or_url.call_count)
- self.assertEqual(self.read_file_or_url.return_value, response)
- self.assertEqual(mock.call(url, headers=expected_headers),
- self.read_file_or_url.call_args)
-
- def test_post(self):
- data = mock.MagicMock()
- url = 'MyTestUrl'
- client = azure_helper.AzureEndpointHttpClient(mock.MagicMock())
- response = client.post(url, data=data)
- self.assertEqual(1, self.read_file_or_url.call_count)
- self.assertEqual(self.read_file_or_url.return_value, response)
- self.assertEqual(
- mock.call(url, data=data, headers=self.regular_headers),
- self.read_file_or_url.call_args)
-
- def test_post_with_extra_headers(self):
- url = 'MyTestUrl'
- client = azure_helper.AzureEndpointHttpClient(mock.MagicMock())
- extra_headers = {'test': 'header'}
- client.post(url, extra_headers=extra_headers)
- self.assertEqual(1, self.read_file_or_url.call_count)
- expected_headers = self.regular_headers.copy()
- expected_headers.update(extra_headers)
- self.assertEqual(
- mock.call(mock.ANY, data=mock.ANY, headers=expected_headers),
- self.read_file_or_url.call_args)
-
-
-class TestOpenSSLManager(TestCase):
-
- def setUp(self):
- super(TestOpenSSLManager, self).setUp()
- patches = ExitStack()
- self.addCleanup(patches.close)
-
- self.subp = patches.enter_context(
- mock.patch.object(azure_helper.util, 'subp'))
- try:
- self.open = patches.enter_context(
- mock.patch('__builtin__.open'))
- except ImportError:
- self.open = patches.enter_context(
- mock.patch('builtins.open'))
-
- @mock.patch.object(azure_helper, 'cd', mock.MagicMock())
- @mock.patch.object(azure_helper.tempfile, 'mkdtemp')
- def test_openssl_manager_creates_a_tmpdir(self, mkdtemp):
- manager = azure_helper.OpenSSLManager()
- self.assertEqual(mkdtemp.return_value, manager.tmpdir)
-
- def test_generate_certificate_uses_tmpdir(self):
- subp_directory = {}
-
- def capture_directory(*args, **kwargs):
- subp_directory['path'] = os.getcwd()
-
- self.subp.side_effect = capture_directory
- manager = azure_helper.OpenSSLManager()
- self.assertEqual(manager.tmpdir, subp_directory['path'])
- manager.clean_up()
-
- @mock.patch.object(azure_helper, 'cd', mock.MagicMock())
- @mock.patch.object(azure_helper.tempfile, 'mkdtemp', mock.MagicMock())
- @mock.patch.object(azure_helper.util, 'del_dir')
- def test_clean_up(self, del_dir):
- manager = azure_helper.OpenSSLManager()
- manager.clean_up()
- self.assertEqual([mock.call(manager.tmpdir)], del_dir.call_args_list)
-
-
-class TestWALinuxAgentShim(TestCase):
-
- def setUp(self):
- super(TestWALinuxAgentShim, self).setUp()
- patches = ExitStack()
- self.addCleanup(patches.close)
-
- self.AzureEndpointHttpClient = patches.enter_context(
- mock.patch.object(azure_helper, 'AzureEndpointHttpClient'))
- self.find_endpoint = patches.enter_context(
- mock.patch.object(
- azure_helper.WALinuxAgentShim, 'find_endpoint'))
- self.GoalState = patches.enter_context(
- mock.patch.object(azure_helper, 'GoalState'))
- self.OpenSSLManager = patches.enter_context(
- mock.patch.object(azure_helper, 'OpenSSLManager'))
- patches.enter_context(
- mock.patch.object(azure_helper.time, 'sleep', mock.MagicMock()))
-
- def test_http_client_uses_certificate(self):
- shim = azure_helper.WALinuxAgentShim()
- shim.register_with_azure_and_fetch_data()
- self.assertEqual(
- [mock.call(self.OpenSSLManager.return_value.certificate)],
- self.AzureEndpointHttpClient.call_args_list)
-
- def test_correct_url_used_for_goalstate(self):
- self.find_endpoint.return_value = 'test_endpoint'
- shim = azure_helper.WALinuxAgentShim()
- shim.register_with_azure_and_fetch_data()
- get = self.AzureEndpointHttpClient.return_value.get
- self.assertEqual(
- [mock.call('http://test_endpoint/machine/?comp=goalstate')],
- get.call_args_list)
- self.assertEqual(
- [mock.call(get.return_value.contents,
- self.AzureEndpointHttpClient.return_value)],
- self.GoalState.call_args_list)
-
- def test_certificates_used_to_determine_public_keys(self):
- shim = azure_helper.WALinuxAgentShim()
- data = shim.register_with_azure_and_fetch_data()
- self.assertEqual(
- [mock.call(self.GoalState.return_value.certificates_xml)],
- self.OpenSSLManager.return_value.parse_certificates.call_args_list)
- self.assertEqual(
- self.OpenSSLManager.return_value.parse_certificates.return_value,
- data['public-keys'])
-
- def test_absent_certificates_produces_empty_public_keys(self):
- self.GoalState.return_value.certificates_xml = None
- shim = azure_helper.WALinuxAgentShim()
- data = shim.register_with_azure_and_fetch_data()
- self.assertEqual([], data['public-keys'])
-
- def test_correct_url_used_for_report_ready(self):
- self.find_endpoint.return_value = 'test_endpoint'
- shim = azure_helper.WALinuxAgentShim()
- shim.register_with_azure_and_fetch_data()
- expected_url = 'http://test_endpoint/machine?comp=health'
- self.assertEqual(
- [mock.call(expected_url, data=mock.ANY, extra_headers=mock.ANY)],
- self.AzureEndpointHttpClient.return_value.post.call_args_list)
-
- def test_goal_state_values_used_for_report_ready(self):
- self.GoalState.return_value.incarnation = 'TestIncarnation'
- self.GoalState.return_value.container_id = 'TestContainerId'
- self.GoalState.return_value.instance_id = 'TestInstanceId'
- shim = azure_helper.WALinuxAgentShim()
- shim.register_with_azure_and_fetch_data()
- posted_document = (
- self.AzureEndpointHttpClient.return_value.post.call_args[1]['data']
- )
- self.assertIn('TestIncarnation', posted_document)
- self.assertIn('TestContainerId', posted_document)
- self.assertIn('TestInstanceId', posted_document)
-
- def test_clean_up_can_be_called_at_any_time(self):
- shim = azure_helper.WALinuxAgentShim()
- shim.clean_up()
-
- def test_clean_up_will_clean_up_openssl_manager_if_instantiated(self):
- shim = azure_helper.WALinuxAgentShim()
- shim.register_with_azure_and_fetch_data()
- shim.clean_up()
- self.assertEqual(
- 1, self.OpenSSLManager.return_value.clean_up.call_count)
-
- def test_failure_to_fetch_goalstate_bubbles_up(self):
- class SentinelException(Exception):
- pass
- self.AzureEndpointHttpClient.return_value.get.side_effect = (
- SentinelException)
- shim = azure_helper.WALinuxAgentShim()
- self.assertRaises(SentinelException,
- shim.register_with_azure_and_fetch_data)
-
-
-class TestGetMetadataFromFabric(TestCase):
-
- @mock.patch.object(azure_helper, 'WALinuxAgentShim')
- def test_data_from_shim_returned(self, shim):
- ret = azure_helper.get_metadata_from_fabric()
- self.assertEqual(
- shim.return_value.register_with_azure_and_fetch_data.return_value,
- ret)
-
- @mock.patch.object(azure_helper, 'WALinuxAgentShim')
- def test_success_calls_clean_up(self, shim):
- azure_helper.get_metadata_from_fabric()
- self.assertEqual(1, shim.return_value.clean_up.call_count)
-
- @mock.patch.object(azure_helper, 'WALinuxAgentShim')
- def test_failure_in_registration_calls_clean_up(self, shim):
- class SentinelException(Exception):
- pass
- shim.return_value.register_with_azure_and_fetch_data.side_effect = (
- SentinelException)
- self.assertRaises(SentinelException,
- azure_helper.get_metadata_from_fabric)
- self.assertEqual(1, shim.return_value.clean_up.call_count)
diff --git a/tests/unittests/test_datasource/test_cloudsigma.py b/tests/unittests/test_datasource/test_cloudsigma.py
deleted file mode 100644
index 2a42ce0c..00000000
--- a/tests/unittests/test_datasource/test_cloudsigma.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# coding: utf-8
-
-import copy
-
-from cloudinit.cs_utils import Cepko
-from cloudinit.sources import DataSourceCloudSigma
-
-from .. import helpers as test_helpers
-
-SERVER_CONTEXT = {
- "cpu": 1000,
- "cpus_instead_of_cores": False,
- "global_context": {"some_global_key": "some_global_val"},
- "mem": 1073741824,
- "meta": {
- "ssh_public_key": "ssh-rsa AAAAB3NzaC1yc2E.../hQ5D5 john@doe",
- "cloudinit-user-data": "#cloud-config\n\n...",
- },
- "name": "test_server",
- "requirements": [],
- "smp": 1,
- "tags": ["much server", "very performance"],
- "uuid": "65b2fb23-8c03-4187-a3ba-8b7c919e8890",
- "vnc_password": "9e84d6cb49e46379",
- "vendor_data": {
- "location": "zrh",
- "cloudinit": "#cloud-config\n\n...",
- }
-}
-
-
-class CepkoMock(Cepko):
- def __init__(self, mocked_context):
- self.result = mocked_context
-
- def all(self):
- return self
-
-
-class DataSourceCloudSigmaTest(test_helpers.TestCase):
- def setUp(self):
- super(DataSourceCloudSigmaTest, self).setUp()
- self.datasource = DataSourceCloudSigma.DataSourceCloudSigma("", "", "")
- self.datasource.is_running_in_cloudsigma = lambda: True
- self.datasource.cepko = CepkoMock(SERVER_CONTEXT)
- self.datasource.get_data()
-
- def test_get_hostname(self):
- self.assertEqual("test_server", self.datasource.get_hostname())
- self.datasource.metadata['name'] = ''
- self.assertEqual("65b2fb23", self.datasource.get_hostname())
- self.datasource.metadata['name'] = u'тест'
- self.assertEqual("65b2fb23", self.datasource.get_hostname())
-
- def test_get_public_ssh_keys(self):
- self.assertEqual([SERVER_CONTEXT['meta']['ssh_public_key']],
- self.datasource.get_public_ssh_keys())
-
- def test_get_instance_id(self):
- self.assertEqual(SERVER_CONTEXT['uuid'],
- self.datasource.get_instance_id())
-
- def test_metadata(self):
- self.assertEqual(self.datasource.metadata, SERVER_CONTEXT)
-
- def test_user_data(self):
- self.assertEqual(self.datasource.userdata_raw,
- SERVER_CONTEXT['meta']['cloudinit-user-data'])
-
- def test_encoded_user_data(self):
- encoded_context = copy.deepcopy(SERVER_CONTEXT)
- encoded_context['meta']['base64_fields'] = 'cloudinit-user-data'
- encoded_context['meta']['cloudinit-user-data'] = 'aGkgd29ybGQK'
- self.datasource.cepko = CepkoMock(encoded_context)
- self.datasource.get_data()
-
- self.assertEqual(self.datasource.userdata_raw, b'hi world\n')
-
- def test_vendor_data(self):
- self.assertEqual(self.datasource.vendordata_raw,
- SERVER_CONTEXT['vendor_data']['cloudinit'])
-
- def test_lack_of_vendor_data(self):
- stripped_context = copy.deepcopy(SERVER_CONTEXT)
- del stripped_context["vendor_data"]
- self.datasource = DataSourceCloudSigma.DataSourceCloudSigma("", "", "")
- self.datasource.cepko = CepkoMock(stripped_context)
- self.datasource.get_data()
-
- self.assertIsNone(self.datasource.vendordata_raw)
-
- def test_lack_of_cloudinit_key_in_vendor_data(self):
- stripped_context = copy.deepcopy(SERVER_CONTEXT)
- del stripped_context["vendor_data"]["cloudinit"]
- self.datasource = DataSourceCloudSigma.DataSourceCloudSigma("", "", "")
- self.datasource.cepko = CepkoMock(stripped_context)
- self.datasource.get_data()
-
- self.assertIsNone(self.datasource.vendordata_raw)
diff --git a/tests/unittests/test_datasource/test_cloudstack.py b/tests/unittests/test_datasource/test_cloudstack.py
deleted file mode 100644
index b1aab17b..00000000
--- a/tests/unittests/test_datasource/test_cloudstack.py
+++ /dev/null
@@ -1,78 +0,0 @@
-from cloudinit import helpers
-from cloudinit.sources.DataSourceCloudStack import DataSourceCloudStack
-
-from ..helpers import TestCase, mock, ExitStack
-
-
-class TestCloudStackPasswordFetching(TestCase):
-
- def setUp(self):
- super(TestCloudStackPasswordFetching, self).setUp()
- self.patches = ExitStack()
- self.addCleanup(self.patches.close)
- mod_name = 'cloudinit.sources.DataSourceCloudStack'
- self.patches.enter_context(mock.patch('{0}.ec2'.format(mod_name)))
- self.patches.enter_context(mock.patch('{0}.uhelp'.format(mod_name)))
-
- def _set_password_server_response(self, response_string):
- subp = mock.MagicMock(return_value=(response_string, ''))
- self.patches.enter_context(
- mock.patch('cloudinit.sources.DataSourceCloudStack.util.subp',
- subp))
- return subp
-
- def test_empty_password_doesnt_create_config(self):
- self._set_password_server_response('')
- ds = DataSourceCloudStack({}, None, helpers.Paths({}))
- ds.get_data()
- self.assertEqual({}, ds.get_config_obj())
-
- def test_saved_password_doesnt_create_config(self):
- self._set_password_server_response('saved_password')
- ds = DataSourceCloudStack({}, None, helpers.Paths({}))
- ds.get_data()
- self.assertEqual({}, ds.get_config_obj())
-
- def test_password_sets_password(self):
- password = 'SekritSquirrel'
- self._set_password_server_response(password)
- ds = DataSourceCloudStack({}, None, helpers.Paths({}))
- ds.get_data()
- self.assertEqual(password, ds.get_config_obj()['password'])
-
- def test_bad_request_doesnt_stop_ds_from_working(self):
- self._set_password_server_response('bad_request')
- ds = DataSourceCloudStack({}, None, helpers.Paths({}))
- self.assertTrue(ds.get_data())
-
- def assertRequestTypesSent(self, subp, expected_request_types):
- request_types = []
- for call in subp.call_args_list:
- args = call[0][0]
- for arg in args:
- if arg.startswith('DomU_Request'):
- request_types.append(arg.split()[1])
- self.assertEqual(expected_request_types, request_types)
-
- def test_valid_response_means_password_marked_as_saved(self):
- password = 'SekritSquirrel'
- subp = self._set_password_server_response(password)
- ds = DataSourceCloudStack({}, None, helpers.Paths({}))
- ds.get_data()
- self.assertRequestTypesSent(subp,
- ['send_my_password', 'saved_password'])
-
- def _check_password_not_saved_for(self, response_string):
- subp = self._set_password_server_response(response_string)
- ds = DataSourceCloudStack({}, None, helpers.Paths({}))
- ds.get_data()
- self.assertRequestTypesSent(subp, ['send_my_password'])
-
- def test_password_not_saved_if_empty(self):
- self._check_password_not_saved_for('')
-
- def test_password_not_saved_if_already_saved(self):
- self._check_password_not_saved_for('saved_password')
-
- def test_password_not_saved_if_bad_request(self):
- self._check_password_not_saved_for('bad_request')
diff --git a/tests/unittests/test_datasource/test_configdrive.py b/tests/unittests/test_datasource/test_configdrive.py
deleted file mode 100644
index 18551b92..00000000
--- a/tests/unittests/test_datasource/test_configdrive.py
+++ /dev/null
@@ -1,597 +0,0 @@
-from copy import copy
-import json
-import os
-import shutil
-import six
-import tempfile
-
-from cloudinit import helpers
-from cloudinit.net import eni
-from cloudinit.net import network_state
-from cloudinit import settings
-from cloudinit.sources import DataSourceConfigDrive as ds
-from cloudinit.sources.helpers import openstack
-from cloudinit import util
-
-from ..helpers import TestCase, ExitStack, mock
-
-
-PUBKEY = u'ssh-rsa AAAAB3NzaC1....sIkJhq8wdX+4I3A4cYbYP ubuntu@server-460\n'
-EC2_META = {
- 'ami-id': 'ami-00000001',
- 'ami-launch-index': 0,
- 'ami-manifest-path': 'FIXME',
- 'block-device-mapping': {
- 'ami': 'sda1',
- 'ephemeral0': 'sda2',
- 'root': '/dev/sda1',
- 'swap': 'sda3'},
- 'hostname': 'sm-foo-test.novalocal',
- 'instance-action': 'none',
- 'instance-id': 'i-00000001',
- 'instance-type': 'm1.tiny',
- 'local-hostname': 'sm-foo-test.novalocal',
- 'local-ipv4': None,
- 'placement': {'availability-zone': 'nova'},
- 'public-hostname': 'sm-foo-test.novalocal',
- 'public-ipv4': '',
- 'public-keys': {'0': {'openssh-key': PUBKEY}},
- 'reservation-id': 'r-iru5qm4m',
- 'security-groups': ['default']
-}
-USER_DATA = b'#!/bin/sh\necho This is user data\n'
-OSTACK_META = {
- 'availability_zone': 'nova',
- 'files': [{'content_path': '/content/0000', 'path': '/etc/foo.cfg'},
- {'content_path': '/content/0001', 'path': '/etc/bar/bar.cfg'}],
- 'hostname': 'sm-foo-test.novalocal',
- 'meta': {'dsmode': 'local', 'my-meta': 'my-value'},
- 'name': 'sm-foo-test',
- 'public_keys': {'mykey': PUBKEY},
- 'uuid': 'b0fa911b-69d4-4476-bbe2-1c92bff6535c'}
-
-CONTENT_0 = b'This is contents of /etc/foo.cfg\n'
-CONTENT_1 = b'# this is /etc/bar/bar.cfg\n'
-NETWORK_DATA = {
- 'services': [
- {'type': 'dns', 'address': '199.204.44.24'},
- {'type': 'dns', 'address': '199.204.47.54'}
- ],
- 'links': [
- {'vif_id': '2ecc7709-b3f7-4448-9580-e1ec32d75bbd',
- 'ethernet_mac_address': 'fa:16:3e:69:b0:58',
- 'type': 'ovs', 'mtu': None, 'id': 'tap2ecc7709-b3'},
- {'vif_id': '2f88d109-5b57-40e6-af32-2472df09dc33',
- 'ethernet_mac_address': 'fa:16:3e:d4:57:ad',
- 'type': 'ovs', 'mtu': None, 'id': 'tap2f88d109-5b'},
- {'vif_id': '1a5382f8-04c5-4d75-ab98-d666c1ef52cc',
- 'ethernet_mac_address': 'fa:16:3e:05:30:fe',
- 'type': 'ovs', 'mtu': None, 'id': 'tap1a5382f8-04', 'name': 'nic0'}
- ],
- 'networks': [
- {'link': 'tap2ecc7709-b3', 'type': 'ipv4_dhcp',
- 'network_id': '6d6357ac-0f70-4afa-8bd7-c274cc4ea235',
- 'id': 'network0'},
- {'link': 'tap2f88d109-5b', 'type': 'ipv4_dhcp',
- 'network_id': 'd227a9b3-6960-4d94-8976-ee5788b44f54',
- 'id': 'network1'},
- {'link': 'tap1a5382f8-04', 'type': 'ipv4_dhcp',
- 'network_id': 'dab2ba57-cae2-4311-a5ed-010b263891f5',
- 'id': 'network2'}
- ]
-}
-
-NETWORK_DATA_2 = {
- "services": [
- {"type": "dns", "address": "1.1.1.191"},
- {"type": "dns", "address": "1.1.1.4"}],
- "networks": [
- {"network_id": "d94bbe94-7abc-48d4-9c82-4628ea26164a", "type": "ipv4",
- "netmask": "255.255.255.248", "link": "eth0",
- "routes": [{"netmask": "0.0.0.0", "network": "0.0.0.0",
- "gateway": "2.2.2.9"}],
- "ip_address": "2.2.2.10", "id": "network0-ipv4"},
- {"network_id": "ca447c83-6409-499b-aaef-6ad1ae995348", "type": "ipv4",
- "netmask": "255.255.255.224", "link": "eth1",
- "routes": [], "ip_address": "3.3.3.24", "id": "network1-ipv4"}],
- "links": [
- {"ethernet_mac_address": "fa:16:3e:dd:50:9a", "mtu": 1500,
- "type": "vif", "id": "eth0", "vif_id": "vif-foo1"},
- {"ethernet_mac_address": "fa:16:3e:a8:14:69", "mtu": 1500,
- "type": "vif", "id": "eth1", "vif_id": "vif-foo2"}]
-}
-
-
-KNOWN_MACS = {
- 'fa:16:3e:69:b0:58': 'enp0s1',
- 'fa:16:3e:d4:57:ad': 'enp0s2',
- 'fa:16:3e:dd:50:9a': 'foo1',
- 'fa:16:3e:a8:14:69': 'foo2',
- 'fa:16:3e:ed:9a:59': 'foo3',
-}
-
-CFG_DRIVE_FILES_V2 = {
- 'ec2/2009-04-04/meta-data.json': json.dumps(EC2_META),
- 'ec2/2009-04-04/user-data': USER_DATA,
- 'ec2/latest/meta-data.json': json.dumps(EC2_META),
- 'ec2/latest/user-data': USER_DATA,
- 'openstack/2012-08-10/meta_data.json': json.dumps(OSTACK_META),
- 'openstack/2012-08-10/user_data': USER_DATA,
- 'openstack/content/0000': CONTENT_0,
- 'openstack/content/0001': CONTENT_1,
- 'openstack/latest/meta_data.json': json.dumps(OSTACK_META),
- 'openstack/latest/user_data': USER_DATA,
- 'openstack/latest/network_data.json': json.dumps(NETWORK_DATA),
- 'openstack/2015-10-15/meta_data.json': json.dumps(OSTACK_META),
- 'openstack/2015-10-15/user_data': USER_DATA,
- 'openstack/2015-10-15/network_data.json': json.dumps(NETWORK_DATA)}
-
-
-class TestConfigDriveDataSource(TestCase):
-
- def setUp(self):
- super(TestConfigDriveDataSource, self).setUp()
- self.tmp = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp)
-
- def test_ec2_metadata(self):
- populate_dir(self.tmp, CFG_DRIVE_FILES_V2)
- found = ds.read_config_drive(self.tmp)
- self.assertTrue('ec2-metadata' in found)
- ec2_md = found['ec2-metadata']
- self.assertEqual(EC2_META, ec2_md)
-
- def test_dev_os_remap(self):
- populate_dir(self.tmp, CFG_DRIVE_FILES_V2)
- cfg_ds = ds.DataSourceConfigDrive(settings.CFG_BUILTIN,
- None,
- helpers.Paths({}))
- found = ds.read_config_drive(self.tmp)
- cfg_ds.metadata = found['metadata']
- name_tests = {
- 'ami': '/dev/vda1',
- 'root': '/dev/vda1',
- 'ephemeral0': '/dev/vda2',
- 'swap': '/dev/vda3',
- }
- for name, dev_name in name_tests.items():
- with ExitStack() as mocks:
- provided_name = dev_name[len('/dev/'):]
- provided_name = "s" + provided_name[1:]
- find_mock = mocks.enter_context(
- mock.patch.object(util, 'find_devs_with',
- return_value=[provided_name]))
- # We want os.path.exists() to return False on its first call,
- # and True on its second call. We use a handy generator as
- # the mock side effect for this. The mocked function returns
- # what the side effect returns.
-
- def exists_side_effect():
- yield False
- yield True
- exists_mock = mocks.enter_context(
- mock.patch.object(os.path, 'exists',
- side_effect=exists_side_effect()))
- device = cfg_ds.device_name_to_device(name)
- self.assertEqual(dev_name, device)
-
- find_mock.assert_called_once_with(mock.ANY)
- self.assertEqual(exists_mock.call_count, 2)
-
- def test_dev_os_map(self):
- populate_dir(self.tmp, CFG_DRIVE_FILES_V2)
- cfg_ds = ds.DataSourceConfigDrive(settings.CFG_BUILTIN,
- None,
- helpers.Paths({}))
- found = ds.read_config_drive(self.tmp)
- os_md = found['metadata']
- cfg_ds.metadata = os_md
- name_tests = {
- 'ami': '/dev/vda1',
- 'root': '/dev/vda1',
- 'ephemeral0': '/dev/vda2',
- 'swap': '/dev/vda3',
- }
- for name, dev_name in name_tests.items():
- with ExitStack() as mocks:
- find_mock = mocks.enter_context(
- mock.patch.object(util, 'find_devs_with',
- return_value=[dev_name]))
- exists_mock = mocks.enter_context(
- mock.patch.object(os.path, 'exists',
- return_value=True))
- device = cfg_ds.device_name_to_device(name)
- self.assertEqual(dev_name, device)
-
- find_mock.assert_called_once_with(mock.ANY)
- exists_mock.assert_called_once_with(mock.ANY)
-
- def test_dev_ec2_remap(self):
- populate_dir(self.tmp, CFG_DRIVE_FILES_V2)
- cfg_ds = ds.DataSourceConfigDrive(settings.CFG_BUILTIN,
- None,
- helpers.Paths({}))
- found = ds.read_config_drive(self.tmp)
- ec2_md = found['ec2-metadata']
- os_md = found['metadata']
- cfg_ds.ec2_metadata = ec2_md
- cfg_ds.metadata = os_md
- name_tests = {
- 'ami': '/dev/vda1',
- 'root': '/dev/vda1',
- 'ephemeral0': '/dev/vda2',
- 'swap': '/dev/vda3',
- None: None,
- 'bob': None,
- 'root2k': None,
- }
- for name, dev_name in name_tests.items():
- # We want os.path.exists() to return False on its first call,
- # and True on its second call. We use a handy generator as
- # the mock side effect for this. The mocked function returns
- # what the side effect returns.
- def exists_side_effect():
- yield False
- yield True
- with mock.patch.object(os.path, 'exists',
- side_effect=exists_side_effect()):
- device = cfg_ds.device_name_to_device(name)
- self.assertEqual(dev_name, device)
- # We don't assert the call count for os.path.exists() because
- # not all of the entries in name_tests results in two calls to
- # that function. Specifically, 'root2k' doesn't seem to call
- # it at all.
-
- def test_dev_ec2_map(self):
- populate_dir(self.tmp, CFG_DRIVE_FILES_V2)
- cfg_ds = ds.DataSourceConfigDrive(settings.CFG_BUILTIN,
- None,
- helpers.Paths({}))
- found = ds.read_config_drive(self.tmp)
- ec2_md = found['ec2-metadata']
- os_md = found['metadata']
- cfg_ds.ec2_metadata = ec2_md
- cfg_ds.metadata = os_md
- name_tests = {
- 'ami': '/dev/sda1',
- 'root': '/dev/sda1',
- 'ephemeral0': '/dev/sda2',
- 'swap': '/dev/sda3',
- None: None,
- 'bob': None,
- 'root2k': None,
- }
- for name, dev_name in name_tests.items():
- with mock.patch.object(os.path, 'exists', return_value=True):
- device = cfg_ds.device_name_to_device(name)
- self.assertEqual(dev_name, device)
-
- def test_dir_valid(self):
- """Verify a dir is read as such."""
-
- populate_dir(self.tmp, CFG_DRIVE_FILES_V2)
-
- found = ds.read_config_drive(self.tmp)
-
- expected_md = copy(OSTACK_META)
- expected_md['instance-id'] = expected_md['uuid']
- expected_md['local-hostname'] = expected_md['hostname']
-
- self.assertEqual(USER_DATA, found['userdata'])
- self.assertEqual(expected_md, found['metadata'])
- self.assertEqual(NETWORK_DATA, found['networkdata'])
- self.assertEqual(found['files']['/etc/foo.cfg'], CONTENT_0)
- self.assertEqual(found['files']['/etc/bar/bar.cfg'], CONTENT_1)
-
- def test_seed_dir_valid_extra(self):
- """Verify extra files do not affect datasource validity."""
-
- data = copy(CFG_DRIVE_FILES_V2)
- data["myfoofile.txt"] = "myfoocontent"
- data["openstack/latest/random-file.txt"] = "random-content"
-
- populate_dir(self.tmp, data)
-
- found = ds.read_config_drive(self.tmp)
-
- expected_md = copy(OSTACK_META)
- expected_md['instance-id'] = expected_md['uuid']
- expected_md['local-hostname'] = expected_md['hostname']
-
- self.assertEqual(expected_md, found['metadata'])
-
- def test_seed_dir_bad_json_metadata(self):
- """Verify that bad json in metadata raises BrokenConfigDriveDir."""
- data = copy(CFG_DRIVE_FILES_V2)
-
- data["openstack/2012-08-10/meta_data.json"] = "non-json garbage {}"
- data["openstack/2015-10-15/meta_data.json"] = "non-json garbage {}"
- data["openstack/latest/meta_data.json"] = "non-json garbage {}"
-
- populate_dir(self.tmp, data)
-
- self.assertRaises(openstack.BrokenMetadata,
- ds.read_config_drive, self.tmp)
-
- def test_seed_dir_no_configdrive(self):
- """Verify that no metadata raises NonConfigDriveDir."""
-
- my_d = os.path.join(self.tmp, "non-configdrive")
- data = copy(CFG_DRIVE_FILES_V2)
- data["myfoofile.txt"] = "myfoocontent"
- data["openstack/latest/random-file.txt"] = "random-content"
- data["content/foo"] = "foocontent"
-
- self.assertRaises(openstack.NonReadable,
- ds.read_config_drive, my_d)
-
- def test_seed_dir_missing(self):
- """Verify that missing seed_dir raises NonConfigDriveDir."""
- my_d = os.path.join(self.tmp, "nonexistantdirectory")
- self.assertRaises(openstack.NonReadable,
- ds.read_config_drive, my_d)
-
- def test_find_candidates(self):
- devs_with_answers = {}
-
- def my_devs_with(*args, **kwargs):
- criteria = args[0] if len(args) else kwargs.pop('criteria', None)
- return devs_with_answers.get(criteria, [])
-
- def my_is_partition(dev):
- return dev[-1] in "0123456789" and not dev.startswith("sr")
-
- try:
- orig_find_devs_with = util.find_devs_with
- util.find_devs_with = my_devs_with
-
- orig_is_partition = util.is_partition
- util.is_partition = my_is_partition
-
- devs_with_answers = {"TYPE=vfat": [],
- "TYPE=iso9660": ["/dev/vdb"],
- "LABEL=config-2": ["/dev/vdb"]}
- self.assertEqual(["/dev/vdb"], ds.find_candidate_devs())
-
- # add a vfat item
- # zdd reverse sorts after vdb, but config-2 label is preferred
- devs_with_answers['TYPE=vfat'] = ["/dev/zdd"]
- self.assertEqual(["/dev/vdb", "/dev/zdd"],
- ds.find_candidate_devs())
-
- # verify that partitions are considered, that have correct label.
- devs_with_answers = {"TYPE=vfat": ["/dev/sda1"],
- "TYPE=iso9660": [],
- "LABEL=config-2": ["/dev/vdb3"]}
- self.assertEqual(["/dev/vdb3"],
- ds.find_candidate_devs())
-
- finally:
- util.find_devs_with = orig_find_devs_with
- util.is_partition = orig_is_partition
-
- @mock.patch('cloudinit.sources.DataSourceConfigDrive.on_first_boot')
- def test_pubkeys_v2(self, on_first_boot):
- """Verify that public-keys work in config-drive-v2."""
- populate_dir(self.tmp, CFG_DRIVE_FILES_V2)
- myds = cfg_ds_from_dir(self.tmp)
- self.assertEqual(myds.get_public_ssh_keys(),
- [OSTACK_META['public_keys']['mykey']])
-
-
-class TestNetJson(TestCase):
- def setUp(self):
- super(TestNetJson, self).setUp()
- self.tmp = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp)
- self.maxDiff = None
-
- @mock.patch('cloudinit.sources.DataSourceConfigDrive.on_first_boot')
- def test_network_data_is_found(self, on_first_boot):
- """Verify that network_data is present in ds in config-drive-v2."""
- populate_dir(self.tmp, CFG_DRIVE_FILES_V2)
- myds = cfg_ds_from_dir(self.tmp)
- self.assertIsNotNone(myds.network_json)
-
- @mock.patch('cloudinit.sources.DataSourceConfigDrive.on_first_boot')
- def test_network_config_is_converted(self, on_first_boot):
- """Verify that network_data is converted and present on ds object."""
- populate_dir(self.tmp, CFG_DRIVE_FILES_V2)
- myds = cfg_ds_from_dir(self.tmp)
- network_config = openstack.convert_net_json(NETWORK_DATA,
- known_macs=KNOWN_MACS)
- self.assertEqual(myds.network_config, network_config)
-
- def test_network_config_conversions(self):
- """Tests a bunch of input network json and checks the
- expected conversions."""
- in_datas = [
- NETWORK_DATA,
- {
- 'services': [{'type': 'dns', 'address': '172.19.0.12'}],
- 'networks': [{
- 'network_id': 'dacd568d-5be6-4786-91fe-750c374b78b4',
- 'type': 'ipv4',
- 'netmask': '255.255.252.0',
- 'link': 'tap1a81968a-79',
- 'routes': [{
- 'netmask': '0.0.0.0',
- 'network': '0.0.0.0',
- 'gateway': '172.19.3.254',
- }],
- 'ip_address': '172.19.1.34',
- 'id': 'network0',
- }],
- 'links': [{
- 'type': 'bridge',
- 'vif_id': '1a81968a-797a-400f-8a80-567f997eb93f',
- 'ethernet_mac_address': 'fa:16:3e:ed:9a:59',
- 'id': 'tap1a81968a-79',
- 'mtu': None,
- }],
- },
- ]
- out_datas = [
- {
- 'version': 1,
- 'config': [
- {
- 'subnets': [{'type': 'dhcp4'}],
- 'type': 'physical',
- 'mac_address': 'fa:16:3e:69:b0:58',
- 'name': 'enp0s1',
- 'mtu': None,
- },
- {
- 'subnets': [{'type': 'dhcp4'}],
- 'type': 'physical',
- 'mac_address': 'fa:16:3e:d4:57:ad',
- 'name': 'enp0s2',
- 'mtu': None,
- },
- {
- 'subnets': [{'type': 'dhcp4'}],
- 'type': 'physical',
- 'mac_address': 'fa:16:3e:05:30:fe',
- 'name': 'nic0',
- 'mtu': None,
- },
- {
- 'type': 'nameserver',
- 'address': '199.204.44.24',
- },
- {
- 'type': 'nameserver',
- 'address': '199.204.47.54',
- }
- ],
-
- },
- {
- 'version': 1,
- 'config': [
- {
- 'name': 'foo3',
- 'mac_address': 'fa:16:3e:ed:9a:59',
- 'mtu': None,
- 'type': 'physical',
- 'subnets': [
- {
- 'address': '172.19.1.34',
- 'netmask': '255.255.252.0',
- 'type': 'static',
- 'ipv4': True,
- 'routes': [{
- 'gateway': '172.19.3.254',
- 'netmask': '0.0.0.0',
- 'network': '0.0.0.0',
- }],
- }
- ]
- },
- {
- 'type': 'nameserver',
- 'address': '172.19.0.12',
- }
- ],
- },
- ]
- for in_data, out_data in zip(in_datas, out_datas):
- conv_data = openstack.convert_net_json(in_data,
- known_macs=KNOWN_MACS)
- self.assertEqual(out_data, conv_data)
-
-
-class TestConvertNetworkData(TestCase):
- def setUp(self):
- super(TestConvertNetworkData, self).setUp()
- self.tmp = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp)
-
- def _getnames_in_config(self, ncfg):
- return set([n['name'] for n in ncfg['config']
- if n['type'] == 'physical'])
-
- def test_conversion_fills_names(self):
- ncfg = openstack.convert_net_json(NETWORK_DATA, known_macs=KNOWN_MACS)
- expected = set(['nic0', 'enp0s1', 'enp0s2'])
- found = self._getnames_in_config(ncfg)
- self.assertEqual(found, expected)
-
- @mock.patch('cloudinit.net.get_interfaces_by_mac')
- def test_convert_reads_system_prefers_name(self, get_interfaces_by_mac):
- macs = KNOWN_MACS.copy()
- macs.update({'fa:16:3e:05:30:fe': 'foonic1',
- 'fa:16:3e:69:b0:58': 'ens1'})
- get_interfaces_by_mac.return_value = macs
-
- ncfg = openstack.convert_net_json(NETWORK_DATA)
- expected = set(['nic0', 'ens1', 'enp0s2'])
- found = self._getnames_in_config(ncfg)
- self.assertEqual(found, expected)
-
- def test_convert_raises_value_error_on_missing_name(self):
- macs = {'aa:aa:aa:aa:aa:00': 'ens1'}
- self.assertRaises(ValueError, openstack.convert_net_json,
- NETWORK_DATA, known_macs=macs)
-
- def test_conversion_with_route(self):
- ncfg = openstack.convert_net_json(NETWORK_DATA_2,
- known_macs=KNOWN_MACS)
- # not the best test, but see that we get a route in the
- # network config and that it gets rendered to an ENI file
- routes = []
- for n in ncfg['config']:
- for s in n.get('subnets', []):
- routes.extend(s.get('routes', []))
- self.assertIn(
- {'network': '0.0.0.0', 'netmask': '0.0.0.0', 'gateway': '2.2.2.9'},
- routes)
- eni_renderer = eni.Renderer()
- eni_renderer.render_network_state(
- self.tmp, network_state.parse_net_config_data(ncfg))
- with open(os.path.join(self.tmp, "etc",
- "network", "interfaces"), 'r') as f:
- eni_rendering = f.read()
- self.assertIn("route add default gw 2.2.2.9", eni_rendering)
-
-
-def cfg_ds_from_dir(seed_d):
- cfg_ds = ds.DataSourceConfigDrive(settings.CFG_BUILTIN, None,
- helpers.Paths({}))
- cfg_ds.seed_dir = seed_d
- cfg_ds.known_macs = KNOWN_MACS.copy()
- if not cfg_ds.get_data():
- raise RuntimeError("Data source did not extract itself from"
- " seed directory %s" % seed_d)
- return cfg_ds
-
-
-def populate_ds_from_read_config(cfg_ds, source, results):
- """Patch the DataSourceConfigDrive from the results of
- read_config_drive_dir hopefully in line with what it would have
- if cfg_ds.get_data had been successfully called"""
- cfg_ds.source = source
- cfg_ds.metadata = results.get('metadata')
- cfg_ds.ec2_metadata = results.get('ec2-metadata')
- cfg_ds.userdata_raw = results.get('userdata')
- cfg_ds.version = results.get('version')
- cfg_ds.network_json = results.get('networkdata')
- cfg_ds._network_config = openstack.convert_net_json(
- cfg_ds.network_json, known_macs=KNOWN_MACS)
-
-
-def populate_dir(seed_dir, files):
- for (name, content) in files.items():
- path = os.path.join(seed_dir, name)
- dirname = os.path.dirname(path)
- if not os.path.isdir(dirname):
- os.makedirs(dirname)
- if isinstance(content, six.text_type):
- mode = "w"
- else:
- mode = "wb"
- with open(path, mode) as fp:
- fp.write(content)
-
-# vi: ts=4 expandtab
diff --git a/tests/unittests/test_datasource/test_digitalocean.py b/tests/unittests/test_datasource/test_digitalocean.py
deleted file mode 100644
index 8936a1e3..00000000
--- a/tests/unittests/test_datasource/test_digitalocean.py
+++ /dev/null
@@ -1,127 +0,0 @@
-#
-# Copyright (C) 2014 Neal Shrader
-#
-# Author: Neal Shrader <neal@digitalocean.com>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 3, as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-import re
-
-from six.moves.urllib_parse import urlparse
-
-from cloudinit import helpers
-from cloudinit import settings
-from cloudinit.sources import DataSourceDigitalOcean
-
-from .. import helpers as test_helpers
-
-httpretty = test_helpers.import_httpretty()
-
-# Abbreviated for the test
-DO_INDEX = """id
- hostname
- user-data
- vendor-data
- public-keys
- region"""
-
-DO_MULTIPLE_KEYS = """ssh-rsa AAAAB3NzaC1yc2EAAAA... neal@digitalocean.com
- ssh-rsa AAAAB3NzaC1yc2EAAAA... neal2@digitalocean.com"""
-DO_SINGLE_KEY = "ssh-rsa AAAAB3NzaC1yc2EAAAA... neal@digitalocean.com"
-
-DO_META = {
- '': DO_INDEX,
- 'user-data': '#!/bin/bash\necho "user-data"',
- 'vendor-data': '#!/bin/bash\necho "vendor-data"',
- 'public-keys': DO_SINGLE_KEY,
- 'region': 'nyc3',
- 'id': '2000000',
- 'hostname': 'cloudinit-test',
-}
-
-MD_URL_RE = re.compile(r'http://169.254.169.254/metadata/v1/.*')
-
-
-def _request_callback(method, uri, headers):
- url_path = urlparse(uri).path
- if url_path.startswith('/metadata/v1/'):
- path = url_path.split('/metadata/v1/')[1:][0]
- else:
- path = None
- if path in DO_META:
- return (200, headers, DO_META.get(path))
- else:
- return (404, headers, '')
-
-
-class TestDataSourceDigitalOcean(test_helpers.HttprettyTestCase):
-
- def setUp(self):
- self.ds = DataSourceDigitalOcean.DataSourceDigitalOcean(
- settings.CFG_BUILTIN, None,
- helpers.Paths({}))
- super(TestDataSourceDigitalOcean, self).setUp()
-
- @httpretty.activate
- def test_connection(self):
- httpretty.register_uri(
- httpretty.GET, MD_URL_RE,
- body=_request_callback)
-
- success = self.ds.get_data()
- self.assertTrue(success)
-
- @httpretty.activate
- def test_metadata(self):
- httpretty.register_uri(
- httpretty.GET, MD_URL_RE,
- body=_request_callback)
- self.ds.get_data()
-
- self.assertEqual(DO_META.get('user-data'),
- self.ds.get_userdata_raw())
-
- self.assertEqual(DO_META.get('vendor-data'),
- self.ds.get_vendordata_raw())
-
- self.assertEqual(DO_META.get('region'),
- self.ds.availability_zone)
-
- self.assertEqual(DO_META.get('id'),
- self.ds.get_instance_id())
-
- self.assertEqual(DO_META.get('hostname'),
- self.ds.get_hostname())
-
- self.assertEqual('http://mirrors.digitalocean.com/',
- self.ds.get_package_mirror_info())
-
- # Single key
- self.assertEqual([DO_META.get('public-keys')],
- self.ds.get_public_ssh_keys())
-
- self.assertIsInstance(self.ds.get_public_ssh_keys(), list)
-
- @httpretty.activate
- def test_multiple_ssh_keys(self):
- DO_META['public_keys'] = DO_MULTIPLE_KEYS
- httpretty.register_uri(
- httpretty.GET, MD_URL_RE,
- body=_request_callback)
- self.ds.get_data()
-
- # Multiple keys
- self.assertEqual(DO_META.get('public-keys').splitlines(),
- self.ds.get_public_ssh_keys())
-
- self.assertIsInstance(self.ds.get_public_ssh_keys(), list)
diff --git a/tests/unittests/test_datasource/test_gce.py b/tests/unittests/test_datasource/test_gce.py
deleted file mode 100644
index 6e62a4d2..00000000
--- a/tests/unittests/test_datasource/test_gce.py
+++ /dev/null
@@ -1,166 +0,0 @@
-#
-# Copyright (C) 2014 Vaidas Jablonskis
-#
-# Author: Vaidas Jablonskis <jablonskis@gmail.com>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 3, as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-import re
-
-from base64 import b64encode, b64decode
-from six.moves.urllib_parse import urlparse
-
-from cloudinit import helpers
-from cloudinit import settings
-from cloudinit.sources import DataSourceGCE
-
-from .. import helpers as test_helpers
-
-httpretty = test_helpers.import_httpretty()
-
-GCE_META = {
- 'instance/id': '123',
- 'instance/zone': 'foo/bar',
- 'project/attributes/sshKeys': 'user:ssh-rsa AA2..+aRD0fyVw== root@server',
- 'instance/hostname': 'server.project-foo.local',
- 'instance/attributes/user-data': b'/bin/echo foo\n',
-}
-
-GCE_META_PARTIAL = {
- 'instance/id': '1234',
- 'instance/hostname': 'server.project-bar.local',
- 'instance/zone': 'bar/baz',
-}
-
-GCE_META_ENCODING = {
- 'instance/id': '12345',
- 'instance/hostname': 'server.project-baz.local',
- 'instance/zone': 'baz/bang',
- 'instance/attributes/user-data': b64encode(b'/bin/echo baz\n'),
- 'instance/attributes/user-data-encoding': 'base64',
-}
-
-HEADERS = {'X-Google-Metadata-Request': 'True'}
-MD_URL_RE = re.compile(
- r'http://metadata.google.internal/computeMetadata/v1/.*')
-
-
-def _set_mock_metadata(gce_meta=None):
- if gce_meta is None:
- gce_meta = GCE_META
-
- def _request_callback(method, uri, headers):
- url_path = urlparse(uri).path
- if url_path.startswith('/computeMetadata/v1/'):
- path = url_path.split('/computeMetadata/v1/')[1:][0]
- else:
- path = None
- if path in gce_meta:
- return (200, headers, gce_meta.get(path))
- else:
- return (404, headers, '')
-
- httpretty.register_uri(httpretty.GET, MD_URL_RE, body=_request_callback)
-
-
-@httpretty.activate
-class TestDataSourceGCE(test_helpers.HttprettyTestCase):
-
- def setUp(self):
- self.ds = DataSourceGCE.DataSourceGCE(
- settings.CFG_BUILTIN, None,
- helpers.Paths({}))
- super(TestDataSourceGCE, self).setUp()
-
- def test_connection(self):
- _set_mock_metadata()
- success = self.ds.get_data()
- self.assertTrue(success)
-
- req_header = httpretty.last_request().headers
- self.assertDictContainsSubset(HEADERS, req_header)
-
- def test_metadata(self):
- _set_mock_metadata()
- self.ds.get_data()
-
- shostname = GCE_META.get('instance/hostname').split('.')[0]
- self.assertEqual(shostname,
- self.ds.get_hostname())
-
- self.assertEqual(GCE_META.get('instance/id'),
- self.ds.get_instance_id())
-
- self.assertEqual(GCE_META.get('instance/attributes/user-data'),
- self.ds.get_userdata_raw())
-
- # test partial metadata (missing user-data in particular)
- def test_metadata_partial(self):
- _set_mock_metadata(GCE_META_PARTIAL)
- self.ds.get_data()
-
- self.assertEqual(GCE_META_PARTIAL.get('instance/id'),
- self.ds.get_instance_id())
-
- shostname = GCE_META_PARTIAL.get('instance/hostname').split('.')[0]
- self.assertEqual(shostname, self.ds.get_hostname())
-
- def test_metadata_encoding(self):
- _set_mock_metadata(GCE_META_ENCODING)
- self.ds.get_data()
-
- decoded = b64decode(
- GCE_META_ENCODING.get('instance/attributes/user-data'))
- self.assertEqual(decoded, self.ds.get_userdata_raw())
-
- def test_missing_required_keys_return_false(self):
- for required_key in ['instance/id', 'instance/zone',
- 'instance/hostname']:
- meta = GCE_META_PARTIAL.copy()
- del meta[required_key]
- _set_mock_metadata(meta)
- self.assertEqual(False, self.ds.get_data())
- httpretty.reset()
-
- def test_project_level_ssh_keys_are_used(self):
- _set_mock_metadata()
- self.ds.get_data()
-
- # we expect a list of public ssh keys with user names stripped
- self.assertEqual(['ssh-rsa AA2..+aRD0fyVw== root@server'],
- self.ds.get_public_ssh_keys())
-
- def test_instance_level_ssh_keys_are_used(self):
- key_content = 'ssh-rsa JustAUser root@server'
- meta = GCE_META.copy()
- meta['instance/attributes/sshKeys'] = 'user:{0}'.format(key_content)
-
- _set_mock_metadata(meta)
- self.ds.get_data()
-
- self.assertIn(key_content, self.ds.get_public_ssh_keys())
-
- def test_instance_level_keys_replace_project_level_keys(self):
- key_content = 'ssh-rsa JustAUser root@server'
- meta = GCE_META.copy()
- meta['instance/attributes/sshKeys'] = 'user:{0}'.format(key_content)
-
- _set_mock_metadata(meta)
- self.ds.get_data()
-
- self.assertEqual([key_content], self.ds.get_public_ssh_keys())
-
- def test_only_last_part_of_zone_used_for_availability_zone(self):
- _set_mock_metadata()
- self.ds.get_data()
- self.assertEqual('bar', self.ds.availability_zone)
diff --git a/tests/unittests/test_datasource/test_maas.py b/tests/unittests/test_datasource/test_maas.py
deleted file mode 100644
index f66f1c6d..00000000
--- a/tests/unittests/test_datasource/test_maas.py
+++ /dev/null
@@ -1,163 +0,0 @@
-from copy import copy
-import os
-import shutil
-import tempfile
-
-from cloudinit.sources import DataSourceMAAS
-from cloudinit import url_helper
-from ..helpers import TestCase, populate_dir
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-
-
-class TestMAASDataSource(TestCase):
-
- def setUp(self):
- super(TestMAASDataSource, self).setUp()
- # Make a temp directoy for tests to use.
- self.tmp = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp)
-
- def test_seed_dir_valid(self):
- """Verify a valid seeddir is read as such."""
-
- data = {'instance-id': 'i-valid01',
- 'local-hostname': 'valid01-hostname',
- 'user-data': b'valid01-userdata',
- 'public-keys': 'ssh-rsa AAAAB3Nz...aC1yc2E= keyname'}
-
- my_d = os.path.join(self.tmp, "valid")
- populate_dir(my_d, data)
-
- (userdata, metadata) = DataSourceMAAS.read_maas_seed_dir(my_d)
-
- self.assertEqual(userdata, data['user-data'])
- for key in ('instance-id', 'local-hostname'):
- self.assertEqual(data[key], metadata[key])
-
- # verify that 'userdata' is not returned as part of the metadata
- self.assertFalse(('user-data' in metadata))
-
- def test_seed_dir_valid_extra(self):
- """Verify extra files do not affect seed_dir validity."""
-
- data = {'instance-id': 'i-valid-extra',
- 'local-hostname': 'valid-extra-hostname',
- 'user-data': b'valid-extra-userdata', 'foo': 'bar'}
-
- my_d = os.path.join(self.tmp, "valid_extra")
- populate_dir(my_d, data)
-
- (userdata, metadata) = DataSourceMAAS.read_maas_seed_dir(my_d)
-
- self.assertEqual(userdata, data['user-data'])
- for key in ('instance-id', 'local-hostname'):
- self.assertEqual(data[key], metadata[key])
-
- # additional files should not just appear as keys in metadata atm
- self.assertFalse(('foo' in metadata))
-
- def test_seed_dir_invalid(self):
- """Verify that invalid seed_dir raises MAASSeedDirMalformed."""
-
- valid = {'instance-id': 'i-instanceid',
- 'local-hostname': 'test-hostname', 'user-data': ''}
-
- my_based = os.path.join(self.tmp, "valid_extra")
-
- # missing 'userdata' file
- my_d = "%s-01" % my_based
- invalid_data = copy(valid)
- del invalid_data['local-hostname']
- populate_dir(my_d, invalid_data)
- self.assertRaises(DataSourceMAAS.MAASSeedDirMalformed,
- DataSourceMAAS.read_maas_seed_dir, my_d)
-
- # missing 'instance-id'
- my_d = "%s-02" % my_based
- invalid_data = copy(valid)
- del invalid_data['instance-id']
- populate_dir(my_d, invalid_data)
- self.assertRaises(DataSourceMAAS.MAASSeedDirMalformed,
- DataSourceMAAS.read_maas_seed_dir, my_d)
-
- def test_seed_dir_none(self):
- """Verify that empty seed_dir raises MAASSeedDirNone."""
-
- my_d = os.path.join(self.tmp, "valid_empty")
- self.assertRaises(DataSourceMAAS.MAASSeedDirNone,
- DataSourceMAAS.read_maas_seed_dir, my_d)
-
- def test_seed_dir_missing(self):
- """Verify that missing seed_dir raises MAASSeedDirNone."""
- self.assertRaises(DataSourceMAAS.MAASSeedDirNone,
- DataSourceMAAS.read_maas_seed_dir,
- os.path.join(self.tmp, "nonexistantdirectory"))
-
- def test_seed_url_valid(self):
- """Verify that valid seed_url is read as such."""
- valid = {
- 'meta-data/instance-id': 'i-instanceid',
- 'meta-data/local-hostname': 'test-hostname',
- 'meta-data/public-keys': 'test-hostname',
- 'user-data': b'foodata',
- }
- valid_order = [
- 'meta-data/local-hostname',
- 'meta-data/instance-id',
- 'meta-data/public-keys',
- 'user-data',
- ]
- my_seed = "http://example.com/xmeta"
- my_ver = "1999-99-99"
- my_headers = {'header1': 'value1', 'header2': 'value2'}
-
- def my_headers_cb(url):
- return my_headers
-
- # Each time url_helper.readurl() is called, something different is
- # returned based on the canned data above. We need to build up a list
- # of side effect return values, which the mock will return. At the
- # same time, we'll build up a list of expected call arguments for
- # asserting after the code under test is run.
- calls = []
-
- def side_effect():
- for key in valid_order:
- resp = valid.get(key)
- url = "%s/%s/%s" % (my_seed, my_ver, key)
- calls.append(
- mock.call(url, headers=None, timeout=mock.ANY,
- data=mock.ANY, sec_between=mock.ANY,
- ssl_details=mock.ANY, retries=mock.ANY,
- headers_cb=my_headers_cb,
- exception_cb=mock.ANY))
- yield url_helper.StringResponse(resp)
-
- # Now do the actual call of the code under test.
- with mock.patch.object(url_helper, 'readurl',
- side_effect=side_effect()) as mockobj:
- userdata, metadata = DataSourceMAAS.read_maas_seed_url(
- my_seed, version=my_ver)
-
- self.assertEqual(b"foodata", userdata)
- self.assertEqual(metadata['instance-id'],
- valid['meta-data/instance-id'])
- self.assertEqual(metadata['local-hostname'],
- valid['meta-data/local-hostname'])
-
- mockobj.has_calls(calls)
-
- def test_seed_url_invalid(self):
- """Verify that invalid seed_url raises MAASSeedDirMalformed."""
- pass
-
- def test_seed_url_missing(self):
- """Verify seed_url with no found entries raises MAASSeedDirNone."""
- pass
-
-
-# vi: ts=4 expandtab
diff --git a/tests/unittests/test_datasource/test_nocloud.py b/tests/unittests/test_datasource/test_nocloud.py
deleted file mode 100644
index b0fa1130..00000000
--- a/tests/unittests/test_datasource/test_nocloud.py
+++ /dev/null
@@ -1,178 +0,0 @@
-from cloudinit import helpers
-from cloudinit.sources import DataSourceNoCloud
-from cloudinit import util
-from ..helpers import TestCase, populate_dir, mock, ExitStack
-
-import os
-import shutil
-import tempfile
-
-import yaml
-
-
-class TestNoCloudDataSource(TestCase):
-
- def setUp(self):
- super(TestNoCloudDataSource, self).setUp()
- self.tmp = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp)
- self.paths = helpers.Paths({'cloud_dir': self.tmp})
-
- self.cmdline = "root=TESTCMDLINE"
-
- self.mocks = ExitStack()
- self.addCleanup(self.mocks.close)
-
- self.mocks.enter_context(
- mock.patch.object(util, 'get_cmdline', return_value=self.cmdline))
-
- def test_nocloud_seed_dir(self):
- md = {'instance-id': 'IID', 'dsmode': 'local'}
- ud = b"USER_DATA_HERE"
- populate_dir(os.path.join(self.paths.seed_dir, "nocloud"),
- {'user-data': ud, 'meta-data': yaml.safe_dump(md)})
-
- sys_cfg = {
- 'datasource': {'NoCloud': {'fs_label': None}}
- }
-
- ds = DataSourceNoCloud.DataSourceNoCloud
-
- dsrc = ds(sys_cfg=sys_cfg, distro=None, paths=self.paths)
- ret = dsrc.get_data()
- self.assertEqual(dsrc.userdata_raw, ud)
- self.assertEqual(dsrc.metadata, md)
- self.assertTrue(ret)
-
- def test_fs_label(self):
- # find_devs_with should not be called ff fs_label is None
- ds = DataSourceNoCloud.DataSourceNoCloud
-
- class PsuedoException(Exception):
- pass
-
- def my_find_devs_with(*args, **kwargs):
- raise PsuedoException
-
- self.mocks.enter_context(
- mock.patch.object(util, 'find_devs_with',
- side_effect=PsuedoException))
-
- # by default, NoCloud should search for filesystems by label
- sys_cfg = {'datasource': {'NoCloud': {}}}
- dsrc = ds(sys_cfg=sys_cfg, distro=None, paths=self.paths)
- self.assertRaises(PsuedoException, dsrc.get_data)
-
- # but disabling searching should just end up with None found
- sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}
- dsrc = ds(sys_cfg=sys_cfg, distro=None, paths=self.paths)
- ret = dsrc.get_data()
- self.assertFalse(ret)
-
- def test_no_datasource_expected(self):
- # no source should be found if no cmdline, config, and fs_label=None
- sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}
-
- ds = DataSourceNoCloud.DataSourceNoCloud
- dsrc = ds(sys_cfg=sys_cfg, distro=None, paths=self.paths)
- self.assertFalse(dsrc.get_data())
-
- def test_seed_in_config(self):
- ds = DataSourceNoCloud.DataSourceNoCloud
-
- data = {
- 'fs_label': None,
- 'meta-data': yaml.safe_dump({'instance-id': 'IID'}),
- 'user-data': b"USER_DATA_RAW",
- }
-
- sys_cfg = {'datasource': {'NoCloud': data}}
- dsrc = ds(sys_cfg=sys_cfg, distro=None, paths=self.paths)
- ret = dsrc.get_data()
- self.assertEqual(dsrc.userdata_raw, b"USER_DATA_RAW")
- self.assertEqual(dsrc.metadata.get('instance-id'), 'IID')
- self.assertTrue(ret)
-
- def test_nocloud_seed_with_vendordata(self):
- md = {'instance-id': 'IID', 'dsmode': 'local'}
- ud = b"USER_DATA_HERE"
- vd = b"THIS IS MY VENDOR_DATA"
-
- populate_dir(os.path.join(self.paths.seed_dir, "nocloud"),
- {'user-data': ud, 'meta-data': yaml.safe_dump(md),
- 'vendor-data': vd})
-
- sys_cfg = {
- 'datasource': {'NoCloud': {'fs_label': None}}
- }
-
- ds = DataSourceNoCloud.DataSourceNoCloud
-
- dsrc = ds(sys_cfg=sys_cfg, distro=None, paths=self.paths)
- ret = dsrc.get_data()
- self.assertEqual(dsrc.userdata_raw, ud)
- self.assertEqual(dsrc.metadata, md)
- self.assertEqual(dsrc.vendordata_raw, vd)
- self.assertTrue(ret)
-
- def test_nocloud_no_vendordata(self):
- populate_dir(os.path.join(self.paths.seed_dir, "nocloud"),
- {'user-data': b"ud", 'meta-data': "instance-id: IID\n"})
-
- sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}
-
- ds = DataSourceNoCloud.DataSourceNoCloud
-
- dsrc = ds(sys_cfg=sys_cfg, distro=None, paths=self.paths)
- ret = dsrc.get_data()
- self.assertEqual(dsrc.userdata_raw, b"ud")
- self.assertFalse(dsrc.vendordata)
- self.assertTrue(ret)
-
-
-class TestParseCommandLineData(TestCase):
-
- def test_parse_cmdline_data_valid(self):
- ds_id = "ds=nocloud"
- pairs = (
- ("root=/dev/sda1 %(ds_id)s", {}),
- ("%(ds_id)s; root=/dev/foo", {}),
- ("%(ds_id)s", {}),
- ("%(ds_id)s;", {}),
- ("%(ds_id)s;s=SEED", {'seedfrom': 'SEED'}),
- ("%(ds_id)s;seedfrom=SEED;local-hostname=xhost",
- {'seedfrom': 'SEED', 'local-hostname': 'xhost'}),
- ("%(ds_id)s;h=xhost",
- {'local-hostname': 'xhost'}),
- ("%(ds_id)s;h=xhost;i=IID",
- {'local-hostname': 'xhost', 'instance-id': 'IID'}),
- )
-
- for (fmt, expected) in pairs:
- fill = {}
- cmdline = fmt % {'ds_id': ds_id}
- ret = DataSourceNoCloud.parse_cmdline_data(ds_id=ds_id, fill=fill,
- cmdline=cmdline)
- self.assertEqual(expected, fill)
- self.assertTrue(ret)
-
- def test_parse_cmdline_data_none(self):
- ds_id = "ds=foo"
- cmdlines = (
- "root=/dev/sda1 ro",
- "console=/dev/ttyS0 root=/dev/foo",
- "",
- "ds=foocloud",
- "ds=foo-net",
- "ds=nocloud;s=SEED",
- )
-
- for cmdline in cmdlines:
- fill = {}
- ret = DataSourceNoCloud.parse_cmdline_data(ds_id=ds_id, fill=fill,
- cmdline=cmdline)
- self.assertEqual(fill, {})
- self.assertFalse(ret)
-
-
-# vi: ts=4 expandtab
diff --git a/tests/unittests/test_datasource/test_opennebula.py b/tests/unittests/test_datasource/test_opennebula.py
deleted file mode 100644
index d796f030..00000000
--- a/tests/unittests/test_datasource/test_opennebula.py
+++ /dev/null
@@ -1,300 +0,0 @@
-from cloudinit import helpers
-from cloudinit.sources import DataSourceOpenNebula as ds
-from cloudinit import util
-from ..helpers import TestCase, populate_dir
-
-import os
-import pwd
-import shutil
-import tempfile
-import unittest
-
-
-TEST_VARS = {
- 'VAR1': 'single',
- 'VAR2': 'double word',
- 'VAR3': 'multi\nline\n',
- 'VAR4': "'single'",
- 'VAR5': "'double word'",
- 'VAR6': "'multi\nline\n'",
- 'VAR7': 'single\\t',
- 'VAR8': 'double\\tword',
- 'VAR9': 'multi\\t\nline\n',
- 'VAR10': '\\', # expect '\'
- 'VAR11': '\'', # expect '
- 'VAR12': '$', # expect $
-}
-
-INVALID_CONTEXT = ';'
-USER_DATA = '#cloud-config\napt_upgrade: true'
-SSH_KEY = 'ssh-rsa AAAAB3NzaC1....sIkJhq8wdX+4I3A4cYbYP ubuntu@server-460-%i'
-HOSTNAME = 'foo.example.com'
-PUBLIC_IP = '10.0.0.3'
-
-CMD_IP_OUT = '''\
-1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
- link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
-2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
- link/ether 02:00:0a:12:01:01 brd ff:ff:ff:ff:ff:ff
-'''
-
-
-class TestOpenNebulaDataSource(TestCase):
- parsed_user = None
-
- def setUp(self):
- super(TestOpenNebulaDataSource, self).setUp()
- self.tmp = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp)
- self.paths = helpers.Paths({'cloud_dir': self.tmp})
-
- # defaults for few tests
- self.ds = ds.DataSourceOpenNebula
- self.seed_dir = os.path.join(self.paths.seed_dir, "opennebula")
- self.sys_cfg = {'datasource': {'OpenNebula': {'dsmode': 'local'}}}
-
- # we don't want 'sudo' called in tests. so we patch switch_user_cmd
- def my_switch_user_cmd(user):
- self.parsed_user = user
- return []
-
- self.switch_user_cmd_real = ds.switch_user_cmd
- ds.switch_user_cmd = my_switch_user_cmd
-
- def tearDown(self):
- ds.switch_user_cmd = self.switch_user_cmd_real
- super(TestOpenNebulaDataSource, self).tearDown()
-
- def test_get_data_non_contextdisk(self):
- orig_find_devs_with = util.find_devs_with
- try:
- # dont' try to lookup for CDs
- util.find_devs_with = lambda n: []
- dsrc = self.ds(sys_cfg=self.sys_cfg, distro=None, paths=self.paths)
- ret = dsrc.get_data()
- self.assertFalse(ret)
- finally:
- util.find_devs_with = orig_find_devs_with
-
- def test_get_data_broken_contextdisk(self):
- orig_find_devs_with = util.find_devs_with
- try:
- # dont' try to lookup for CDs
- util.find_devs_with = lambda n: []
- populate_dir(self.seed_dir, {'context.sh': INVALID_CONTEXT})
- dsrc = self.ds(sys_cfg=self.sys_cfg, distro=None, paths=self.paths)
- self.assertRaises(ds.BrokenContextDiskDir, dsrc.get_data)
- finally:
- util.find_devs_with = orig_find_devs_with
-
- def test_get_data_invalid_identity(self):
- orig_find_devs_with = util.find_devs_with
- try:
- # generate non-existing system user name
- sys_cfg = self.sys_cfg
- invalid_user = 'invalid'
- while not sys_cfg['datasource']['OpenNebula'].get('parseuser'):
- try:
- pwd.getpwnam(invalid_user)
- invalid_user += 'X'
- except KeyError:
- sys_cfg['datasource']['OpenNebula']['parseuser'] = \
- invalid_user
-
- # dont' try to lookup for CDs
- util.find_devs_with = lambda n: []
- populate_context_dir(self.seed_dir, {'KEY1': 'val1'})
- dsrc = self.ds(sys_cfg=sys_cfg, distro=None, paths=self.paths)
- self.assertRaises(ds.BrokenContextDiskDir, dsrc.get_data)
- finally:
- util.find_devs_with = orig_find_devs_with
-
- def test_get_data(self):
- orig_find_devs_with = util.find_devs_with
- try:
- # dont' try to lookup for CDs
- util.find_devs_with = lambda n: []
- populate_context_dir(self.seed_dir, {'KEY1': 'val1'})
- dsrc = self.ds(sys_cfg=self.sys_cfg, distro=None, paths=self.paths)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- finally:
- util.find_devs_with = orig_find_devs_with
-
- def test_seed_dir_non_contextdisk(self):
- self.assertRaises(ds.NonContextDiskDir, ds.read_context_disk_dir,
- self.seed_dir)
-
- def test_seed_dir_empty1_context(self):
- populate_dir(self.seed_dir, {'context.sh': ''})
- results = ds.read_context_disk_dir(self.seed_dir)
-
- self.assertEqual(results['userdata'], None)
- self.assertEqual(results['metadata'], {})
-
- def test_seed_dir_empty2_context(self):
- populate_context_dir(self.seed_dir, {})
- results = ds.read_context_disk_dir(self.seed_dir)
-
- self.assertEqual(results['userdata'], None)
- self.assertEqual(results['metadata'], {})
-
- def test_seed_dir_broken_context(self):
- populate_dir(self.seed_dir, {'context.sh': INVALID_CONTEXT})
-
- self.assertRaises(ds.BrokenContextDiskDir,
- ds.read_context_disk_dir,
- self.seed_dir)
-
- def test_context_parser(self):
- populate_context_dir(self.seed_dir, TEST_VARS)
- results = ds.read_context_disk_dir(self.seed_dir)
-
- self.assertTrue('metadata' in results)
- self.assertEqual(TEST_VARS, results['metadata'])
-
- def test_ssh_key(self):
- public_keys = ['first key', 'second key']
- for c in range(4):
- for k in ('SSH_KEY', 'SSH_PUBLIC_KEY'):
- my_d = os.path.join(self.tmp, "%s-%i" % (k, c))
- populate_context_dir(my_d, {k: '\n'.join(public_keys)})
- results = ds.read_context_disk_dir(my_d)
-
- self.assertTrue('metadata' in results)
- self.assertTrue('public-keys' in results['metadata'])
- self.assertEqual(public_keys,
- results['metadata']['public-keys'])
-
- public_keys.append(SSH_KEY % (c + 1,))
-
- def test_user_data_plain(self):
- for k in ('USER_DATA', 'USERDATA'):
- my_d = os.path.join(self.tmp, k)
- populate_context_dir(my_d, {k: USER_DATA,
- 'USERDATA_ENCODING': ''})
- results = ds.read_context_disk_dir(my_d)
-
- self.assertTrue('userdata' in results)
- self.assertEqual(USER_DATA, results['userdata'])
-
- def test_user_data_encoding_required_for_decode(self):
- b64userdata = util.b64e(USER_DATA)
- for k in ('USER_DATA', 'USERDATA'):
- my_d = os.path.join(self.tmp, k)
- populate_context_dir(my_d, {k: b64userdata})
- results = ds.read_context_disk_dir(my_d)
-
- self.assertTrue('userdata' in results)
- self.assertEqual(b64userdata, results['userdata'])
-
- def test_user_data_base64_encoding(self):
- for k in ('USER_DATA', 'USERDATA'):
- my_d = os.path.join(self.tmp, k)
- populate_context_dir(my_d, {k: util.b64e(USER_DATA),
- 'USERDATA_ENCODING': 'base64'})
- results = ds.read_context_disk_dir(my_d)
-
- self.assertTrue('userdata' in results)
- self.assertEqual(USER_DATA, results['userdata'])
-
- def test_hostname(self):
- for k in ('HOSTNAME', 'PUBLIC_IP', 'IP_PUBLIC', 'ETH0_IP'):
- my_d = os.path.join(self.tmp, k)
- populate_context_dir(my_d, {k: PUBLIC_IP})
- results = ds.read_context_disk_dir(my_d)
-
- self.assertTrue('metadata' in results)
- self.assertTrue('local-hostname' in results['metadata'])
- self.assertEqual(PUBLIC_IP, results['metadata']['local-hostname'])
-
- def test_network_interfaces(self):
- populate_context_dir(self.seed_dir, {'ETH0_IP': '1.2.3.4'})
- results = ds.read_context_disk_dir(self.seed_dir)
-
- self.assertTrue('network-interfaces' in results)
-
- def test_find_candidates(self):
- def my_devs_with(criteria):
- return {
- "LABEL=CONTEXT": ["/dev/sdb"],
- "LABEL=CDROM": ["/dev/sr0"],
- "TYPE=iso9660": ["/dev/vdb"],
- }.get(criteria, [])
-
- orig_find_devs_with = util.find_devs_with
- try:
- util.find_devs_with = my_devs_with
- self.assertEqual(["/dev/sdb", "/dev/sr0", "/dev/vdb"],
- ds.find_candidate_devs())
- finally:
- util.find_devs_with = orig_find_devs_with
-
-
-class TestOpenNebulaNetwork(unittest.TestCase):
-
- def setUp(self):
- super(TestOpenNebulaNetwork, self).setUp()
-
- def test_lo(self):
- net = ds.OpenNebulaNetwork('', {})
- self.assertEqual(net.gen_conf(), u'''\
-auto lo
-iface lo inet loopback
-''')
-
- def test_eth0(self):
- net = ds.OpenNebulaNetwork(CMD_IP_OUT, {})
- self.assertEqual(net.gen_conf(), u'''\
-auto lo
-iface lo inet loopback
-
-auto eth0
-iface eth0 inet static
- address 10.18.1.1
- network 10.18.1.0
- netmask 255.255.255.0
-''')
-
- def test_eth0_override(self):
- context = {
- 'DNS': '1.2.3.8',
- 'ETH0_IP': '1.2.3.4',
- 'ETH0_NETWORK': '1.2.3.0',
- 'ETH0_MASK': '255.255.0.0',
- 'ETH0_GATEWAY': '1.2.3.5',
- 'ETH0_DOMAIN': 'example.com',
- 'ETH0_DNS': '1.2.3.6 1.2.3.7'
- }
-
- net = ds.OpenNebulaNetwork(CMD_IP_OUT, context)
- self.assertEqual(net.gen_conf(), u'''\
-auto lo
-iface lo inet loopback
-
-auto eth0
-iface eth0 inet static
- address 1.2.3.4
- network 1.2.3.0
- netmask 255.255.0.0
- gateway 1.2.3.5
- dns-search example.com
- dns-nameservers 1.2.3.8 1.2.3.6 1.2.3.7
-''')
-
-
-class TestParseShellConfig(unittest.TestCase):
- def test_no_seconds(self):
- cfg = '\n'.join(["foo=bar", "SECONDS=2", "xx=foo"])
- # we could test 'sleep 2', but that would make the test run slower.
- ret = ds.parse_shell_config(cfg)
- self.assertEqual(ret, {"foo": "bar", "xx": "foo"})
-
-
-def populate_context_dir(path, variables):
- data = "# Context variables generated by OpenNebula\n"
- for k, v in variables.items():
- data += ("%s='%s'\n" % (k.upper(), v.replace(r"'", r"'\''")))
- populate_dir(path, {'context.sh': data})
-
-# vi: ts=4 expandtab
diff --git a/tests/unittests/test_datasource/test_openstack.py b/tests/unittests/test_datasource/test_openstack.py
deleted file mode 100644
index 5c8592c5..00000000
--- a/tests/unittests/test_datasource/test_openstack.py
+++ /dev/null
@@ -1,347 +0,0 @@
-# vi: ts=4 expandtab
-#
-# Copyright (C) 2014 Yahoo! Inc.
-#
-# Author: Joshua Harlow <harlowja@yahoo-inc.com>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 3, as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-import copy
-import json
-import re
-
-from .. import helpers as test_helpers
-
-from six.moves.urllib.parse import urlparse
-from six import StringIO
-
-from cloudinit import helpers
-from cloudinit import settings
-from cloudinit.sources import DataSourceOpenStack as ds
-from cloudinit.sources.helpers import openstack
-from cloudinit import util
-
-hp = test_helpers.import_httpretty()
-
-BASE_URL = "http://169.254.169.254"
-PUBKEY = u'ssh-rsa AAAAB3NzaC1....sIkJhq8wdX+4I3A4cYbYP ubuntu@server-460\n'
-EC2_META = {
- 'ami-id': 'ami-00000001',
- 'ami-launch-index': '0',
- 'ami-manifest-path': 'FIXME',
- 'hostname': 'sm-foo-test.novalocal',
- 'instance-action': 'none',
- 'instance-id': 'i-00000001',
- 'instance-type': 'm1.tiny',
- 'local-hostname': 'sm-foo-test.novalocal',
- 'local-ipv4': '0.0.0.0',
- 'public-hostname': 'sm-foo-test.novalocal',
- 'public-ipv4': '0.0.0.1',
- 'reservation-id': 'r-iru5qm4m',
-}
-USER_DATA = b'#!/bin/sh\necho This is user data\n'
-VENDOR_DATA = {
- 'magic': '',
-}
-OSTACK_META = {
- 'availability_zone': 'nova',
- 'files': [{'content_path': '/content/0000', 'path': '/etc/foo.cfg'},
- {'content_path': '/content/0001', 'path': '/etc/bar/bar.cfg'}],
- 'hostname': 'sm-foo-test.novalocal',
- 'meta': {'dsmode': 'local', 'my-meta': 'my-value'},
- 'name': 'sm-foo-test',
- 'public_keys': {'mykey': PUBKEY},
- 'uuid': 'b0fa911b-69d4-4476-bbe2-1c92bff6535c',
-}
-CONTENT_0 = b'This is contents of /etc/foo.cfg\n'
-CONTENT_1 = b'# this is /etc/bar/bar.cfg\n'
-OS_FILES = {
- 'openstack/latest/meta_data.json': json.dumps(OSTACK_META),
- 'openstack/latest/user_data': USER_DATA,
- 'openstack/content/0000': CONTENT_0,
- 'openstack/content/0001': CONTENT_1,
- 'openstack/latest/meta_data.json': json.dumps(OSTACK_META),
- 'openstack/latest/user_data': USER_DATA,
- 'openstack/latest/vendor_data.json': json.dumps(VENDOR_DATA),
-}
-EC2_FILES = {
- 'latest/user-data': USER_DATA,
-}
-EC2_VERSIONS = [
- 'latest',
-]
-
-
-def _register_uris(version, ec2_files, ec2_meta, os_files):
- """Registers a set of url patterns into httpretty that will mimic the
- same data returned by the openstack metadata service (and ec2 service)."""
-
- def match_ec2_url(uri, headers):
- path = uri.path.strip("/")
- if len(path) == 0:
- return (200, headers, "\n".join(EC2_VERSIONS))
- path = uri.path.lstrip("/")
- if path in ec2_files:
- return (200, headers, ec2_files.get(path))
- if path == 'latest/meta-data/':
- buf = StringIO()
- for (k, v) in ec2_meta.items():
- if isinstance(v, (list, tuple)):
- buf.write("%s/" % (k))
- else:
- buf.write("%s" % (k))
- buf.write("\n")
- return (200, headers, buf.getvalue())
- if path.startswith('latest/meta-data/'):
- value = None
- pieces = path.split("/")
- if path.endswith("/"):
- pieces = pieces[2:-1]
- value = util.get_cfg_by_path(ec2_meta, pieces)
- else:
- pieces = pieces[2:]
- value = util.get_cfg_by_path(ec2_meta, pieces)
- if value is not None:
- return (200, headers, str(value))
- return (404, headers, '')
-
- def match_os_uri(uri, headers):
- path = uri.path.strip("/")
- if path == 'openstack':
- return (200, headers, "\n".join([openstack.OS_LATEST]))
- path = uri.path.lstrip("/")
- if path in os_files:
- return (200, headers, os_files.get(path))
- return (404, headers, '')
-
- def get_request_callback(method, uri, headers):
- uri = urlparse(uri)
- path = uri.path.lstrip("/").split("/")
- if path[0] == 'openstack':
- return match_os_uri(uri, headers)
- return match_ec2_url(uri, headers)
-
- hp.register_uri(hp.GET, re.compile(r'http://169.254.169.254/.*'),
- body=get_request_callback)
-
-
-def _read_metadata_service():
- return ds.read_metadata_service(BASE_URL, retries=0, timeout=0.1)
-
-
-class TestOpenStackDataSource(test_helpers.HttprettyTestCase):
- VERSION = 'latest'
-
- @hp.activate
- def test_successful(self):
- _register_uris(self.VERSION, EC2_FILES, EC2_META, OS_FILES)
- f = _read_metadata_service()
- self.assertEqual(VENDOR_DATA, f.get('vendordata'))
- self.assertEqual(CONTENT_0, f['files']['/etc/foo.cfg'])
- self.assertEqual(CONTENT_1, f['files']['/etc/bar/bar.cfg'])
- self.assertEqual(2, len(f['files']))
- self.assertEqual(USER_DATA, f.get('userdata'))
- self.assertEqual(EC2_META, f.get('ec2-metadata'))
- self.assertEqual(2, f.get('version'))
- metadata = f['metadata']
- self.assertEqual('nova', metadata.get('availability_zone'))
- self.assertEqual('sm-foo-test.novalocal', metadata.get('hostname'))
- self.assertEqual('sm-foo-test.novalocal',
- metadata.get('local-hostname'))
- self.assertEqual('sm-foo-test', metadata.get('name'))
- self.assertEqual('b0fa911b-69d4-4476-bbe2-1c92bff6535c',
- metadata.get('uuid'))
- self.assertEqual('b0fa911b-69d4-4476-bbe2-1c92bff6535c',
- metadata.get('instance-id'))
-
- @hp.activate
- def test_no_ec2(self):
- _register_uris(self.VERSION, {}, {}, OS_FILES)
- f = _read_metadata_service()
- self.assertEqual(VENDOR_DATA, f.get('vendordata'))
- self.assertEqual(CONTENT_0, f['files']['/etc/foo.cfg'])
- self.assertEqual(CONTENT_1, f['files']['/etc/bar/bar.cfg'])
- self.assertEqual(USER_DATA, f.get('userdata'))
- self.assertEqual({}, f.get('ec2-metadata'))
- self.assertEqual(2, f.get('version'))
-
- @hp.activate
- def test_bad_metadata(self):
- os_files = copy.deepcopy(OS_FILES)
- for k in list(os_files.keys()):
- if k.endswith('meta_data.json'):
- os_files.pop(k, None)
- _register_uris(self.VERSION, {}, {}, os_files)
- self.assertRaises(openstack.NonReadable, _read_metadata_service)
-
- @hp.activate
- def test_bad_uuid(self):
- os_files = copy.deepcopy(OS_FILES)
- os_meta = copy.deepcopy(OSTACK_META)
- os_meta.pop('uuid')
- for k in list(os_files.keys()):
- if k.endswith('meta_data.json'):
- os_files[k] = json.dumps(os_meta)
- _register_uris(self.VERSION, {}, {}, os_files)
- self.assertRaises(openstack.BrokenMetadata, _read_metadata_service)
-
- @hp.activate
- def test_userdata_empty(self):
- os_files = copy.deepcopy(OS_FILES)
- for k in list(os_files.keys()):
- if k.endswith('user_data'):
- os_files.pop(k, None)
- _register_uris(self.VERSION, {}, {}, os_files)
- f = _read_metadata_service()
- self.assertEqual(VENDOR_DATA, f.get('vendordata'))
- self.assertEqual(CONTENT_0, f['files']['/etc/foo.cfg'])
- self.assertEqual(CONTENT_1, f['files']['/etc/bar/bar.cfg'])
- self.assertFalse(f.get('userdata'))
-
- @hp.activate
- def test_vendordata_empty(self):
- os_files = copy.deepcopy(OS_FILES)
- for k in list(os_files.keys()):
- if k.endswith('vendor_data.json'):
- os_files.pop(k, None)
- _register_uris(self.VERSION, {}, {}, os_files)
- f = _read_metadata_service()
- self.assertEqual(CONTENT_0, f['files']['/etc/foo.cfg'])
- self.assertEqual(CONTENT_1, f['files']['/etc/bar/bar.cfg'])
- self.assertFalse(f.get('vendordata'))
-
- @hp.activate
- def test_vendordata_invalid(self):
- os_files = copy.deepcopy(OS_FILES)
- for k in list(os_files.keys()):
- if k.endswith('vendor_data.json'):
- os_files[k] = '{' # some invalid json
- _register_uris(self.VERSION, {}, {}, os_files)
- self.assertRaises(openstack.BrokenMetadata, _read_metadata_service)
-
- @hp.activate
- def test_metadata_invalid(self):
- os_files = copy.deepcopy(OS_FILES)
- for k in list(os_files.keys()):
- if k.endswith('meta_data.json'):
- os_files[k] = '{' # some invalid json
- _register_uris(self.VERSION, {}, {}, os_files)
- self.assertRaises(openstack.BrokenMetadata, _read_metadata_service)
-
- @hp.activate
- def test_datasource(self):
- _register_uris(self.VERSION, EC2_FILES, EC2_META, OS_FILES)
- ds_os = ds.DataSourceOpenStack(settings.CFG_BUILTIN,
- None,
- helpers.Paths({}))
- self.assertIsNone(ds_os.version)
- found = ds_os.get_data(timeout=0.1, retries=0)
- self.assertTrue(found)
- self.assertEqual(2, ds_os.version)
- md = dict(ds_os.metadata)
- md.pop('instance-id', None)
- md.pop('local-hostname', None)
- self.assertEqual(OSTACK_META, md)
- self.assertEqual(EC2_META, ds_os.ec2_metadata)
- self.assertEqual(USER_DATA, ds_os.userdata_raw)
- self.assertEqual(2, len(ds_os.files))
- self.assertEqual(VENDOR_DATA, ds_os.vendordata_pure)
- self.assertEqual(ds_os.vendordata_raw, None)
-
- @hp.activate
- def test_bad_datasource_meta(self):
- os_files = copy.deepcopy(OS_FILES)
- for k in list(os_files.keys()):
- if k.endswith('meta_data.json'):
- os_files[k] = '{' # some invalid json
- _register_uris(self.VERSION, {}, {}, os_files)
- ds_os = ds.DataSourceOpenStack(settings.CFG_BUILTIN,
- None,
- helpers.Paths({}))
- self.assertIsNone(ds_os.version)
- found = ds_os.get_data(timeout=0.1, retries=0)
- self.assertFalse(found)
- self.assertIsNone(ds_os.version)
-
- @hp.activate
- def test_no_datasource(self):
- os_files = copy.deepcopy(OS_FILES)
- for k in list(os_files.keys()):
- if k.endswith('meta_data.json'):
- os_files.pop(k)
- _register_uris(self.VERSION, {}, {}, os_files)
- ds_os = ds.DataSourceOpenStack(settings.CFG_BUILTIN,
- None,
- helpers.Paths({}))
- ds_os.ds_cfg = {
- 'max_wait': 0,
- 'timeout': 0,
- }
- self.assertIsNone(ds_os.version)
- found = ds_os.get_data(timeout=0.1, retries=0)
- self.assertFalse(found)
- self.assertIsNone(ds_os.version)
-
- @hp.activate
- def test_disabled_datasource(self):
- os_files = copy.deepcopy(OS_FILES)
- os_meta = copy.deepcopy(OSTACK_META)
- os_meta['meta'] = {
- 'dsmode': 'disabled',
- }
- for k in list(os_files.keys()):
- if k.endswith('meta_data.json'):
- os_files[k] = json.dumps(os_meta)
- _register_uris(self.VERSION, {}, {}, os_files)
- ds_os = ds.DataSourceOpenStack(settings.CFG_BUILTIN,
- None,
- helpers.Paths({}))
- ds_os.ds_cfg = {
- 'max_wait': 0,
- 'timeout': 0,
- }
- self.assertIsNone(ds_os.version)
- found = ds_os.get_data(timeout=0.1, retries=0)
- self.assertFalse(found)
- self.assertIsNone(ds_os.version)
-
-
-class TestVendorDataLoading(test_helpers.TestCase):
- def cvj(self, data):
- return openstack.convert_vendordata_json(data)
-
- def test_vd_load_none(self):
- # non-existant vendor-data should return none
- self.assertIsNone(self.cvj(None))
-
- def test_vd_load_string(self):
- self.assertEqual(self.cvj("foobar"), "foobar")
-
- def test_vd_load_list(self):
- data = [{'foo': 'bar'}, 'mystring', list(['another', 'list'])]
- self.assertEqual(self.cvj(data), data)
-
- def test_vd_load_dict_no_ci(self):
- self.assertEqual(self.cvj({'foo': 'bar'}), None)
-
- def test_vd_load_dict_ci_dict(self):
- self.assertRaises(ValueError, self.cvj,
- {'foo': 'bar', 'cloud-init': {'x': 1}})
-
- def test_vd_load_dict_ci_string(self):
- data = {'foo': 'bar', 'cloud-init': 'VENDOR_DATA'}
- self.assertEqual(self.cvj(data), data['cloud-init'])
-
- def test_vd_load_dict_ci_list(self):
- data = {'foo': 'bar', 'cloud-init': ['VD_1', 'VD_2']}
- self.assertEqual(self.cvj(data), data['cloud-init'])
diff --git a/tests/unittests/test_datasource/test_smartos.py b/tests/unittests/test_datasource/test_smartos.py
deleted file mode 100644
index 9c6c8768..00000000
--- a/tests/unittests/test_datasource/test_smartos.py
+++ /dev/null
@@ -1,543 +0,0 @@
-# vi: ts=4 expandtab
-#
-# Copyright (C) 2013 Canonical Ltd.
-#
-# Author: Ben Howard <ben.howard@canonical.com>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 3, as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-#
-# This is a testcase for the SmartOS datasource. It replicates a serial
-# console and acts like the SmartOS console does in order to validate
-# return responses.
-#
-
-from __future__ import print_function
-
-from binascii import crc32
-import json
-import os
-import os.path
-import re
-import shutil
-import stat
-import tempfile
-import uuid
-
-from cloudinit import serial
-from cloudinit.sources import DataSourceSmartOS
-
-import six
-
-from cloudinit import helpers as c_helpers
-from cloudinit.util import b64e
-
-from ..helpers import mock, FilesystemMockingTestCase, TestCase
-
-SDC_NICS = json.loads("""
-[
- {
- "nic_tag": "external",
- "primary": true,
- "mtu": 1500,
- "model": "virtio",
- "gateway": "8.12.42.1",
- "netmask": "255.255.255.0",
- "ip": "8.12.42.102",
- "network_uuid": "992fc7ce-6aac-4b74-aed6-7b9d2c6c0bfe",
- "gateways": [
- "8.12.42.1"
- ],
- "vlan_id": 324,
- "mac": "90:b8:d0:f5:e4:f5",
- "interface": "net0",
- "ips": [
- "8.12.42.102/24"
- ]
- },
- {
- "nic_tag": "sdc_overlay/16187209",
- "gateway": "192.168.128.1",
- "model": "virtio",
- "mac": "90:b8:d0:a5:ff:cd",
- "netmask": "255.255.252.0",
- "ip": "192.168.128.93",
- "network_uuid": "4cad71da-09bc-452b-986d-03562a03a0a9",
- "gateways": [
- "192.168.128.1"
- ],
- "vlan_id": 2,
- "mtu": 8500,
- "interface": "net1",
- "ips": [
- "192.168.128.93/22"
- ]
- }
-]
-""")
-
-MOCK_RETURNS = {
- 'hostname': 'test-host',
- 'root_authorized_keys': 'ssh-rsa AAAAB3Nz...aC1yc2E= keyname',
- 'disable_iptables_flag': None,
- 'enable_motd_sys_info': None,
- 'test-var1': 'some data',
- 'cloud-init:user-data': '\n'.join(['#!/bin/sh', '/bin/true', '']),
- 'sdc:datacenter_name': 'somewhere2',
- 'sdc:operator-script': '\n'.join(['bin/true', '']),
- 'sdc:uuid': str(uuid.uuid4()),
- 'sdc:vendor-data': '\n'.join(['VENDOR_DATA', '']),
- 'user-data': '\n'.join(['something', '']),
- 'user-script': '\n'.join(['/bin/true', '']),
- 'sdc:nics': json.dumps(SDC_NICS),
-}
-
-DMI_DATA_RETURN = 'smartdc'
-
-
-class PsuedoJoyentClient(object):
- def __init__(self, data=None):
- if data is None:
- data = MOCK_RETURNS.copy()
- self.data = data
- return
-
- def get(self, key, default=None, strip=False):
- if key in self.data:
- r = self.data[key]
- if strip:
- r = r.strip()
- else:
- r = default
- return r
-
- def get_json(self, key, default=None):
- result = self.get(key, default=default)
- if result is None:
- return default
- return json.loads(result)
-
- def exists(self):
- return True
-
-
-class TestSmartOSDataSource(FilesystemMockingTestCase):
- def setUp(self):
- super(TestSmartOSDataSource, self).setUp()
-
- dsmos = 'cloudinit.sources.DataSourceSmartOS'
- patcher = mock.patch(dsmos + ".jmc_client_factory")
- self.jmc_cfact = patcher.start()
- self.addCleanup(patcher.stop)
- patcher = mock.patch(dsmos + ".get_smartos_environ")
- self.get_smartos_environ = patcher.start()
- self.addCleanup(patcher.stop)
-
- self.tmp = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp)
- self.paths = c_helpers.Paths({'cloud_dir': self.tmp})
-
- self.legacy_user_d = os.path.join(self.tmp, 'legacy_user_tmp')
- os.mkdir(self.legacy_user_d)
-
- self.orig_lud = DataSourceSmartOS.LEGACY_USER_D
- DataSourceSmartOS.LEGACY_USER_D = self.legacy_user_d
-
- def tearDown(self):
- DataSourceSmartOS.LEGACY_USER_D = self.orig_lud
- super(TestSmartOSDataSource, self).tearDown()
-
- def _get_ds(self, mockdata=None, mode=DataSourceSmartOS.SMARTOS_ENV_KVM,
- sys_cfg=None, ds_cfg=None):
- self.jmc_cfact.return_value = PsuedoJoyentClient(mockdata)
- self.get_smartos_environ.return_value = mode
-
- if sys_cfg is None:
- sys_cfg = {}
-
- if ds_cfg is not None:
- sys_cfg['datasource'] = sys_cfg.get('datasource', {})
- sys_cfg['datasource']['SmartOS'] = ds_cfg
-
- return DataSourceSmartOS.DataSourceSmartOS(
- sys_cfg, distro=None, paths=self.paths)
-
- def test_no_base64(self):
- ds_cfg = {'no_base64_decode': ['test_var1'], 'all_base': True}
- dsrc = self._get_ds(ds_cfg=ds_cfg)
- ret = dsrc.get_data()
- self.assertTrue(ret)
-
- def test_uuid(self):
- dsrc = self._get_ds(mockdata=MOCK_RETURNS)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertEqual(MOCK_RETURNS['sdc:uuid'],
- dsrc.metadata['instance-id'])
-
- def test_root_keys(self):
- dsrc = self._get_ds(mockdata=MOCK_RETURNS)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertEqual(MOCK_RETURNS['root_authorized_keys'],
- dsrc.metadata['public-keys'])
-
- def test_hostname_b64(self):
- dsrc = self._get_ds(mockdata=MOCK_RETURNS)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertEqual(MOCK_RETURNS['hostname'],
- dsrc.metadata['local-hostname'])
-
- def test_hostname(self):
- dsrc = self._get_ds(mockdata=MOCK_RETURNS)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertEqual(MOCK_RETURNS['hostname'],
- dsrc.metadata['local-hostname'])
-
- def test_userdata(self):
- dsrc = self._get_ds(mockdata=MOCK_RETURNS)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertEqual(MOCK_RETURNS['user-data'],
- dsrc.metadata['legacy-user-data'])
- self.assertEqual(MOCK_RETURNS['cloud-init:user-data'],
- dsrc.userdata_raw)
-
- def test_sdc_nics(self):
- dsrc = self._get_ds(mockdata=MOCK_RETURNS)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertEqual(json.loads(MOCK_RETURNS['sdc:nics']),
- dsrc.metadata['network-data'])
-
- def test_sdc_scripts(self):
- dsrc = self._get_ds(mockdata=MOCK_RETURNS)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertEqual(MOCK_RETURNS['user-script'],
- dsrc.metadata['user-script'])
-
- legacy_script_f = "%s/user-script" % self.legacy_user_d
- self.assertTrue(os.path.exists(legacy_script_f))
- self.assertTrue(os.path.islink(legacy_script_f))
- user_script_perm = oct(os.stat(legacy_script_f)[stat.ST_MODE])[-3:]
- self.assertEqual(user_script_perm, '700')
-
- def test_scripts_shebanged(self):
- dsrc = self._get_ds(mockdata=MOCK_RETURNS)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertEqual(MOCK_RETURNS['user-script'],
- dsrc.metadata['user-script'])
-
- legacy_script_f = "%s/user-script" % self.legacy_user_d
- self.assertTrue(os.path.exists(legacy_script_f))
- self.assertTrue(os.path.islink(legacy_script_f))
- shebang = None
- with open(legacy_script_f, 'r') as f:
- shebang = f.readlines()[0].strip()
- self.assertEqual(shebang, "#!/bin/bash")
- user_script_perm = oct(os.stat(legacy_script_f)[stat.ST_MODE])[-3:]
- self.assertEqual(user_script_perm, '700')
-
- def test_scripts_shebang_not_added(self):
- """
- Test that the SmartOS requirement that plain text scripts
- are executable. This test makes sure that plain texts scripts
- with out file magic have it added appropriately by cloud-init.
- """
-
- my_returns = MOCK_RETURNS.copy()
- my_returns['user-script'] = '\n'.join(['#!/usr/bin/perl',
- 'print("hi")', ''])
-
- dsrc = self._get_ds(mockdata=my_returns)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertEqual(my_returns['user-script'],
- dsrc.metadata['user-script'])
-
- legacy_script_f = "%s/user-script" % self.legacy_user_d
- self.assertTrue(os.path.exists(legacy_script_f))
- self.assertTrue(os.path.islink(legacy_script_f))
- shebang = None
- with open(legacy_script_f, 'r') as f:
- shebang = f.readlines()[0].strip()
- self.assertEqual(shebang, "#!/usr/bin/perl")
-
- def test_userdata_removed(self):
- """
- User-data in the SmartOS world is supposed to be written to a file
- each and every boot. This tests to make sure that in the event the
- legacy user-data is removed, the existing user-data is backed-up
- and there is no /var/db/user-data left.
- """
-
- user_data_f = "%s/mdata-user-data" % self.legacy_user_d
- with open(user_data_f, 'w') as f:
- f.write("PREVIOUS")
-
- my_returns = MOCK_RETURNS.copy()
- del my_returns['user-data']
-
- dsrc = self._get_ds(mockdata=my_returns)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertFalse(dsrc.metadata.get('legacy-user-data'))
-
- found_new = False
- for root, _dirs, files in os.walk(self.legacy_user_d):
- for name in files:
- name_f = os.path.join(root, name)
- permissions = oct(os.stat(name_f)[stat.ST_MODE])[-3:]
- if re.match(r'.*\/mdata-user-data$', name_f):
- found_new = True
- print(name_f)
- self.assertEqual(permissions, '400')
-
- self.assertFalse(found_new)
-
- def test_vendor_data_not_default(self):
- dsrc = self._get_ds(mockdata=MOCK_RETURNS)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertEqual(MOCK_RETURNS['sdc:vendor-data'],
- dsrc.metadata['vendor-data'])
-
- def test_default_vendor_data(self):
- my_returns = MOCK_RETURNS.copy()
- def_op_script = my_returns['sdc:vendor-data']
- del my_returns['sdc:vendor-data']
- dsrc = self._get_ds(mockdata=my_returns)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertNotEqual(def_op_script, dsrc.metadata['vendor-data'])
-
- # we expect default vendor-data is a boothook
- self.assertTrue(dsrc.vendordata_raw.startswith("#cloud-boothook"))
-
- def test_disable_iptables_flag(self):
- dsrc = self._get_ds(mockdata=MOCK_RETURNS)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertEqual(MOCK_RETURNS['disable_iptables_flag'],
- dsrc.metadata['iptables_disable'])
-
- def test_motd_sys_info(self):
- dsrc = self._get_ds(mockdata=MOCK_RETURNS)
- ret = dsrc.get_data()
- self.assertTrue(ret)
- self.assertEqual(MOCK_RETURNS['enable_motd_sys_info'],
- dsrc.metadata['motd_sys_info'])
-
- def test_default_ephemeral(self):
- # Test to make sure that the builtin config has the ephemeral
- # configuration.
- dsrc = self._get_ds()
- cfg = dsrc.get_config_obj()
-
- ret = dsrc.get_data()
- self.assertTrue(ret)
-
- assert 'disk_setup' in cfg
- assert 'fs_setup' in cfg
- self.assertIsInstance(cfg['disk_setup'], dict)
- self.assertIsInstance(cfg['fs_setup'], list)
-
- def test_override_disk_aliases(self):
- # Test to make sure that the built-in DS is overriden
- builtin = DataSourceSmartOS.BUILTIN_DS_CONFIG
-
- mydscfg = {'disk_aliases': {'FOO': '/dev/bar'}}
-
- # expect that these values are in builtin, or this is pointless
- for k in mydscfg:
- self.assertIn(k, builtin)
-
- dsrc = self._get_ds(ds_cfg=mydscfg)
- ret = dsrc.get_data()
- self.assertTrue(ret)
-
- self.assertEqual(mydscfg['disk_aliases']['FOO'],
- dsrc.ds_cfg['disk_aliases']['FOO'])
-
- self.assertEqual(dsrc.device_name_to_device('FOO'),
- mydscfg['disk_aliases']['FOO'])
-
-
-class TestJoyentMetadataClient(FilesystemMockingTestCase):
-
- def setUp(self):
- super(TestJoyentMetadataClient, self).setUp()
-
- self.serial = mock.MagicMock(spec=serial.Serial)
- self.request_id = 0xabcdef12
- self.metadata_value = 'value'
- self.response_parts = {
- 'command': 'SUCCESS',
- 'crc': 'b5a9ff00',
- 'length': 17 + len(b64e(self.metadata_value)),
- 'payload': b64e(self.metadata_value),
- 'request_id': '{0:08x}'.format(self.request_id),
- }
-
- def make_response():
- payloadstr = ''
- if 'payload' in self.response_parts:
- payloadstr = ' {0}'.format(self.response_parts['payload'])
- return ('V2 {length} {crc} {request_id} '
- '{command}{payloadstr}\n'.format(
- payloadstr=payloadstr,
- **self.response_parts).encode('ascii'))
-
- self.metasource_data = None
-
- def read_response(length):
- if not self.metasource_data:
- self.metasource_data = make_response()
- self.metasource_data_len = len(self.metasource_data)
- resp = self.metasource_data[:length]
- self.metasource_data = self.metasource_data[length:]
- return resp
-
- self.serial.read.side_effect = read_response
- self.patched_funcs.enter_context(
- mock.patch('cloudinit.sources.DataSourceSmartOS.random.randint',
- mock.Mock(return_value=self.request_id)))
-
- def _get_client(self):
- return DataSourceSmartOS.JoyentMetadataClient(
- fp=self.serial, smartos_type=DataSourceSmartOS.SMARTOS_ENV_KVM)
-
- def assertEndsWith(self, haystack, prefix):
- self.assertTrue(haystack.endswith(prefix),
- "{0} does not end with '{1}'".format(
- repr(haystack), prefix))
-
- def assertStartsWith(self, haystack, prefix):
- self.assertTrue(haystack.startswith(prefix),
- "{0} does not start with '{1}'".format(
- repr(haystack), prefix))
-
- def test_get_metadata_writes_a_single_line(self):
- client = self._get_client()
- client.get('some_key')
- self.assertEqual(1, self.serial.write.call_count)
- written_line = self.serial.write.call_args[0][0]
- print(type(written_line))
- self.assertEndsWith(written_line.decode('ascii'),
- b'\n'.decode('ascii'))
- self.assertEqual(1, written_line.count(b'\n'))
-
- def _get_written_line(self, key='some_key'):
- client = self._get_client()
- client.get(key)
- return self.serial.write.call_args[0][0]
-
- def test_get_metadata_writes_bytes(self):
- self.assertIsInstance(self._get_written_line(), six.binary_type)
-
- def test_get_metadata_line_starts_with_v2(self):
- foo = self._get_written_line()
- self.assertStartsWith(foo.decode('ascii'), b'V2'.decode('ascii'))
-
- def test_get_metadata_uses_get_command(self):
- parts = self._get_written_line().decode('ascii').strip().split(' ')
- self.assertEqual('GET', parts[4])
-
- def test_get_metadata_base64_encodes_argument(self):
- key = 'my_key'
- parts = self._get_written_line(key).decode('ascii').strip().split(' ')
- self.assertEqual(b64e(key), parts[5])
-
- def test_get_metadata_calculates_length_correctly(self):
- parts = self._get_written_line().decode('ascii').strip().split(' ')
- expected_length = len(' '.join(parts[3:]))
- self.assertEqual(expected_length, int(parts[1]))
-
- def test_get_metadata_uses_appropriate_request_id(self):
- parts = self._get_written_line().decode('ascii').strip().split(' ')
- request_id = parts[3]
- self.assertEqual(8, len(request_id))
- self.assertEqual(request_id, request_id.lower())
-
- def test_get_metadata_uses_random_number_for_request_id(self):
- line = self._get_written_line()
- request_id = line.decode('ascii').strip().split(' ')[3]
- self.assertEqual('{0:08x}'.format(self.request_id), request_id)
-
- def test_get_metadata_checksums_correctly(self):
- parts = self._get_written_line().decode('ascii').strip().split(' ')
- expected_checksum = '{0:08x}'.format(
- crc32(' '.join(parts[3:]).encode('utf-8')) & 0xffffffff)
- checksum = parts[2]
- self.assertEqual(expected_checksum, checksum)
-
- def test_get_metadata_reads_a_line(self):
- client = self._get_client()
- client.get('some_key')
- self.assertEqual(self.metasource_data_len, self.serial.read.call_count)
-
- def test_get_metadata_returns_valid_value(self):
- client = self._get_client()
- value = client.get('some_key')
- self.assertEqual(self.metadata_value, value)
-
- def test_get_metadata_throws_exception_for_incorrect_length(self):
- self.response_parts['length'] = 0
- client = self._get_client()
- self.assertRaises(DataSourceSmartOS.JoyentMetadataFetchException,
- client.get, 'some_key')
-
- def test_get_metadata_throws_exception_for_incorrect_crc(self):
- self.response_parts['crc'] = 'deadbeef'
- client = self._get_client()
- self.assertRaises(DataSourceSmartOS.JoyentMetadataFetchException,
- client.get, 'some_key')
-
- def test_get_metadata_throws_exception_for_request_id_mismatch(self):
- self.response_parts['request_id'] = 'deadbeef'
- client = self._get_client()
- client._checksum = lambda _: self.response_parts['crc']
- self.assertRaises(DataSourceSmartOS.JoyentMetadataFetchException,
- client.get, 'some_key')
-
- def test_get_metadata_returns_None_if_value_not_found(self):
- self.response_parts['payload'] = ''
- self.response_parts['command'] = 'NOTFOUND'
- self.response_parts['length'] = 17
- client = self._get_client()
- client._checksum = lambda _: self.response_parts['crc']
- self.assertIsNone(client.get('some_key'))
-
-
-class TestNetworkConversion(TestCase):
-
- def test_convert_simple(self):
- expected = {
- 'version': 1,
- 'config': [
- {'name': 'net0', 'type': 'physical',
- 'subnets': [{'type': 'static', 'gateway': '8.12.42.1',
- 'netmask': '255.255.255.0',
- 'address': '8.12.42.102/24'}],
- 'mtu': 1500, 'mac_address': '90:b8:d0:f5:e4:f5'},
- {'name': 'net1', 'type': 'physical',
- 'subnets': [{'type': 'static', 'gateway': '192.168.128.1',
- 'netmask': '255.255.252.0',
- 'address': '192.168.128.93/22'}],
- 'mtu': 8500, 'mac_address': '90:b8:d0:a5:ff:cd'}]}
- found = DataSourceSmartOS.convert_smartos_network_data(SDC_NICS)
- self.assertEqual(expected, found)
diff --git a/tests/unittests/test_distros/__init__.py b/tests/unittests/test_distros/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/unittests/test_distros/__init__.py
+++ /dev/null
diff --git a/tests/unittests/test_distros/test_generic.py b/tests/unittests/test_distros/test_generic.py
deleted file mode 100644
index 96fa0811..00000000
--- a/tests/unittests/test_distros/test_generic.py
+++ /dev/null
@@ -1,233 +0,0 @@
-from cloudinit import distros
-from cloudinit import util
-
-from .. import helpers
-
-import os
-import shutil
-import tempfile
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-
-unknown_arch_info = {
- 'arches': ['default'],
- 'failsafe': {'primary': 'http://fs-primary-default',
- 'security': 'http://fs-security-default'}
-}
-
-package_mirrors = [
- {'arches': ['i386', 'amd64'],
- 'failsafe': {'primary': 'http://fs-primary-intel',
- 'security': 'http://fs-security-intel'},
- 'search': {
- 'primary': ['http://%(ec2_region)s.ec2/',
- 'http://%(availability_zone)s.clouds/'],
- 'security': ['http://security-mirror1-intel',
- 'http://security-mirror2-intel']}},
- {'arches': ['armhf', 'armel'],
- 'failsafe': {'primary': 'http://fs-primary-arm',
- 'security': 'http://fs-security-arm'}},
- unknown_arch_info
-]
-
-gpmi = distros._get_package_mirror_info
-gapmi = distros._get_arch_package_mirror_info
-
-
-class TestGenericDistro(helpers.FilesystemMockingTestCase):
-
- def return_first(self, mlist):
- if not mlist:
- return None
- return mlist[0]
-
- def return_second(self, mlist):
- if not mlist:
- return None
- return mlist[1]
-
- def return_none(self, _mlist):
- return None
-
- def return_last(self, mlist):
- if not mlist:
- return None
- return(mlist[-1])
-
- def setUp(self):
- super(TestGenericDistro, self).setUp()
- # Make a temp directoy for tests to use.
- self.tmp = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp)
-
- def _write_load_sudoers(self, _user, rules):
- cls = distros.fetch("ubuntu")
- d = cls("ubuntu", {}, None)
- os.makedirs(os.path.join(self.tmp, "etc"))
- os.makedirs(os.path.join(self.tmp, "etc", 'sudoers.d'))
- self.patchOS(self.tmp)
- self.patchUtils(self.tmp)
- d.write_sudo_rules("harlowja", rules)
- contents = util.load_file(d.ci_sudoers_fn)
- return contents
-
- def _count_in(self, lines_look_for, text_content):
- found_amount = 0
- for e in lines_look_for:
- for line in text_content.splitlines():
- line = line.strip()
- if line == e:
- found_amount += 1
- return found_amount
-
- def test_sudoers_ensure_rules(self):
- rules = 'ALL=(ALL:ALL) ALL'
- contents = self._write_load_sudoers('harlowja', rules)
- expected = ['harlowja ALL=(ALL:ALL) ALL']
- self.assertEqual(len(expected), self._count_in(expected, contents))
- not_expected = [
- 'harlowja A',
- 'harlowja L',
- 'harlowja L',
- ]
- self.assertEqual(0, self._count_in(not_expected, contents))
-
- def test_sudoers_ensure_rules_list(self):
- rules = [
- 'ALL=(ALL:ALL) ALL',
- 'B-ALL=(ALL:ALL) ALL',
- 'C-ALL=(ALL:ALL) ALL',
- ]
- contents = self._write_load_sudoers('harlowja', rules)
- expected = [
- 'harlowja ALL=(ALL:ALL) ALL',
- 'harlowja B-ALL=(ALL:ALL) ALL',
- 'harlowja C-ALL=(ALL:ALL) ALL',
- ]
- self.assertEqual(len(expected), self._count_in(expected, contents))
- not_expected = [
- 'harlowja A',
- 'harlowja L',
- 'harlowja L',
- ]
- self.assertEqual(0, self._count_in(not_expected, contents))
-
- def test_sudoers_ensure_new(self):
- cls = distros.fetch("ubuntu")
- d = cls("ubuntu", {}, None)
- self.patchOS(self.tmp)
- self.patchUtils(self.tmp)
- d.ensure_sudo_dir("/b")
- contents = util.load_file("/etc/sudoers")
- self.assertIn("includedir /b", contents)
- self.assertTrue(os.path.isdir("/b"))
-
- def test_sudoers_ensure_append(self):
- cls = distros.fetch("ubuntu")
- d = cls("ubuntu", {}, None)
- self.patchOS(self.tmp)
- self.patchUtils(self.tmp)
- util.write_file("/etc/sudoers", "josh, josh\n")
- d.ensure_sudo_dir("/b")
- contents = util.load_file("/etc/sudoers")
- self.assertIn("includedir /b", contents)
- self.assertTrue(os.path.isdir("/b"))
- self.assertIn("josh", contents)
- self.assertEqual(2, contents.count("josh"))
-
- def test_arch_package_mirror_info_unknown(self):
- """for an unknown arch, we should get back that with arch 'default'."""
- arch_mirrors = gapmi(package_mirrors, arch="unknown")
- self.assertEqual(unknown_arch_info, arch_mirrors)
-
- def test_arch_package_mirror_info_known(self):
- arch_mirrors = gapmi(package_mirrors, arch="amd64")
- self.assertEqual(package_mirrors[0], arch_mirrors)
-
- def test_get_package_mirror_info_az_ec2(self):
- arch_mirrors = gapmi(package_mirrors, arch="amd64")
- data_source_mock = mock.Mock(availability_zone="us-east-1a")
-
- results = gpmi(arch_mirrors, data_source=data_source_mock,
- mirror_filter=self.return_first)
- self.assertEqual(results,
- {'primary': 'http://us-east-1.ec2/',
- 'security': 'http://security-mirror1-intel'})
-
- results = gpmi(arch_mirrors, data_source=data_source_mock,
- mirror_filter=self.return_second)
- self.assertEqual(results,
- {'primary': 'http://us-east-1a.clouds/',
- 'security': 'http://security-mirror2-intel'})
-
- results = gpmi(arch_mirrors, data_source=data_source_mock,
- mirror_filter=self.return_none)
- self.assertEqual(results, package_mirrors[0]['failsafe'])
-
- def test_get_package_mirror_info_az_non_ec2(self):
- arch_mirrors = gapmi(package_mirrors, arch="amd64")
- data_source_mock = mock.Mock(availability_zone="nova.cloudvendor")
-
- results = gpmi(arch_mirrors, data_source=data_source_mock,
- mirror_filter=self.return_first)
- self.assertEqual(results,
- {'primary': 'http://nova.cloudvendor.clouds/',
- 'security': 'http://security-mirror1-intel'})
-
- results = gpmi(arch_mirrors, data_source=data_source_mock,
- mirror_filter=self.return_last)
- self.assertEqual(results,
- {'primary': 'http://nova.cloudvendor.clouds/',
- 'security': 'http://security-mirror2-intel'})
-
- def test_get_package_mirror_info_none(self):
- arch_mirrors = gapmi(package_mirrors, arch="amd64")
- data_source_mock = mock.Mock(availability_zone=None)
-
- # because both search entries here replacement based on
- # availability-zone, the filter will be called with an empty list and
- # failsafe should be taken.
- results = gpmi(arch_mirrors, data_source=data_source_mock,
- mirror_filter=self.return_first)
- self.assertEqual(results,
- {'primary': 'http://fs-primary-intel',
- 'security': 'http://security-mirror1-intel'})
-
- results = gpmi(arch_mirrors, data_source=data_source_mock,
- mirror_filter=self.return_last)
- self.assertEqual(results,
- {'primary': 'http://fs-primary-intel',
- 'security': 'http://security-mirror2-intel'})
-
- def test_systemd_in_use(self):
- cls = distros.fetch("ubuntu")
- d = cls("ubuntu", {}, None)
- self.patchOS(self.tmp)
- self.patchUtils(self.tmp)
- os.makedirs('/run/systemd/system')
- self.assertTrue(d.uses_systemd())
-
- def test_systemd_not_in_use(self):
- cls = distros.fetch("ubuntu")
- d = cls("ubuntu", {}, None)
- self.patchOS(self.tmp)
- self.patchUtils(self.tmp)
- self.assertFalse(d.uses_systemd())
-
- def test_systemd_symlink(self):
- cls = distros.fetch("ubuntu")
- d = cls("ubuntu", {}, None)
- self.patchOS(self.tmp)
- self.patchUtils(self.tmp)
- os.makedirs('/run/systemd')
- os.symlink('/', '/run/systemd/system')
- self.assertFalse(d.uses_systemd())
-
-# def _get_package_mirror_info(mirror_info, availability_zone=None,
-# mirror_filter=util.search_for_mirror):
-
-
-# vi: ts=4 expandtab
diff --git a/tests/unittests/test_distros/test_hostname.py b/tests/unittests/test_distros/test_hostname.py
deleted file mode 100644
index 5f28a868..00000000
--- a/tests/unittests/test_distros/test_hostname.py
+++ /dev/null
@@ -1,38 +0,0 @@
-import unittest
-
-from cloudinit.distros.parsers import hostname
-
-
-BASE_HOSTNAME = '''
-# My super-duper-hostname
-
-blahblah
-
-'''
-BASE_HOSTNAME = BASE_HOSTNAME.strip()
-
-
-class TestHostnameHelper(unittest.TestCase):
- def test_parse_same(self):
- hn = hostname.HostnameConf(BASE_HOSTNAME)
- self.assertEqual(str(hn).strip(), BASE_HOSTNAME)
- self.assertEqual(hn.hostname, 'blahblah')
-
- def test_no_adjust_hostname(self):
- hn = hostname.HostnameConf(BASE_HOSTNAME)
- prev_name = hn.hostname
- hn.set_hostname("")
- self.assertEqual(hn.hostname, prev_name)
-
- def test_adjust_hostname(self):
- hn = hostname.HostnameConf(BASE_HOSTNAME)
- prev_name = hn.hostname
- self.assertEqual(prev_name, 'blahblah')
- hn.set_hostname("bbbbd")
- self.assertEqual(hn.hostname, 'bbbbd')
- expected_out = '''
-# My super-duper-hostname
-
-bbbbd
-'''
- self.assertEqual(str(hn).strip(), expected_out.strip())
diff --git a/tests/unittests/test_distros/test_hosts.py b/tests/unittests/test_distros/test_hosts.py
deleted file mode 100644
index ab867c6f..00000000
--- a/tests/unittests/test_distros/test_hosts.py
+++ /dev/null
@@ -1,41 +0,0 @@
-import unittest
-
-from cloudinit.distros.parsers import hosts
-
-
-BASE_ETC = '''
-# Example
-127.0.0.1 localhost
-192.168.1.10 foo.mydomain.org foo
-192.168.1.10 bar.mydomain.org bar
-146.82.138.7 master.debian.org master
-209.237.226.90 www.opensource.org
-'''
-BASE_ETC = BASE_ETC.strip()
-
-
-class TestHostsHelper(unittest.TestCase):
- def test_parse(self):
- eh = hosts.HostsConf(BASE_ETC)
- self.assertEqual(eh.get_entry('127.0.0.1'), [['localhost']])
- self.assertEqual(eh.get_entry('192.168.1.10'),
- [['foo.mydomain.org', 'foo'],
- ['bar.mydomain.org', 'bar']])
- eh = str(eh)
- self.assertTrue(eh.startswith('# Example'))
-
- def test_add(self):
- eh = hosts.HostsConf(BASE_ETC)
- eh.add_entry('127.0.0.0', 'blah')
- self.assertEqual(eh.get_entry('127.0.0.0'), [['blah']])
- eh.add_entry('127.0.0.3', 'blah', 'blah2', 'blah3')
- self.assertEqual(eh.get_entry('127.0.0.3'),
- [['blah', 'blah2', 'blah3']])
-
- def test_del(self):
- eh = hosts.HostsConf(BASE_ETC)
- eh.add_entry('127.0.0.0', 'blah')
- self.assertEqual(eh.get_entry('127.0.0.0'), [['blah']])
-
- eh.del_entries('127.0.0.0')
- self.assertEqual(eh.get_entry('127.0.0.0'), [])
diff --git a/tests/unittests/test_distros/test_netconfig.py b/tests/unittests/test_distros/test_netconfig.py
deleted file mode 100644
index 36eae2dc..00000000
--- a/tests/unittests/test_distros/test_netconfig.py
+++ /dev/null
@@ -1,381 +0,0 @@
-import os
-from six import StringIO
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-try:
- from contextlib import ExitStack
-except ImportError:
- from contextlib2 import ExitStack
-
-from ..helpers import TestCase
-
-from cloudinit import distros
-from cloudinit.distros.parsers.sys_conf import SysConf
-from cloudinit import helpers
-from cloudinit import settings
-from cloudinit import util
-
-
-BASE_NET_CFG = '''
-auto lo
-iface lo inet loopback
-
-auto eth0
-iface eth0 inet static
- address 192.168.1.5
- netmask 255.255.255.0
- network 192.168.0.0
- broadcast 192.168.1.0
- gateway 192.168.1.254
-
-auto eth1
-iface eth1 inet dhcp
-'''
-
-BASE_NET_CFG_IPV6 = '''
-auto lo
-iface lo inet loopback
-
-auto eth0
-iface eth0 inet static
- address 192.168.1.5
- netmask 255.255.255.0
- network 192.168.0.0
- broadcast 192.168.1.0
- gateway 192.168.1.254
-
-iface eth0 inet6 static
- address 2607:f0d0:1002:0011::2
- netmask 64
- gateway 2607:f0d0:1002:0011::1
-
-iface eth1 inet static
- address 192.168.1.6
- netmask 255.255.255.0
- network 192.168.0.0
- broadcast 192.168.1.0
- gateway 192.168.1.254
-
-iface eth1 inet6 static
- address 2607:f0d0:1002:0011::3
- netmask 64
- gateway 2607:f0d0:1002:0011::1
-'''
-
-
-class WriteBuffer(object):
- def __init__(self):
- self.buffer = StringIO()
- self.mode = None
- self.omode = None
-
- def write(self, text):
- self.buffer.write(text)
-
- def __str__(self):
- return self.buffer.getvalue()
-
-
-class TestNetCfgDistro(TestCase):
-
- def _get_distro(self, dname):
- cls = distros.fetch(dname)
- cfg = settings.CFG_BUILTIN
- cfg['system_info']['distro'] = dname
- paths = helpers.Paths({})
- return cls(dname, cfg, paths)
-
- def test_simple_write_ub(self):
- ub_distro = self._get_distro('ubuntu')
- with ExitStack() as mocks:
- write_bufs = {}
-
- def replace_write(filename, content, mode=0o644, omode="wb"):
- buf = WriteBuffer()
- buf.mode = mode
- buf.omode = omode
- buf.write(content)
- write_bufs[filename] = buf
-
- mocks.enter_context(
- mock.patch.object(util, 'write_file', replace_write))
- mocks.enter_context(
- mock.patch.object(os.path, 'isfile', return_value=False))
-
- ub_distro.apply_network(BASE_NET_CFG, False)
-
- self.assertEqual(len(write_bufs), 1)
- eni_name = '/etc/network/interfaces.d/50-cloud-init.cfg'
- self.assertIn(eni_name, write_bufs)
- write_buf = write_bufs[eni_name]
- self.assertEqual(str(write_buf).strip(), BASE_NET_CFG.strip())
- self.assertEqual(write_buf.mode, 0o644)
-
- def assertCfgEquals(self, blob1, blob2):
- b1 = dict(SysConf(blob1.strip().splitlines()))
- b2 = dict(SysConf(blob2.strip().splitlines()))
- self.assertEqual(b1, b2)
- for (k, v) in b1.items():
- self.assertIn(k, b2)
- for (k, v) in b2.items():
- self.assertIn(k, b1)
- for (k, v) in b1.items():
- self.assertEqual(v, b2[k])
-
- def test_simple_write_rh(self):
- rh_distro = self._get_distro('rhel')
-
- write_bufs = {}
-
- def replace_write(filename, content, mode=0o644, omode="wb"):
- buf = WriteBuffer()
- buf.mode = mode
- buf.omode = omode
- buf.write(content)
- write_bufs[filename] = buf
-
- with ExitStack() as mocks:
- mocks.enter_context(
- mock.patch.object(util, 'write_file', replace_write))
- mocks.enter_context(
- mock.patch.object(util, 'load_file', return_value=''))
- mocks.enter_context(
- mock.patch.object(os.path, 'isfile', return_value=False))
-
- rh_distro.apply_network(BASE_NET_CFG, False)
-
- self.assertEqual(len(write_bufs), 4)
- self.assertIn('/etc/sysconfig/network-scripts/ifcfg-lo',
- write_bufs)
- write_buf = write_bufs['/etc/sysconfig/network-scripts/ifcfg-lo']
- expected_buf = '''
-DEVICE="lo"
-ONBOOT=yes
-'''
- self.assertCfgEquals(expected_buf, str(write_buf))
- self.assertEqual(write_buf.mode, 0o644)
-
- self.assertIn('/etc/sysconfig/network-scripts/ifcfg-eth0',
- write_bufs)
- write_buf = write_bufs['/etc/sysconfig/network-scripts/ifcfg-eth0']
- expected_buf = '''
-DEVICE="eth0"
-BOOTPROTO="static"
-NETMASK="255.255.255.0"
-IPADDR="192.168.1.5"
-ONBOOT=yes
-GATEWAY="192.168.1.254"
-BROADCAST="192.168.1.0"
-'''
- self.assertCfgEquals(expected_buf, str(write_buf))
- self.assertEqual(write_buf.mode, 0o644)
-
- self.assertIn('/etc/sysconfig/network-scripts/ifcfg-eth1',
- write_bufs)
- write_buf = write_bufs['/etc/sysconfig/network-scripts/ifcfg-eth1']
- expected_buf = '''
-DEVICE="eth1"
-BOOTPROTO="dhcp"
-ONBOOT=yes
-'''
- self.assertCfgEquals(expected_buf, str(write_buf))
- self.assertEqual(write_buf.mode, 0o644)
-
- self.assertIn('/etc/sysconfig/network', write_bufs)
- write_buf = write_bufs['/etc/sysconfig/network']
- expected_buf = '''
-# Created by cloud-init v. 0.7
-NETWORKING=yes
-'''
- self.assertCfgEquals(expected_buf, str(write_buf))
- self.assertEqual(write_buf.mode, 0o644)
-
- def test_write_ipv6_rhel(self):
- rh_distro = self._get_distro('rhel')
-
- write_bufs = {}
-
- def replace_write(filename, content, mode=0o644, omode="wb"):
- buf = WriteBuffer()
- buf.mode = mode
- buf.omode = omode
- buf.write(content)
- write_bufs[filename] = buf
-
- with ExitStack() as mocks:
- mocks.enter_context(
- mock.patch.object(util, 'write_file', replace_write))
- mocks.enter_context(
- mock.patch.object(util, 'load_file', return_value=''))
- mocks.enter_context(
- mock.patch.object(os.path, 'isfile', return_value=False))
-
- rh_distro.apply_network(BASE_NET_CFG_IPV6, False)
-
- self.assertEqual(len(write_bufs), 4)
- self.assertIn('/etc/sysconfig/network-scripts/ifcfg-lo',
- write_bufs)
- write_buf = write_bufs['/etc/sysconfig/network-scripts/ifcfg-lo']
- expected_buf = '''
-DEVICE="lo"
-ONBOOT=yes
-'''
- self.assertCfgEquals(expected_buf, str(write_buf))
- self.assertEqual(write_buf.mode, 0o644)
-
- self.assertIn('/etc/sysconfig/network-scripts/ifcfg-eth0',
- write_bufs)
- write_buf = write_bufs['/etc/sysconfig/network-scripts/ifcfg-eth0']
- expected_buf = '''
-DEVICE="eth0"
-BOOTPROTO="static"
-NETMASK="255.255.255.0"
-IPADDR="192.168.1.5"
-ONBOOT=yes
-GATEWAY="192.168.1.254"
-BROADCAST="192.168.1.0"
-IPV6INIT=yes
-IPV6ADDR="2607:f0d0:1002:0011::2"
-IPV6_DEFAULTGW="2607:f0d0:1002:0011::1"
-'''
- self.assertCfgEquals(expected_buf, str(write_buf))
- self.assertEqual(write_buf.mode, 0o644)
- self.assertIn('/etc/sysconfig/network-scripts/ifcfg-eth1',
- write_bufs)
- write_buf = write_bufs['/etc/sysconfig/network-scripts/ifcfg-eth1']
- expected_buf = '''
-DEVICE="eth1"
-BOOTPROTO="static"
-NETMASK="255.255.255.0"
-IPADDR="192.168.1.6"
-ONBOOT=no
-GATEWAY="192.168.1.254"
-BROADCAST="192.168.1.0"
-IPV6INIT=yes
-IPV6ADDR="2607:f0d0:1002:0011::3"
-IPV6_DEFAULTGW="2607:f0d0:1002:0011::1"
-'''
- self.assertCfgEquals(expected_buf, str(write_buf))
- self.assertEqual(write_buf.mode, 0o644)
-
- self.assertIn('/etc/sysconfig/network', write_bufs)
- write_buf = write_bufs['/etc/sysconfig/network']
- expected_buf = '''
-# Created by cloud-init v. 0.7
-NETWORKING=yes
-NETWORKING_IPV6=yes
-IPV6_AUTOCONF=no
-'''
- self.assertCfgEquals(expected_buf, str(write_buf))
- self.assertEqual(write_buf.mode, 0o644)
-
- def test_simple_write_freebsd(self):
- fbsd_distro = self._get_distro('freebsd')
-
- write_bufs = {}
- read_bufs = {
- '/etc/rc.conf': '',
- '/etc/resolv.conf': '',
- }
-
- def replace_write(filename, content, mode=0o644, omode="wb"):
- buf = WriteBuffer()
- buf.mode = mode
- buf.omode = omode
- buf.write(content)
- write_bufs[filename] = buf
-
- def replace_read(fname, read_cb=None, quiet=False):
- if fname not in read_bufs:
- if fname in write_bufs:
- return str(write_bufs[fname])
- raise IOError("%s not found" % fname)
- else:
- if fname in write_bufs:
- return str(write_bufs[fname])
- return read_bufs[fname]
-
- with ExitStack() as mocks:
- mocks.enter_context(
- mock.patch.object(util, 'subp', return_value=('vtnet0', '')))
- mocks.enter_context(
- mock.patch.object(os.path, 'exists', return_value=False))
- mocks.enter_context(
- mock.patch.object(util, 'write_file', replace_write))
- mocks.enter_context(
- mock.patch.object(util, 'load_file', replace_read))
-
- fbsd_distro.apply_network(BASE_NET_CFG, False)
-
- self.assertIn('/etc/rc.conf', write_bufs)
- write_buf = write_bufs['/etc/rc.conf']
- expected_buf = '''
-ifconfig_vtnet0="192.168.1.5 netmask 255.255.255.0"
-ifconfig_vtnet1="DHCP"
-defaultrouter="192.168.1.254"
-'''
- self.assertCfgEquals(expected_buf, str(write_buf))
- self.assertEqual(write_buf.mode, 0o644)
-
- def test_apply_network_config_fallback(self):
- fbsd_distro = self._get_distro('freebsd')
-
- # a weak attempt to verify that we don't have an implementation
- # of _write_network_config or apply_network_config in fbsd now,
- # which would make this test not actually test the fallback.
- self.assertRaises(
- NotImplementedError, fbsd_distro._write_network_config,
- BASE_NET_CFG)
-
- # now run
- mynetcfg = {
- 'config': [{"type": "physical", "name": "eth0",
- "mac_address": "c0:d6:9f:2c:e8:80",
- "subnets": [{"type": "dhcp"}]}],
- 'version': 1}
-
- write_bufs = {}
- read_bufs = {
- '/etc/rc.conf': '',
- '/etc/resolv.conf': '',
- }
-
- def replace_write(filename, content, mode=0o644, omode="wb"):
- buf = WriteBuffer()
- buf.mode = mode
- buf.omode = omode
- buf.write(content)
- write_bufs[filename] = buf
-
- def replace_read(fname, read_cb=None, quiet=False):
- if fname not in read_bufs:
- if fname in write_bufs:
- return str(write_bufs[fname])
- raise IOError("%s not found" % fname)
- else:
- if fname in write_bufs:
- return str(write_bufs[fname])
- return read_bufs[fname]
-
- with ExitStack() as mocks:
- mocks.enter_context(
- mock.patch.object(util, 'subp', return_value=('vtnet0', '')))
- mocks.enter_context(
- mock.patch.object(os.path, 'exists', return_value=False))
- mocks.enter_context(
- mock.patch.object(util, 'write_file', replace_write))
- mocks.enter_context(
- mock.patch.object(util, 'load_file', replace_read))
-
- fbsd_distro.apply_network_config(mynetcfg, bring_up=False)
-
- self.assertIn('/etc/rc.conf', write_bufs)
- write_buf = write_bufs['/etc/rc.conf']
- expected_buf = '''
-ifconfig_vtnet0="DHCP"
-'''
- self.assertCfgEquals(expected_buf, str(write_buf))
- self.assertEqual(write_buf.mode, 0o644)
diff --git a/tests/unittests/test_distros/test_resolv.py b/tests/unittests/test_distros/test_resolv.py
deleted file mode 100644
index 9402b5ea..00000000
--- a/tests/unittests/test_distros/test_resolv.py
+++ /dev/null
@@ -1,67 +0,0 @@
-from cloudinit.distros.parsers import resolv_conf
-from cloudinit.distros import rhel_util
-
-from ..helpers import TestCase
-
-import re
-import tempfile
-
-
-BASE_RESOLVE = '''
-; generated by /sbin/dhclient-script
-search blah.yahoo.com yahoo.com
-nameserver 10.15.44.14
-nameserver 10.15.30.92
-'''
-BASE_RESOLVE = BASE_RESOLVE.strip()
-
-
-class TestResolvHelper(TestCase):
- def test_parse_same(self):
- rp = resolv_conf.ResolvConf(BASE_RESOLVE)
- rp_r = str(rp).strip()
- self.assertEqual(BASE_RESOLVE, rp_r)
-
- def test_write_works(self):
- with tempfile.NamedTemporaryFile() as fh:
- rhel_util.update_resolve_conf_file(fh.name, [], [])
-
- def test_local_domain(self):
- rp = resolv_conf.ResolvConf(BASE_RESOLVE)
- self.assertEqual(None, rp.local_domain)
-
- rp.local_domain = "bob"
- self.assertEqual('bob', rp.local_domain)
- self.assertIn('domain bob', str(rp))
-
- def test_nameservers(self):
- rp = resolv_conf.ResolvConf(BASE_RESOLVE)
- self.assertIn('10.15.44.14', rp.nameservers)
- self.assertIn('10.15.30.92', rp.nameservers)
- rp.add_nameserver('10.2')
- self.assertIn('10.2', rp.nameservers)
- self.assertIn('nameserver 10.2', str(rp))
- self.assertNotIn('10.3', rp.nameservers)
- self.assertEqual(len(rp.nameservers), 3)
- rp.add_nameserver('10.2')
- self.assertRaises(ValueError, rp.add_nameserver, '10.3')
- self.assertNotIn('10.3', rp.nameservers)
-
- def test_search_domains(self):
- rp = resolv_conf.ResolvConf(BASE_RESOLVE)
- self.assertIn('yahoo.com', rp.search_domains)
- self.assertIn('blah.yahoo.com', rp.search_domains)
- rp.add_search_domain('bbb.y.com')
- self.assertIn('bbb.y.com', rp.search_domains)
- self.assertTrue(re.search(r'search(.*)bbb.y.com(.*)', str(rp)))
- self.assertIn('bbb.y.com', rp.search_domains)
- rp.add_search_domain('bbb.y.com')
- self.assertEqual(len(rp.search_domains), 3)
- rp.add_search_domain('bbb2.y.com')
- self.assertEqual(len(rp.search_domains), 4)
- rp.add_search_domain('bbb3.y.com')
- self.assertEqual(len(rp.search_domains), 5)
- rp.add_search_domain('bbb4.y.com')
- self.assertEqual(len(rp.search_domains), 6)
- self.assertRaises(ValueError, rp.add_search_domain, 'bbb5.y.com')
- self.assertEqual(len(rp.search_domains), 6)
diff --git a/tests/unittests/test_distros/test_sysconfig.py b/tests/unittests/test_distros/test_sysconfig.py
deleted file mode 100644
index 8cb55522..00000000
--- a/tests/unittests/test_distros/test_sysconfig.py
+++ /dev/null
@@ -1,82 +0,0 @@
-import re
-
-from cloudinit.distros.parsers.sys_conf import SysConf
-
-from ..helpers import TestCase
-
-
-# Lots of good examples @
-# http://content.hccfl.edu/pollock/AUnix1/SysconfigFilesDesc.txt
-
-class TestSysConfHelper(TestCase):
- # This function was added in 2.7, make it work for 2.6
- def assertRegMatches(self, text, regexp):
- regexp = re.compile(regexp)
- self.assertTrue(regexp.search(text),
- msg="%s must match %s!" % (text, regexp.pattern))
-
- def test_parse_no_change(self):
- contents = '''# A comment
-USESMBAUTH=no
-KEYTABLE=/usr/lib/kbd/keytables/us.map
-SHORTDATE=$(date +%y:%m:%d:%H:%M)
-HOSTNAME=blahblah
-NETMASK0=255.255.255.0
-# Inline comment
-LIST=$LOGROOT/incremental-list
-IPV6TO4_ROUTING='eth0-:0004::1/64 eth1-:0005::1/64'
-ETHTOOL_OPTS="-K ${DEVICE} tso on; -G ${DEVICE} rx 256 tx 256"
-USEMD5=no'''
- conf = SysConf(contents.splitlines())
- self.assertEqual(conf['HOSTNAME'], 'blahblah')
- self.assertEqual(conf['SHORTDATE'], '$(date +%y:%m:%d:%H:%M)')
- # Should be unquoted
- self.assertEqual(conf['ETHTOOL_OPTS'], ('-K ${DEVICE} tso on; '
- '-G ${DEVICE} rx 256 tx 256'))
- self.assertEqual(contents, str(conf))
-
- def test_parse_shell_vars(self):
- contents = 'USESMBAUTH=$XYZ'
- conf = SysConf(contents.splitlines())
- self.assertEqual(contents, str(conf))
- conf = SysConf('')
- conf['B'] = '${ZZ}d apples'
- # Should be quoted
- self.assertEqual('B="${ZZ}d apples"', str(conf))
- conf = SysConf('')
- conf['B'] = '$? d apples'
- self.assertEqual('B="$? d apples"', str(conf))
- contents = 'IPMI_WATCHDOG_OPTIONS="timeout=60"'
- conf = SysConf(contents.splitlines())
- self.assertEqual('IPMI_WATCHDOG_OPTIONS=timeout=60', str(conf))
-
- def test_parse_adjust(self):
- contents = 'IPV6TO4_ROUTING="eth0-:0004::1/64 eth1-:0005::1/64"'
- conf = SysConf(contents.splitlines())
- # Should be unquoted
- self.assertEqual('eth0-:0004::1/64 eth1-:0005::1/64',
- conf['IPV6TO4_ROUTING'])
- conf['IPV6TO4_ROUTING'] = "blah \tblah"
- contents2 = str(conf).strip()
- # Should be requoted due to whitespace
- self.assertRegMatches(contents2,
- r'IPV6TO4_ROUTING=[\']blah\s+blah[\']')
-
- def test_parse_no_adjust_shell(self):
- conf = SysConf(''.splitlines())
- conf['B'] = ' $(time)'
- contents = str(conf)
- self.assertEqual('B= $(time)', contents)
-
- def test_parse_empty(self):
- contents = ''
- conf = SysConf(contents.splitlines())
- self.assertEqual('', str(conf).strip())
-
- def test_parse_add_new(self):
- contents = 'BLAH=b'
- conf = SysConf(contents.splitlines())
- conf['Z'] = 'd'
- contents = str(conf)
- self.assertIn("Z=d", contents)
- self.assertIn("BLAH=b", contents)
diff --git a/tests/unittests/test_distros/test_user_data_normalize.py b/tests/unittests/test_distros/test_user_data_normalize.py
deleted file mode 100644
index a887a930..00000000
--- a/tests/unittests/test_distros/test_user_data_normalize.py
+++ /dev/null
@@ -1,297 +0,0 @@
-from cloudinit import distros
-from cloudinit import helpers
-from cloudinit import settings
-
-from ..helpers import TestCase
-
-
-bcfg = {
- 'name': 'bob',
- 'plain_text_passwd': 'ubuntu',
- 'home': "/home/ubuntu",
- 'shell': "/bin/bash",
- 'lock_passwd': True,
- 'gecos': "Ubuntu",
- 'groups': ["foo"]
-}
-
-
-class TestUGNormalize(TestCase):
-
- def _make_distro(self, dtype, def_user=None):
- cfg = dict(settings.CFG_BUILTIN)
- cfg['system_info']['distro'] = dtype
- paths = helpers.Paths(cfg['system_info']['paths'])
- distro_cls = distros.fetch(dtype)
- if def_user:
- cfg['system_info']['default_user'] = def_user.copy()
- distro = distro_cls(dtype, cfg['system_info'], paths)
- return distro
-
- def _norm(self, cfg, distro):
- return distros.normalize_users_groups(cfg, distro)
-
- def test_group_dict(self):
- distro = self._make_distro('ubuntu')
- g = {'groups':
- [{'ubuntu': ['foo', 'bar'],
- 'bob': 'users'},
- 'cloud-users',
- {'bob': 'users2'}]}
- (_users, groups) = self._norm(g, distro)
- self.assertIn('ubuntu', groups)
- ub_members = groups['ubuntu']
- self.assertEqual(sorted(['foo', 'bar']), sorted(ub_members))
- self.assertIn('bob', groups)
- b_members = groups['bob']
- self.assertEqual(sorted(['users', 'users2']),
- sorted(b_members))
-
- def test_basic_groups(self):
- distro = self._make_distro('ubuntu')
- ug_cfg = {
- 'groups': ['bob'],
- }
- (users, groups) = self._norm(ug_cfg, distro)
- self.assertIn('bob', groups)
- self.assertEqual({}, users)
-
- def test_csv_groups(self):
- distro = self._make_distro('ubuntu')
- ug_cfg = {
- 'groups': 'bob,joe,steve',
- }
- (users, groups) = self._norm(ug_cfg, distro)
- self.assertIn('bob', groups)
- self.assertIn('joe', groups)
- self.assertIn('steve', groups)
- self.assertEqual({}, users)
-
- def test_more_groups(self):
- distro = self._make_distro('ubuntu')
- ug_cfg = {
- 'groups': ['bob', 'joe', 'steve']
- }
- (users, groups) = self._norm(ug_cfg, distro)
- self.assertIn('bob', groups)
- self.assertIn('joe', groups)
- self.assertIn('steve', groups)
- self.assertEqual({}, users)
-
- def test_member_groups(self):
- distro = self._make_distro('ubuntu')
- ug_cfg = {
- 'groups': {
- 'bob': ['s'],
- 'joe': [],
- 'steve': [],
- }
- }
- (users, groups) = self._norm(ug_cfg, distro)
- self.assertIn('bob', groups)
- self.assertEqual(['s'], groups['bob'])
- self.assertEqual([], groups['joe'])
- self.assertIn('joe', groups)
- self.assertIn('steve', groups)
- self.assertEqual({}, users)
-
- def test_users_simple_dict(self):
- distro = self._make_distro('ubuntu', bcfg)
- ug_cfg = {
- 'users': {
- 'default': True,
- }
- }
- (users, _groups) = self._norm(ug_cfg, distro)
- self.assertIn('bob', users)
- ug_cfg = {
- 'users': {
- 'default': 'yes',
- }
- }
- (users, _groups) = self._norm(ug_cfg, distro)
- self.assertIn('bob', users)
- ug_cfg = {
- 'users': {
- 'default': '1',
- }
- }
- (users, _groups) = self._norm(ug_cfg, distro)
- self.assertIn('bob', users)
-
- def test_users_simple_dict_no(self):
- distro = self._make_distro('ubuntu', bcfg)
- ug_cfg = {
- 'users': {
- 'default': False,
- }
- }
- (users, _groups) = self._norm(ug_cfg, distro)
- self.assertEqual({}, users)
- ug_cfg = {
- 'users': {
- 'default': 'no',
- }
- }
- (users, _groups) = self._norm(ug_cfg, distro)
- self.assertEqual({}, users)
-
- def test_users_simple_csv(self):
- distro = self._make_distro('ubuntu')
- ug_cfg = {
- 'users': 'joe,bob',
- }
- (users, _groups) = self._norm(ug_cfg, distro)
- self.assertIn('joe', users)
- self.assertIn('bob', users)
- self.assertEqual({'default': False}, users['joe'])
- self.assertEqual({'default': False}, users['bob'])
-
- def test_users_simple(self):
- distro = self._make_distro('ubuntu')
- ug_cfg = {
- 'users': [
- 'joe',
- 'bob'
- ],
- }
- (users, _groups) = self._norm(ug_cfg, distro)
- self.assertIn('joe', users)
- self.assertIn('bob', users)
- self.assertEqual({'default': False}, users['joe'])
- self.assertEqual({'default': False}, users['bob'])
-
- def test_users_old_user(self):
- distro = self._make_distro('ubuntu', bcfg)
- ug_cfg = {
- 'user': 'zetta',
- 'users': 'default'
- }
- (users, _groups) = self._norm(ug_cfg, distro)
- self.assertNotIn('bob', users) # Bob is not the default now, zetta is
- self.assertIn('zetta', users)
- self.assertTrue(users['zetta']['default'])
- self.assertNotIn('default', users)
- ug_cfg = {
- 'user': 'zetta',
- 'users': 'default, joe'
- }
- (users, _groups) = self._norm(ug_cfg, distro)
- self.assertNotIn('bob', users) # Bob is not the default now, zetta is
- self.assertIn('joe', users)
- self.assertIn('zetta', users)
- self.assertTrue(users['zetta']['default'])
- self.assertNotIn('default', users)
- ug_cfg = {
- 'user': 'zetta',
- 'users': ['bob', 'joe']
- }
- (users, _groups) = self._norm(ug_cfg, distro)
- self.assertIn('bob', users)
- self.assertIn('joe', users)
- self.assertIn('zetta', users)
- self.assertTrue(users['zetta']['default'])
- ug_cfg = {
- 'user': 'zetta',
- 'users': {
- 'bob': True,
- 'joe': True,
- }
- }
- (users, _groups) = self._norm(ug_cfg, distro)
- self.assertIn('bob', users)
- self.assertIn('joe', users)
- self.assertIn('zetta', users)
- self.assertTrue(users['zetta']['default'])
- ug_cfg = {
- 'user': 'zetta',
- }
- (users, _groups) = self._norm(ug_cfg, distro)
- self.assertIn('zetta', users)
- ug_cfg = {}
- (users, groups) = self._norm(ug_cfg, distro)
- self.assertEqual({}, users)
- self.assertEqual({}, groups)
-
- def test_users_dict_default_additional(self):
- distro = self._make_distro('ubuntu', bcfg)
- ug_cfg = {
- 'users': [
- {'name': 'default', 'blah': True}
- ],
- }
- (users, _groups) = self._norm(ug_cfg, distro)
- self.assertIn('bob', users)
- self.assertEqual(",".join(distro.get_default_user()['groups']),
- users['bob']['groups'])
- self.assertEqual(True, users['bob']['blah'])
- self.assertEqual(True, users['bob']['default'])
-
- def test_users_dict_extract(self):
- distro = self._make_distro('ubuntu', bcfg)
- ug_cfg = {
- 'users': [
- 'default',
- ],
- }
- (users, _groups) = self._norm(ug_cfg, distro)
- self.assertIn('bob', users)
- (name, config) = distros.extract_default(users)
- self.assertEqual(name, 'bob')
- expected_config = {}
- def_config = None
- try:
- def_config = distro.get_default_user()
- except NotImplementedError:
- pass
- if not def_config:
- def_config = {}
- expected_config.update(def_config)
-
- # Ignore these for now
- expected_config.pop('name', None)
- expected_config.pop('groups', None)
- config.pop('groups', None)
- self.assertEqual(config, expected_config)
-
- def test_users_dict_default(self):
- distro = self._make_distro('ubuntu', bcfg)
- ug_cfg = {
- 'users': [
- 'default',
- ],
- }
- (users, _groups) = self._norm(ug_cfg, distro)
- self.assertIn('bob', users)
- self.assertEqual(",".join(distro.get_default_user()['groups']),
- users['bob']['groups'])
- self.assertEqual(True, users['bob']['default'])
-
- def test_users_dict_trans(self):
- distro = self._make_distro('ubuntu')
- ug_cfg = {
- 'users': [
- {'name': 'joe',
- 'tr-me': True},
- {'name': 'bob'},
- ],
- }
- (users, _groups) = self._norm(ug_cfg, distro)
- self.assertIn('joe', users)
- self.assertIn('bob', users)
- self.assertEqual({'tr_me': True, 'default': False}, users['joe'])
- self.assertEqual({'default': False}, users['bob'])
-
- def test_users_dict(self):
- distro = self._make_distro('ubuntu')
- ug_cfg = {
- 'users': [
- {'name': 'joe'},
- {'name': 'bob'},
- ],
- }
- (users, _groups) = self._norm(ug_cfg, distro)
- self.assertIn('joe', users)
- self.assertIn('bob', users)
- self.assertEqual({'default': False}, users['joe'])
- self.assertEqual({'default': False}, users['bob'])
diff --git a/tests/unittests/test_ec2_util.py b/tests/unittests/test_ec2_util.py
deleted file mode 100644
index d6cf17fa..00000000
--- a/tests/unittests/test_ec2_util.py
+++ /dev/null
@@ -1,139 +0,0 @@
-from . import helpers
-
-from cloudinit import ec2_utils as eu
-from cloudinit import url_helper as uh
-
-hp = helpers.import_httpretty()
-
-
-class TestEc2Util(helpers.HttprettyTestCase):
- VERSION = 'latest'
-
- @hp.activate
- def test_userdata_fetch(self):
- hp.register_uri(hp.GET,
- 'http://169.254.169.254/%s/user-data' % (self.VERSION),
- body='stuff',
- status=200)
- userdata = eu.get_instance_userdata(self.VERSION)
- self.assertEqual('stuff', userdata.decode('utf-8'))
-
- @hp.activate
- def test_userdata_fetch_fail_not_found(self):
- hp.register_uri(hp.GET,
- 'http://169.254.169.254/%s/user-data' % (self.VERSION),
- status=404)
- userdata = eu.get_instance_userdata(self.VERSION, retries=0)
- self.assertEqual('', userdata)
-
- @hp.activate
- def test_userdata_fetch_fail_server_dead(self):
- hp.register_uri(hp.GET,
- 'http://169.254.169.254/%s/user-data' % (self.VERSION),
- status=500)
- userdata = eu.get_instance_userdata(self.VERSION, retries=0)
- self.assertEqual('', userdata)
-
- @hp.activate
- def test_userdata_fetch_fail_server_not_found(self):
- hp.register_uri(hp.GET,
- 'http://169.254.169.254/%s/user-data' % (self.VERSION),
- status=404)
- userdata = eu.get_instance_userdata(self.VERSION)
- self.assertEqual('', userdata)
-
- @hp.activate
- def test_metadata_fetch_no_keys(self):
- base_url = 'http://169.254.169.254/%s/meta-data/' % (self.VERSION)
- hp.register_uri(hp.GET, base_url, status=200,
- body="\n".join(['hostname',
- 'instance-id',
- 'ami-launch-index']))
- hp.register_uri(hp.GET, uh.combine_url(base_url, 'hostname'),
- status=200, body='ec2.fake.host.name.com')
- hp.register_uri(hp.GET, uh.combine_url(base_url, 'instance-id'),
- status=200, body='123')
- hp.register_uri(hp.GET, uh.combine_url(base_url, 'ami-launch-index'),
- status=200, body='1')
- md = eu.get_instance_metadata(self.VERSION, retries=0)
- self.assertEqual(md['hostname'], 'ec2.fake.host.name.com')
- self.assertEqual(md['instance-id'], '123')
- self.assertEqual(md['ami-launch-index'], '1')
-
- @hp.activate
- def test_metadata_fetch_key(self):
- base_url = 'http://169.254.169.254/%s/meta-data/' % (self.VERSION)
- hp.register_uri(hp.GET, base_url, status=200,
- body="\n".join(['hostname',
- 'instance-id',
- 'public-keys/']))
- hp.register_uri(hp.GET, uh.combine_url(base_url, 'hostname'),
- status=200, body='ec2.fake.host.name.com')
- hp.register_uri(hp.GET, uh.combine_url(base_url, 'instance-id'),
- status=200, body='123')
- hp.register_uri(hp.GET, uh.combine_url(base_url, 'public-keys/'),
- status=200, body='0=my-public-key')
- hp.register_uri(hp.GET,
- uh.combine_url(base_url, 'public-keys/0/openssh-key'),
- status=200, body='ssh-rsa AAAA.....wZEf my-public-key')
- md = eu.get_instance_metadata(self.VERSION, retries=0, timeout=0.1)
- self.assertEqual(md['hostname'], 'ec2.fake.host.name.com')
- self.assertEqual(md['instance-id'], '123')
- self.assertEqual(1, len(md['public-keys']))
-
- @hp.activate
- def test_metadata_fetch_with_2_keys(self):
- base_url = 'http://169.254.169.254/%s/meta-data/' % (self.VERSION)
- hp.register_uri(hp.GET, base_url, status=200,
- body="\n".join(['hostname',
- 'instance-id',
- 'public-keys/']))
- hp.register_uri(hp.GET, uh.combine_url(base_url, 'hostname'),
- status=200, body='ec2.fake.host.name.com')
- hp.register_uri(hp.GET, uh.combine_url(base_url, 'instance-id'),
- status=200, body='123')
- hp.register_uri(hp.GET, uh.combine_url(base_url, 'public-keys/'),
- status=200,
- body="\n".join(['0=my-public-key', '1=my-other-key']))
- hp.register_uri(hp.GET,
- uh.combine_url(base_url, 'public-keys/0/openssh-key'),
- status=200, body='ssh-rsa AAAA.....wZEf my-public-key')
- hp.register_uri(hp.GET,
- uh.combine_url(base_url, 'public-keys/1/openssh-key'),
- status=200, body='ssh-rsa AAAA.....wZEf my-other-key')
- md = eu.get_instance_metadata(self.VERSION, retries=0, timeout=0.1)
- self.assertEqual(md['hostname'], 'ec2.fake.host.name.com')
- self.assertEqual(md['instance-id'], '123')
- self.assertEqual(2, len(md['public-keys']))
-
- @hp.activate
- def test_metadata_fetch_bdm(self):
- base_url = 'http://169.254.169.254/%s/meta-data/' % (self.VERSION)
- hp.register_uri(hp.GET, base_url, status=200,
- body="\n".join(['hostname',
- 'instance-id',
- 'block-device-mapping/']))
- hp.register_uri(hp.GET, uh.combine_url(base_url, 'hostname'),
- status=200, body='ec2.fake.host.name.com')
- hp.register_uri(hp.GET, uh.combine_url(base_url, 'instance-id'),
- status=200, body='123')
- hp.register_uri(hp.GET,
- uh.combine_url(base_url, 'block-device-mapping/'),
- status=200,
- body="\n".join(['ami', 'ephemeral0']))
- hp.register_uri(hp.GET,
- uh.combine_url(base_url, 'block-device-mapping/ami'),
- status=200,
- body="sdb")
- hp.register_uri(hp.GET,
- uh.combine_url(base_url,
- 'block-device-mapping/ephemeral0'),
- status=200,
- body="sdc")
- md = eu.get_instance_metadata(self.VERSION, retries=0, timeout=0.1)
- self.assertEqual(md['hostname'], 'ec2.fake.host.name.com')
- self.assertEqual(md['instance-id'], '123')
- bdm = md['block-device-mapping']
- self.assertEqual(2, len(bdm))
- self.assertEqual(bdm['ami'], 'sdb')
- self.assertEqual(bdm['ephemeral0'], 'sdc')
diff --git a/tests/unittests/test_filters/__init__.py b/tests/unittests/test_filters/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/unittests/test_filters/__init__.py
+++ /dev/null
diff --git a/tests/unittests/test_filters/test_launch_index.py b/tests/unittests/test_filters/test_launch_index.py
deleted file mode 100644
index 395713e6..00000000
--- a/tests/unittests/test_filters/test_launch_index.py
+++ /dev/null
@@ -1,132 +0,0 @@
-import copy
-
-from .. import helpers
-
-from six.moves import filterfalse
-
-from cloudinit.filters import launch_index
-from cloudinit import user_data as ud
-from cloudinit import util
-
-
-def count_messages(root):
- am = 0
- for m in root.walk():
- if ud.is_skippable(m):
- continue
- am += 1
- return am
-
-
-class TestLaunchFilter(helpers.ResourceUsingTestCase):
-
- def assertCounts(self, message, expected_counts):
- orig_message = copy.deepcopy(message)
- for (index, count) in expected_counts.items():
- index = util.safe_int(index)
- filtered_message = launch_index.Filter(index).apply(message)
- self.assertEqual(count_messages(filtered_message), count)
- # Ensure original message still ok/not modified
- self.assertTrue(self.equivalentMessage(message, orig_message))
-
- def equivalentMessage(self, msg1, msg2):
- msg1_count = count_messages(msg1)
- msg2_count = count_messages(msg2)
- if msg1_count != msg2_count:
- return False
- # Do some basic payload checking
- msg1_msgs = [m for m in msg1.walk()]
- msg1_msgs = [m for m in filterfalse(ud.is_skippable, msg1_msgs)]
- msg2_msgs = [m for m in msg2.walk()]
- msg2_msgs = [m for m in filterfalse(ud.is_skippable, msg2_msgs)]
- for i in range(0, len(msg2_msgs)):
- m1_msg = msg1_msgs[i]
- m2_msg = msg2_msgs[i]
- if m1_msg.get_charset() != m2_msg.get_charset():
- return False
- if m1_msg.is_multipart() != m2_msg.is_multipart():
- return False
- m1_py = m1_msg.get_payload(decode=True)
- m2_py = m2_msg.get_payload(decode=True)
- if m1_py != m2_py:
- return False
- return True
-
- def testMultiEmailIndex(self):
- test_data = self.readResource('filter_cloud_multipart_2.email')
- ud_proc = ud.UserDataProcessor(self.getCloudPaths())
- message = ud_proc.process(test_data)
- self.assertTrue(count_messages(message) > 0)
- # This file should have the following
- # indexes -> amount mapping in it
- expected_counts = {
- 3: 1,
- 2: 2,
- None: 3,
- -1: 0,
- }
- self.assertCounts(message, expected_counts)
-
- def testHeaderEmailIndex(self):
- test_data = self.readResource('filter_cloud_multipart_header.email')
- ud_proc = ud.UserDataProcessor(self.getCloudPaths())
- message = ud_proc.process(test_data)
- self.assertTrue(count_messages(message) > 0)
- # This file should have the following
- # indexes -> amount mapping in it
- expected_counts = {
- 5: 1,
- -1: 0,
- 'c': 1,
- None: 1,
- }
- self.assertCounts(message, expected_counts)
-
- def testConfigEmailIndex(self):
- test_data = self.readResource('filter_cloud_multipart_1.email')
- ud_proc = ud.UserDataProcessor(self.getCloudPaths())
- message = ud_proc.process(test_data)
- self.assertTrue(count_messages(message) > 0)
- # This file should have the following
- # indexes -> amount mapping in it
- expected_counts = {
- 2: 1,
- -1: 0,
- None: 1,
- }
- self.assertCounts(message, expected_counts)
-
- def testNoneIndex(self):
- test_data = self.readResource('filter_cloud_multipart.yaml')
- ud_proc = ud.UserDataProcessor(self.getCloudPaths())
- message = ud_proc.process(test_data)
- start_count = count_messages(message)
- self.assertTrue(start_count > 0)
- filtered_message = launch_index.Filter(None).apply(message)
- self.assertTrue(self.equivalentMessage(message, filtered_message))
-
- def testIndexes(self):
- test_data = self.readResource('filter_cloud_multipart.yaml')
- ud_proc = ud.UserDataProcessor(self.getCloudPaths())
- message = ud_proc.process(test_data)
- start_count = count_messages(message)
- self.assertTrue(start_count > 0)
- # This file should have the following
- # indexes -> amount mapping in it
- expected_counts = {
- 2: 2,
- 3: 2,
- 1: 2,
- 0: 1,
- 4: 1,
- 7: 0,
- -1: 0,
- 100: 0,
- # None should just give all back
- None: start_count,
- # Non ints should be ignored
- 'c': start_count,
- # Strings should be converted
- '1': 2,
- }
- self.assertCounts(message, expected_counts)
diff --git a/tests/unittests/test_handler/__init__.py b/tests/unittests/test_handler/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/unittests/test_handler/__init__.py
+++ /dev/null
diff --git a/tests/unittests/test_handler/test_handler_apt_configure.py b/tests/unittests/test_handler/test_handler_apt_configure.py
deleted file mode 100644
index d1dca2c4..00000000
--- a/tests/unittests/test_handler/test_handler_apt_configure.py
+++ /dev/null
@@ -1,109 +0,0 @@
-from cloudinit.config import cc_apt_configure
-from cloudinit import util
-
-from ..helpers import TestCase
-
-import os
-import re
-import shutil
-import tempfile
-
-
-def load_tfile_or_url(*args, **kwargs):
- return(util.decode_binary(util.read_file_or_url(*args, **kwargs).contents))
-
-
-class TestAptProxyConfig(TestCase):
- def setUp(self):
- super(TestAptProxyConfig, self).setUp()
- self.tmp = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp)
- self.pfile = os.path.join(self.tmp, "proxy.cfg")
- self.cfile = os.path.join(self.tmp, "config.cfg")
-
- def _search_apt_config(self, contents, ptype, value):
- return re.search(
- r"acquire::%s::proxy\s+[\"']%s[\"'];\n" % (ptype, value),
- contents, flags=re.IGNORECASE)
-
- def test_apt_proxy_written(self):
- cfg = {'apt_proxy': 'myproxy'}
- cc_apt_configure.apply_apt_config(cfg, self.pfile, self.cfile)
-
- self.assertTrue(os.path.isfile(self.pfile))
- self.assertFalse(os.path.isfile(self.cfile))
-
- contents = load_tfile_or_url(self.pfile)
- self.assertTrue(self._search_apt_config(contents, "http", "myproxy"))
-
- def test_apt_http_proxy_written(self):
- cfg = {'apt_http_proxy': 'myproxy'}
- cc_apt_configure.apply_apt_config(cfg, self.pfile, self.cfile)
-
- self.assertTrue(os.path.isfile(self.pfile))
- self.assertFalse(os.path.isfile(self.cfile))
-
- contents = load_tfile_or_url(self.pfile)
- self.assertTrue(self._search_apt_config(contents, "http", "myproxy"))
-
- def test_apt_all_proxy_written(self):
- cfg = {'apt_http_proxy': 'myproxy_http_proxy',
- 'apt_https_proxy': 'myproxy_https_proxy',
- 'apt_ftp_proxy': 'myproxy_ftp_proxy'}
-
- values = {'http': cfg['apt_http_proxy'],
- 'https': cfg['apt_https_proxy'],
- 'ftp': cfg['apt_ftp_proxy'],
- }
-
- cc_apt_configure.apply_apt_config(cfg, self.pfile, self.cfile)
-
- self.assertTrue(os.path.isfile(self.pfile))
- self.assertFalse(os.path.isfile(self.cfile))
-
- contents = load_tfile_or_url(self.pfile)
-
- for ptype, pval in values.items():
- self.assertTrue(self._search_apt_config(contents, ptype, pval))
-
- def test_proxy_deleted(self):
- util.write_file(self.cfile, "content doesnt matter")
- cc_apt_configure.apply_apt_config({}, self.pfile, self.cfile)
- self.assertFalse(os.path.isfile(self.pfile))
- self.assertFalse(os.path.isfile(self.cfile))
-
- def test_proxy_replaced(self):
- util.write_file(self.cfile, "content doesnt matter")
- cc_apt_configure.apply_apt_config({'apt_proxy': "foo"},
- self.pfile, self.cfile)
- self.assertTrue(os.path.isfile(self.pfile))
- contents = load_tfile_or_url(self.pfile)
- self.assertTrue(self._search_apt_config(contents, "http", "foo"))
-
- def test_config_written(self):
- payload = 'this is my apt config'
- cfg = {'apt_config': payload}
-
- cc_apt_configure.apply_apt_config(cfg, self.pfile, self.cfile)
-
- self.assertTrue(os.path.isfile(self.cfile))
- self.assertFalse(os.path.isfile(self.pfile))
-
- self.assertEqual(load_tfile_or_url(self.cfile), payload)
-
- def test_config_replaced(self):
- util.write_file(self.pfile, "content doesnt matter")
- cc_apt_configure.apply_apt_config({'apt_config': "foo"},
- self.pfile, self.cfile)
- self.assertTrue(os.path.isfile(self.cfile))
- self.assertEqual(load_tfile_or_url(self.cfile), "foo")
-
- def test_config_deleted(self):
- # if no 'apt_config' is provided, delete any previously written file
- util.write_file(self.pfile, "content doesnt matter")
- cc_apt_configure.apply_apt_config({}, self.pfile, self.cfile)
- self.assertFalse(os.path.isfile(self.pfile))
- self.assertFalse(os.path.isfile(self.cfile))
-
-
-# vi: ts=4 expandtab
diff --git a/tests/unittests/test_handler/test_handler_apt_configure_sources_list.py b/tests/unittests/test_handler/test_handler_apt_configure_sources_list.py
deleted file mode 100644
index acde0863..00000000
--- a/tests/unittests/test_handler/test_handler_apt_configure_sources_list.py
+++ /dev/null
@@ -1,180 +0,0 @@
-""" test_handler_apt_configure_sources_list
-Test templating of sources list
-"""
-import logging
-import os
-import shutil
-import tempfile
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-
-from cloudinit import cloud
-from cloudinit import distros
-from cloudinit import helpers
-from cloudinit import templater
-from cloudinit import util
-
-from cloudinit.config import cc_apt_configure
-from cloudinit.sources import DataSourceNone
-
-from cloudinit.distros.debian import Distro
-
-from .. import helpers as t_help
-
-LOG = logging.getLogger(__name__)
-
-YAML_TEXT_CUSTOM_SL = """
-apt_mirror: http://archive.ubuntu.com/ubuntu/
-apt_custom_sources_list: |
- ## template:jinja
- ## Note, this file is written by cloud-init on first boot of an instance
- ## modifications made here will not survive a re-bundle.
- ## if you wish to make changes you can:
- ## a.) add 'apt_preserve_sources_list: true' to /etc/cloud/cloud.cfg
- ## or do the same in user-data
- ## b.) add sources in /etc/apt/sources.list.d
- ## c.) make changes to template file /etc/cloud/templates/sources.list.tmpl
-
- # See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
- # newer versions of the distribution.
- deb {{mirror}} {{codename}} main restricted
- deb-src {{mirror}} {{codename}} main restricted
- # FIND_SOMETHING_SPECIAL
-"""
-
-EXPECTED_CONVERTED_CONTENT = (
- """## Note, this file is written by cloud-init on first boot of an instance
-## modifications made here will not survive a re-bundle.
-## if you wish to make changes you can:
-## a.) add 'apt_preserve_sources_list: true' to /etc/cloud/cloud.cfg
-## or do the same in user-data
-## b.) add sources in /etc/apt/sources.list.d
-## c.) make changes to template file /etc/cloud/templates/sources.list.tmpl
-
-# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
-# newer versions of the distribution.
-deb http://archive.ubuntu.com/ubuntu/ fakerelease main restricted
-deb-src http://archive.ubuntu.com/ubuntu/ fakerelease main restricted
-# FIND_SOMETHING_SPECIAL
-""")
-
-
-def load_tfile_or_url(*args, **kwargs):
- """load_tfile_or_url
- load file and return content after decoding
- """
- return util.decode_binary(util.read_file_or_url(*args, **kwargs).contents)
-
-
-class TestAptSourceConfigSourceList(t_help.FilesystemMockingTestCase):
- """TestAptSourceConfigSourceList
- Main Class to test sources list rendering
- """
- def setUp(self):
- super(TestAptSourceConfigSourceList, self).setUp()
- self.subp = util.subp
- self.new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.new_root)
-
- def _get_cloud(self, distro, metadata=None):
- self.patchUtils(self.new_root)
- paths = helpers.Paths({})
- cls = distros.fetch(distro)
- mydist = cls(distro, {}, paths)
- myds = DataSourceNone.DataSourceNone({}, mydist, paths)
- if metadata:
- myds.metadata.update(metadata)
- return cloud.Cloud(myds, paths, {}, mydist, None)
-
- def apt_source_list(self, distro, mirror, mirrorcheck=None):
- """apt_source_list
- Test rendering of a source.list from template for a given distro
- """
- if mirrorcheck is None:
- mirrorcheck = mirror
-
- if isinstance(mirror, list):
- cfg = {'apt_mirror_search': mirror}
- else:
- cfg = {'apt_mirror': mirror}
- mycloud = self._get_cloud(distro)
-
- with mock.patch.object(templater, 'render_to_file') as mocktmpl:
- with mock.patch.object(os.path, 'isfile',
- return_value=True) as mockisfile:
- with mock.patch.object(util, 'rename'):
- cc_apt_configure.handle("notimportant", cfg, mycloud,
- LOG, None)
-
- mockisfile.assert_any_call(
- ('/etc/cloud/templates/sources.list.%s.tmpl' % distro))
- mocktmpl.assert_called_once_with(
- ('/etc/cloud/templates/sources.list.%s.tmpl' % distro),
- '/etc/apt/sources.list',
- {'codename': '', 'primary': mirrorcheck, 'mirror': mirrorcheck})
-
- def test_apt_source_list_debian(self):
- """Test rendering of a source.list from template for debian"""
- self.apt_source_list('debian', 'http://httpredir.debian.org/debian')
-
- def test_apt_source_list_ubuntu(self):
- """Test rendering of a source.list from template for ubuntu"""
- self.apt_source_list('ubuntu', 'http://archive.ubuntu.com/ubuntu/')
-
- @staticmethod
- def myresolve(name):
- """Fake util.is_resolvable for mirrorfail tests"""
- if name == "does.not.exist":
- print("Faking FAIL for '%s'" % name)
- return False
- else:
- print("Faking SUCCESS for '%s'" % name)
- return True
-
- def test_apt_srcl_debian_mirrorfail(self):
- """Test rendering of a source.list from template for debian"""
- with mock.patch.object(util, 'is_resolvable',
- side_effect=self.myresolve) as mockresolve:
- self.apt_source_list('debian',
- ['http://does.not.exist',
- 'http://httpredir.debian.org/debian'],
- 'http://httpredir.debian.org/debian')
- mockresolve.assert_any_call("does.not.exist")
- mockresolve.assert_any_call("httpredir.debian.org")
-
- def test_apt_srcl_ubuntu_mirrorfail(self):
- """Test rendering of a source.list from template for ubuntu"""
- with mock.patch.object(util, 'is_resolvable',
- side_effect=self.myresolve) as mockresolve:
- self.apt_source_list('ubuntu',
- ['http://does.not.exist',
- 'http://archive.ubuntu.com/ubuntu/'],
- 'http://archive.ubuntu.com/ubuntu/')
- mockresolve.assert_any_call("does.not.exist")
- mockresolve.assert_any_call("archive.ubuntu.com")
-
- def test_apt_srcl_custom(self):
- """Test rendering from a custom source.list template"""
- cfg = util.load_yaml(YAML_TEXT_CUSTOM_SL)
- mycloud = self._get_cloud('ubuntu')
-
- # the second mock restores the original subp
- with mock.patch.object(util, 'write_file') as mockwrite:
- with mock.patch.object(util, 'subp', self.subp):
- with mock.patch.object(cc_apt_configure, 'get_release',
- return_value='fakerelease'):
- with mock.patch.object(Distro, 'get_primary_arch',
- return_value='amd64'):
- cc_apt_configure.handle("notimportant", cfg, mycloud,
- LOG, None)
-
- mockwrite.assert_called_once_with(
- '/etc/apt/sources.list',
- EXPECTED_CONVERTED_CONTENT,
- mode=420)
-
-
-# vi: ts=4 expandtab
diff --git a/tests/unittests/test_handler/test_handler_apt_source.py b/tests/unittests/test_handler/test_handler_apt_source.py
deleted file mode 100644
index 99a4d860..00000000
--- a/tests/unittests/test_handler/test_handler_apt_source.py
+++ /dev/null
@@ -1,516 +0,0 @@
-""" test_handler_apt_source
-Testing various config variations of the apt_source config
-"""
-import os
-import re
-import shutil
-import tempfile
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-from mock import call
-
-from cloudinit.config import cc_apt_configure
-from cloudinit import gpg
-from cloudinit import util
-
-from ..helpers import TestCase
-
-EXPECTEDKEY = """-----BEGIN PGP PUBLIC KEY BLOCK-----
-Version: GnuPG v1
-
-mI0ESuZLUgEEAKkqq3idtFP7g9hzOu1a8+v8ImawQN4TrvlygfScMU1TIS1eC7UQ
-NUA8Qqgr9iUaGnejb0VciqftLrU9D6WYHSKz+EITefgdyJ6SoQxjoJdsCpJ7o9Jy
-8PQnpRttiFm4qHu6BVnKnBNxw/z3ST9YMqW5kbMQpfxbGe+obRox59NpABEBAAG0
-HUxhdW5jaHBhZCBQUEEgZm9yIFNjb3R0IE1vc2VyiLYEEwECACAFAkrmS1ICGwMG
-CwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRAGILvPA2g/d3aEA/9tVjc10HOZwV29
-OatVuTeERjjrIbxflO586GLA8cp0C9RQCwgod/R+cKYdQcHjbqVcP0HqxveLg0RZ
-FJpWLmWKamwkABErwQLGlM/Hwhjfade8VvEQutH5/0JgKHmzRsoqfR+LMO6OS+Sm
-S0ORP6HXET3+jC8BMG4tBWCTK/XEZw==
-=ACB2
------END PGP PUBLIC KEY BLOCK-----"""
-
-
-def load_tfile_or_url(*args, **kwargs):
- """load_tfile_or_url
- load file and return content after decoding
- """
- return util.decode_binary(util.read_file_or_url(*args, **kwargs).contents)
-
-
-class TestAptSourceConfig(TestCase):
- """TestAptSourceConfig
- Main Class to test apt_source configs
- """
- release = "fantastic"
-
- def setUp(self):
- super(TestAptSourceConfig, self).setUp()
- self.tmp = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp)
- self.aptlistfile = os.path.join(self.tmp, "single-deb.list")
- self.aptlistfile2 = os.path.join(self.tmp, "single-deb2.list")
- self.aptlistfile3 = os.path.join(self.tmp, "single-deb3.list")
- self.join = os.path.join
- # mock fallback filename into writable tmp dir
- self.fallbackfn = os.path.join(self.tmp, "etc/apt/sources.list.d/",
- "cloud_config_sources.list")
-
- patcher = mock.patch("cloudinit.config.cc_apt_configure.get_release")
- get_rel = patcher.start()
- get_rel.return_value = self.release
- self.addCleanup(patcher.stop)
-
- @staticmethod
- def _get_default_params():
- """get_default_params
- Get the most basic default mrror and release info to be used in tests
- """
- params = {}
- params['RELEASE'] = cc_apt_configure.get_release()
- params['MIRROR'] = "http://archive.ubuntu.com/ubuntu"
- return params
-
- def myjoin(self, *args, **kwargs):
- """myjoin - redir into writable tmpdir"""
- if (args[0] == "/etc/apt/sources.list.d/" and
- args[1] == "cloud_config_sources.list" and
- len(args) == 2):
- return self.join(self.tmp, args[0].lstrip("/"), args[1])
- else:
- return self.join(*args, **kwargs)
-
- def apt_src_basic(self, filename, cfg):
- """apt_src_basic
- Test Fix deb source string, has to overwrite mirror conf in params
- """
- params = self._get_default_params()
-
- cc_apt_configure.add_apt_sources(cfg, params)
-
- self.assertTrue(os.path.isfile(filename))
-
- contents = load_tfile_or_url(filename)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb", "http://archive.ubuntu.com/ubuntu",
- "karmic-backports",
- "main universe multiverse restricted"),
- contents, flags=re.IGNORECASE))
-
- def test_apt_src_basic(self):
- """Test deb source string, overwrite mirror and filename"""
- cfg = {'source': ('deb http://archive.ubuntu.com/ubuntu'
- ' karmic-backports'
- ' main universe multiverse restricted'),
- 'filename': self.aptlistfile}
- self.apt_src_basic(self.aptlistfile, [cfg])
-
- def test_apt_src_basic_dict(self):
- """Test deb source string, overwrite mirror and filename (dict)"""
- cfg = {self.aptlistfile: {'source':
- ('deb http://archive.ubuntu.com/ubuntu'
- ' karmic-backports'
- ' main universe multiverse restricted')}}
- self.apt_src_basic(self.aptlistfile, cfg)
-
- def apt_src_basic_tri(self, cfg):
- """apt_src_basic_tri
- Test Fix three deb source string, has to overwrite mirror conf in
- params. Test with filenames provided in config.
- generic part to check three files with different content
- """
- self.apt_src_basic(self.aptlistfile, cfg)
-
- # extra verify on two extra files of this test
- contents = load_tfile_or_url(self.aptlistfile2)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb", "http://archive.ubuntu.com/ubuntu",
- "precise-backports",
- "main universe multiverse restricted"),
- contents, flags=re.IGNORECASE))
- contents = load_tfile_or_url(self.aptlistfile3)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb", "http://archive.ubuntu.com/ubuntu",
- "lucid-backports",
- "main universe multiverse restricted"),
- contents, flags=re.IGNORECASE))
-
- def test_apt_src_basic_tri(self):
- """Test Fix three deb source string with filenames"""
- cfg1 = {'source': ('deb http://archive.ubuntu.com/ubuntu'
- ' karmic-backports'
- ' main universe multiverse restricted'),
- 'filename': self.aptlistfile}
- cfg2 = {'source': ('deb http://archive.ubuntu.com/ubuntu'
- ' precise-backports'
- ' main universe multiverse restricted'),
- 'filename': self.aptlistfile2}
- cfg3 = {'source': ('deb http://archive.ubuntu.com/ubuntu'
- ' lucid-backports'
- ' main universe multiverse restricted'),
- 'filename': self.aptlistfile3}
- self.apt_src_basic_tri([cfg1, cfg2, cfg3])
-
- def test_apt_src_basic_dict_tri(self):
- """Test Fix three deb source string with filenames (dict)"""
- cfg = {self.aptlistfile: {'source':
- ('deb http://archive.ubuntu.com/ubuntu'
- ' karmic-backports'
- ' main universe multiverse restricted')},
- self.aptlistfile2: {'source':
- ('deb http://archive.ubuntu.com/ubuntu'
- ' precise-backports'
- ' main universe multiverse restricted')},
- self.aptlistfile3: {'source':
- ('deb http://archive.ubuntu.com/ubuntu'
- ' lucid-backports'
- ' main universe multiverse restricted')}}
- self.apt_src_basic_tri(cfg)
-
- def test_apt_src_basic_nofn(self):
- """Test Fix three deb source string without filenames (dict)"""
- cfg = {'source': ('deb http://archive.ubuntu.com/ubuntu'
- ' karmic-backports'
- ' main universe multiverse restricted')}
- with mock.patch.object(os.path, 'join', side_effect=self.myjoin):
- self.apt_src_basic(self.fallbackfn, [cfg])
-
- def apt_src_replacement(self, filename, cfg):
- """apt_src_replace
- Test Autoreplacement of MIRROR and RELEASE in source specs
- """
- params = self._get_default_params()
- cc_apt_configure.add_apt_sources(cfg, params)
-
- self.assertTrue(os.path.isfile(filename))
-
- contents = load_tfile_or_url(filename)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb", params['MIRROR'], params['RELEASE'],
- "multiverse"),
- contents, flags=re.IGNORECASE))
-
- def test_apt_src_replace(self):
- """Test Autoreplacement of MIRROR and RELEASE in source specs"""
- cfg = {'source': 'deb $MIRROR $RELEASE multiverse',
- 'filename': self.aptlistfile}
- self.apt_src_replacement(self.aptlistfile, [cfg])
-
- def apt_src_replace_tri(self, cfg):
- """apt_src_replace_tri
- Test three autoreplacements of MIRROR and RELEASE in source specs with
- generic part
- """
- self.apt_src_replacement(self.aptlistfile, cfg)
-
- # extra verify on two extra files of this test
- params = self._get_default_params()
- contents = load_tfile_or_url(self.aptlistfile2)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb", params['MIRROR'], params['RELEASE'],
- "main"),
- contents, flags=re.IGNORECASE))
- contents = load_tfile_or_url(self.aptlistfile3)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb", params['MIRROR'], params['RELEASE'],
- "universe"),
- contents, flags=re.IGNORECASE))
-
- def test_apt_src_replace_tri(self):
- """Test triple Autoreplacement of MIRROR and RELEASE in source specs"""
- cfg1 = {'source': 'deb $MIRROR $RELEASE multiverse',
- 'filename': self.aptlistfile}
- cfg2 = {'source': 'deb $MIRROR $RELEASE main',
- 'filename': self.aptlistfile2}
- cfg3 = {'source': 'deb $MIRROR $RELEASE universe',
- 'filename': self.aptlistfile3}
- self.apt_src_replace_tri([cfg1, cfg2, cfg3])
-
- def test_apt_src_replace_dict_tri(self):
- """Test triple Autoreplacement in source specs (dict)"""
- cfg = {self.aptlistfile: {'source': 'deb $MIRROR $RELEASE multiverse'},
- 'notused': {'source': 'deb $MIRROR $RELEASE main',
- 'filename': self.aptlistfile2},
- self.aptlistfile3: {'source': 'deb $MIRROR $RELEASE universe'}}
- self.apt_src_replace_tri(cfg)
-
- def test_apt_src_replace_nofn(self):
- """Test Autoreplacement of MIRROR and RELEASE in source specs nofile"""
- cfg = {'source': 'deb $MIRROR $RELEASE multiverse'}
- with mock.patch.object(os.path, 'join', side_effect=self.myjoin):
- self.apt_src_replacement(self.fallbackfn, [cfg])
-
- def apt_src_keyid(self, filename, cfg, keynum):
- """apt_src_keyid
- Test specification of a source + keyid
- """
- params = self._get_default_params()
-
- with mock.patch.object(util, 'subp',
- return_value=('fakekey 1234', '')) as mockobj:
- cc_apt_configure.add_apt_sources(cfg, params)
-
- # check if it added the right ammount of keys
- calls = []
- for _ in range(keynum):
- calls.append(call(('apt-key', 'add', '-'), 'fakekey 1234'))
- mockobj.assert_has_calls(calls, any_order=True)
-
- self.assertTrue(os.path.isfile(filename))
-
- contents = load_tfile_or_url(filename)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb",
- ('http://ppa.launchpad.net/smoser/'
- 'cloud-init-test/ubuntu'),
- "xenial", "main"),
- contents, flags=re.IGNORECASE))
-
- def test_apt_src_keyid(self):
- """Test specification of a source + keyid with filename being set"""
- cfg = {'source': ('deb '
- 'http://ppa.launchpad.net/'
- 'smoser/cloud-init-test/ubuntu'
- ' xenial main'),
- 'keyid': "03683F77",
- 'filename': self.aptlistfile}
- self.apt_src_keyid(self.aptlistfile, [cfg], 1)
-
- def test_apt_src_keyid_tri(self):
- """Test 3x specification of a source + keyid with filename being set"""
- cfg1 = {'source': ('deb '
- 'http://ppa.launchpad.net/'
- 'smoser/cloud-init-test/ubuntu'
- ' xenial main'),
- 'keyid': "03683F77",
- 'filename': self.aptlistfile}
- cfg2 = {'source': ('deb '
- 'http://ppa.launchpad.net/'
- 'smoser/cloud-init-test/ubuntu'
- ' xenial universe'),
- 'keyid': "03683F77",
- 'filename': self.aptlistfile2}
- cfg3 = {'source': ('deb '
- 'http://ppa.launchpad.net/'
- 'smoser/cloud-init-test/ubuntu'
- ' xenial multiverse'),
- 'keyid': "03683F77",
- 'filename': self.aptlistfile3}
-
- self.apt_src_keyid(self.aptlistfile, [cfg1, cfg2, cfg3], 3)
- contents = load_tfile_or_url(self.aptlistfile2)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb",
- ('http://ppa.launchpad.net/smoser/'
- 'cloud-init-test/ubuntu'),
- "xenial", "universe"),
- contents, flags=re.IGNORECASE))
- contents = load_tfile_or_url(self.aptlistfile3)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb",
- ('http://ppa.launchpad.net/smoser/'
- 'cloud-init-test/ubuntu'),
- "xenial", "multiverse"),
- contents, flags=re.IGNORECASE))
-
- def test_apt_src_keyid_nofn(self):
- """Test specification of a source + keyid without filename being set"""
- cfg = {'source': ('deb '
- 'http://ppa.launchpad.net/'
- 'smoser/cloud-init-test/ubuntu'
- ' xenial main'),
- 'keyid': "03683F77"}
- with mock.patch.object(os.path, 'join', side_effect=self.myjoin):
- self.apt_src_keyid(self.fallbackfn, [cfg], 1)
-
- def apt_src_key(self, filename, cfg):
- """apt_src_key
- Test specification of a source + key
- """
- params = self._get_default_params()
-
- with mock.patch.object(util, 'subp') as mockobj:
- cc_apt_configure.add_apt_sources([cfg], params)
-
- mockobj.assert_called_with(('apt-key', 'add', '-'), 'fakekey 4321')
-
- self.assertTrue(os.path.isfile(filename))
-
- contents = load_tfile_or_url(filename)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb",
- ('http://ppa.launchpad.net/smoser/'
- 'cloud-init-test/ubuntu'),
- "xenial", "main"),
- contents, flags=re.IGNORECASE))
-
- def test_apt_src_key(self):
- """Test specification of a source + key with filename being set"""
- cfg = {'source': ('deb '
- 'http://ppa.launchpad.net/'
- 'smoser/cloud-init-test/ubuntu'
- ' xenial main'),
- 'key': "fakekey 4321",
- 'filename': self.aptlistfile}
- self.apt_src_key(self.aptlistfile, cfg)
-
- def test_apt_src_key_nofn(self):
- """Test specification of a source + key without filename being set"""
- cfg = {'source': ('deb '
- 'http://ppa.launchpad.net/'
- 'smoser/cloud-init-test/ubuntu'
- ' xenial main'),
- 'key': "fakekey 4321"}
- with mock.patch.object(os.path, 'join', side_effect=self.myjoin):
- self.apt_src_key(self.fallbackfn, cfg)
-
- def test_apt_src_keyonly(self):
- """Test specifying key without source"""
- params = self._get_default_params()
- cfg = {'key': "fakekey 4242",
- 'filename': self.aptlistfile}
-
- with mock.patch.object(util, 'subp') as mockobj:
- cc_apt_configure.add_apt_sources([cfg], params)
-
- mockobj.assert_called_once_with(('apt-key', 'add', '-'),
- 'fakekey 4242')
-
- # filename should be ignored on key only
- self.assertFalse(os.path.isfile(self.aptlistfile))
-
- def test_apt_src_keyidonly(self):
- """Test specification of a keyid without source"""
- params = self._get_default_params()
- cfg = {'keyid': "03683F77",
- 'filename': self.aptlistfile}
-
- with mock.patch.object(util, 'subp',
- return_value=('fakekey 1212', '')) as mockobj:
- cc_apt_configure.add_apt_sources([cfg], params)
-
- mockobj.assert_called_with(('apt-key', 'add', '-'), 'fakekey 1212')
-
- # filename should be ignored on key only
- self.assertFalse(os.path.isfile(self.aptlistfile))
-
- def apt_src_keyid_real(self, cfg, expectedkey):
- """apt_src_keyid_real
- Test specification of a keyid without source including
- up to addition of the key (add_apt_key_raw mocked to keep the
- environment as is)
- """
- params = self._get_default_params()
-
- with mock.patch.object(cc_apt_configure, 'add_apt_key_raw') as mockkey:
- with mock.patch.object(gpg, 'get_key_by_id',
- return_value=expectedkey) as mockgetkey:
- cc_apt_configure.add_apt_sources([cfg], params)
-
- mockgetkey.assert_called_with(cfg['keyid'],
- cfg.get('keyserver',
- 'keyserver.ubuntu.com'))
- mockkey.assert_called_with(expectedkey)
-
- # filename should be ignored on key only
- self.assertFalse(os.path.isfile(self.aptlistfile))
-
- def test_apt_src_keyid_real(self):
- """test_apt_src_keyid_real - Test keyid including key add"""
- keyid = "03683F77"
- cfg = {'keyid': keyid,
- 'filename': self.aptlistfile}
-
- self.apt_src_keyid_real(cfg, EXPECTEDKEY)
-
- def test_apt_src_longkeyid_real(self):
- """test_apt_src_longkeyid_real - Test long keyid including key add"""
- keyid = "B59D 5F15 97A5 04B7 E230 6DCA 0620 BBCF 0368 3F77"
- cfg = {'keyid': keyid,
- 'filename': self.aptlistfile}
-
- self.apt_src_keyid_real(cfg, EXPECTEDKEY)
-
- def test_apt_src_longkeyid_ks_real(self):
- """test_apt_src_longkeyid_ks_real - Test long keyid from other ks"""
- keyid = "B59D 5F15 97A5 04B7 E230 6DCA 0620 BBCF 0368 3F77"
- cfg = {'keyid': keyid,
- 'keyserver': 'keys.gnupg.net',
- 'filename': self.aptlistfile}
-
- self.apt_src_keyid_real(cfg, EXPECTEDKEY)
-
- def test_apt_src_ppa(self):
- """Test adding a ppa"""
- params = self._get_default_params()
- cfg = {'source': 'ppa:smoser/cloud-init-test',
- 'filename': self.aptlistfile}
-
- # default matcher needed for ppa
- matcher = re.compile(r'^[\w-]+:\w').search
-
- with mock.patch.object(util, 'subp') as mockobj:
- cc_apt_configure.add_apt_sources([cfg], params,
- aa_repo_match=matcher)
- mockobj.assert_called_once_with(['add-apt-repository',
- 'ppa:smoser/cloud-init-test'])
-
- # adding ppa should ignore filename (uses add-apt-repository)
- self.assertFalse(os.path.isfile(self.aptlistfile))
-
- def test_apt_src_ppa_tri(self):
- """Test adding three ppa's"""
- params = self._get_default_params()
- cfg1 = {'source': 'ppa:smoser/cloud-init-test',
- 'filename': self.aptlistfile}
- cfg2 = {'source': 'ppa:smoser/cloud-init-test2',
- 'filename': self.aptlistfile2}
- cfg3 = {'source': 'ppa:smoser/cloud-init-test3',
- 'filename': self.aptlistfile3}
-
- # default matcher needed for ppa
- matcher = re.compile(r'^[\w-]+:\w').search
-
- with mock.patch.object(util, 'subp') as mockobj:
- cc_apt_configure.add_apt_sources([cfg1, cfg2, cfg3], params,
- aa_repo_match=matcher)
- calls = [call(['add-apt-repository', 'ppa:smoser/cloud-init-test']),
- call(['add-apt-repository', 'ppa:smoser/cloud-init-test2']),
- call(['add-apt-repository', 'ppa:smoser/cloud-init-test3'])]
- mockobj.assert_has_calls(calls, any_order=True)
-
- # adding ppa should ignore all filenames (uses add-apt-repository)
- self.assertFalse(os.path.isfile(self.aptlistfile))
- self.assertFalse(os.path.isfile(self.aptlistfile2))
- self.assertFalse(os.path.isfile(self.aptlistfile3))
-
- def test_convert_to_new_format(self):
- """Test the conversion of old to new format"""
- cfg1 = {'source': 'deb $MIRROR $RELEASE multiverse',
- 'filename': self.aptlistfile}
- cfg2 = {'source': 'deb $MIRROR $RELEASE main',
- 'filename': self.aptlistfile2}
- cfg3 = {'source': 'deb $MIRROR $RELEASE universe',
- 'filename': self.aptlistfile3}
- checkcfg = {self.aptlistfile: {'filename': self.aptlistfile,
- 'source': 'deb $MIRROR $RELEASE '
- 'multiverse'},
- self.aptlistfile2: {'filename': self.aptlistfile2,
- 'source': 'deb $MIRROR $RELEASE main'},
- self.aptlistfile3: {'filename': self.aptlistfile3,
- 'source': 'deb $MIRROR $RELEASE '
- 'universe'}}
-
- newcfg = cc_apt_configure.convert_to_new_format([cfg1, cfg2, cfg3])
- self.assertEqual(newcfg, checkcfg)
-
- newcfg2 = cc_apt_configure.convert_to_new_format(newcfg)
- self.assertEqual(newcfg2, checkcfg)
-
- with self.assertRaises(ValueError):
- cc_apt_configure.convert_to_new_format(5)
-
-
-# vi: ts=4 expandtab
diff --git a/tests/unittests/test_handler/test_handler_ca_certs.py b/tests/unittests/test_handler/test_handler_ca_certs.py
deleted file mode 100644
index 5e771731..00000000
--- a/tests/unittests/test_handler/test_handler_ca_certs.py
+++ /dev/null
@@ -1,271 +0,0 @@
-from cloudinit import cloud
-from cloudinit.config import cc_ca_certs
-from cloudinit import helpers
-from cloudinit import util
-
-from ..helpers import TestCase
-
-import logging
-import shutil
-import tempfile
-import unittest
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-try:
- from contextlib import ExitStack
-except ImportError:
- from contextlib2 import ExitStack
-
-
-class TestNoConfig(unittest.TestCase):
- def setUp(self):
- super(TestNoConfig, self).setUp()
- self.name = "ca-certs"
- self.cloud_init = None
- self.log = logging.getLogger("TestNoConfig")
- self.args = []
-
- def test_no_config(self):
- """
- Test that nothing is done if no ca-certs configuration is provided.
- """
- config = util.get_builtin_cfg()
- with ExitStack() as mocks:
- util_mock = mocks.enter_context(
- mock.patch.object(util, 'write_file'))
- certs_mock = mocks.enter_context(
- mock.patch.object(cc_ca_certs, 'update_ca_certs'))
-
- cc_ca_certs.handle(self.name, config, self.cloud_init, self.log,
- self.args)
-
- self.assertEqual(util_mock.call_count, 0)
- self.assertEqual(certs_mock.call_count, 0)
-
-
-class TestConfig(TestCase):
- def setUp(self):
- super(TestConfig, self).setUp()
- self.name = "ca-certs"
- self.paths = None
- self.cloud = cloud.Cloud(None, self.paths, None, None, None)
- self.log = logging.getLogger("TestNoConfig")
- self.args = []
-
- self.mocks = ExitStack()
- self.addCleanup(self.mocks.close)
-
- # Mock out the functions that actually modify the system
- self.mock_add = self.mocks.enter_context(
- mock.patch.object(cc_ca_certs, 'add_ca_certs'))
- self.mock_update = self.mocks.enter_context(
- mock.patch.object(cc_ca_certs, 'update_ca_certs'))
- self.mock_remove = self.mocks.enter_context(
- mock.patch.object(cc_ca_certs, 'remove_default_ca_certs'))
-
- def test_no_trusted_list(self):
- """
- Test that no certificates are written if the 'trusted' key is not
- present.
- """
- config = {"ca-certs": {}}
-
- cc_ca_certs.handle(self.name, config, self.cloud, self.log, self.args)
-
- self.assertEqual(self.mock_add.call_count, 0)
- self.assertEqual(self.mock_update.call_count, 1)
- self.assertEqual(self.mock_remove.call_count, 0)
-
- def test_empty_trusted_list(self):
- """Test that no certificate are written if 'trusted' list is empty."""
- config = {"ca-certs": {"trusted": []}}
-
- cc_ca_certs.handle(self.name, config, self.cloud, self.log, self.args)
-
- self.assertEqual(self.mock_add.call_count, 0)
- self.assertEqual(self.mock_update.call_count, 1)
- self.assertEqual(self.mock_remove.call_count, 0)
-
- def test_single_trusted(self):
- """Test that a single cert gets passed to add_ca_certs."""
- config = {"ca-certs": {"trusted": ["CERT1"]}}
-
- cc_ca_certs.handle(self.name, config, self.cloud, self.log, self.args)
-
- self.mock_add.assert_called_once_with(['CERT1'])
- self.assertEqual(self.mock_update.call_count, 1)
- self.assertEqual(self.mock_remove.call_count, 0)
-
- def test_multiple_trusted(self):
- """Test that multiple certs get passed to add_ca_certs."""
- config = {"ca-certs": {"trusted": ["CERT1", "CERT2"]}}
-
- cc_ca_certs.handle(self.name, config, self.cloud, self.log, self.args)
-
- self.mock_add.assert_called_once_with(['CERT1', 'CERT2'])
- self.assertEqual(self.mock_update.call_count, 1)
- self.assertEqual(self.mock_remove.call_count, 0)
-
- def test_remove_default_ca_certs(self):
- """Test remove_defaults works as expected."""
- config = {"ca-certs": {"remove-defaults": True}}
-
- cc_ca_certs.handle(self.name, config, self.cloud, self.log, self.args)
-
- self.assertEqual(self.mock_add.call_count, 0)
- self.assertEqual(self.mock_update.call_count, 1)
- self.assertEqual(self.mock_remove.call_count, 1)
-
- def test_no_remove_defaults_if_false(self):
- """Test remove_defaults is not called when config value is False."""
- config = {"ca-certs": {"remove-defaults": False}}
-
- cc_ca_certs.handle(self.name, config, self.cloud, self.log, self.args)
-
- self.assertEqual(self.mock_add.call_count, 0)
- self.assertEqual(self.mock_update.call_count, 1)
- self.assertEqual(self.mock_remove.call_count, 0)
-
- def test_correct_order_for_remove_then_add(self):
- """Test remove_defaults is not called when config value is False."""
- config = {"ca-certs": {"remove-defaults": True, "trusted": ["CERT1"]}}
-
- cc_ca_certs.handle(self.name, config, self.cloud, self.log, self.args)
-
- self.mock_add.assert_called_once_with(['CERT1'])
- self.assertEqual(self.mock_update.call_count, 1)
- self.assertEqual(self.mock_remove.call_count, 1)
-
-
-class TestAddCaCerts(TestCase):
-
- def setUp(self):
- super(TestAddCaCerts, self).setUp()
- tmpdir = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, tmpdir)
- self.paths = helpers.Paths({
- 'cloud_dir': tmpdir,
- })
-
- def test_no_certs_in_list(self):
- """Test that no certificate are written if not provided."""
- with mock.patch.object(util, 'write_file') as mockobj:
- cc_ca_certs.add_ca_certs([])
- self.assertEqual(mockobj.call_count, 0)
-
- def test_single_cert_trailing_cr(self):
- """Test adding a single certificate to the trusted CAs
- when existing ca-certificates has trailing newline"""
- cert = "CERT1\nLINE2\nLINE3"
-
- ca_certs_content = "line1\nline2\ncloud-init-ca-certs.crt\nline3\n"
- expected = "line1\nline2\nline3\ncloud-init-ca-certs.crt\n"
-
- with ExitStack() as mocks:
- mock_write = mocks.enter_context(
- mock.patch.object(util, 'write_file'))
- mock_load = mocks.enter_context(
- mock.patch.object(util, 'load_file',
- return_value=ca_certs_content))
-
- cc_ca_certs.add_ca_certs([cert])
-
- mock_write.assert_has_calls([
- mock.call("/usr/share/ca-certificates/cloud-init-ca-certs.crt",
- cert, mode=0o644),
- mock.call("/etc/ca-certificates.conf", expected, omode="wb")])
- mock_load.assert_called_once_with("/etc/ca-certificates.conf")
-
- def test_single_cert_no_trailing_cr(self):
- """Test adding a single certificate to the trusted CAs
- when existing ca-certificates has no trailing newline"""
- cert = "CERT1\nLINE2\nLINE3"
-
- ca_certs_content = "line1\nline2\nline3"
-
- with ExitStack() as mocks:
- mock_write = mocks.enter_context(
- mock.patch.object(util, 'write_file'))
- mock_load = mocks.enter_context(
- mock.patch.object(util, 'load_file',
- return_value=ca_certs_content))
-
- cc_ca_certs.add_ca_certs([cert])
-
- mock_write.assert_has_calls([
- mock.call("/usr/share/ca-certificates/cloud-init-ca-certs.crt",
- cert, mode=0o644),
- mock.call("/etc/ca-certificates.conf",
- "%s\n%s\n" % (ca_certs_content,
- "cloud-init-ca-certs.crt"),
- omode="wb")])
-
- mock_load.assert_called_once_with("/etc/ca-certificates.conf")
-
- def test_multiple_certs(self):
- """Test adding multiple certificates to the trusted CAs."""
- certs = ["CERT1\nLINE2\nLINE3", "CERT2\nLINE2\nLINE3"]
- expected_cert_file = "\n".join(certs)
- ca_certs_content = "line1\nline2\nline3"
-
- with ExitStack() as mocks:
- mock_write = mocks.enter_context(
- mock.patch.object(util, 'write_file'))
- mock_load = mocks.enter_context(
- mock.patch.object(util, 'load_file',
- return_value=ca_certs_content))
-
- cc_ca_certs.add_ca_certs(certs)
-
- mock_write.assert_has_calls([
- mock.call("/usr/share/ca-certificates/cloud-init-ca-certs.crt",
- expected_cert_file, mode=0o644),
- mock.call("/etc/ca-certificates.conf",
- "%s\n%s\n" % (ca_certs_content,
- "cloud-init-ca-certs.crt"),
- omode='wb')])
-
- mock_load.assert_called_once_with("/etc/ca-certificates.conf")
-
-
-class TestUpdateCaCerts(unittest.TestCase):
- def test_commands(self):
- with mock.patch.object(util, 'subp') as mockobj:
- cc_ca_certs.update_ca_certs()
- mockobj.assert_called_once_with(
- ["update-ca-certificates"], capture=False)
-
-
-class TestRemoveDefaultCaCerts(TestCase):
-
- def setUp(self):
- super(TestRemoveDefaultCaCerts, self).setUp()
- tmpdir = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, tmpdir)
- self.paths = helpers.Paths({
- 'cloud_dir': tmpdir,
- })
-
- def test_commands(self):
- with ExitStack() as mocks:
- mock_delete = mocks.enter_context(
- mock.patch.object(util, 'delete_dir_contents'))
- mock_write = mocks.enter_context(
- mock.patch.object(util, 'write_file'))
- mock_subp = mocks.enter_context(mock.patch.object(util, 'subp'))
-
- cc_ca_certs.remove_default_ca_certs()
-
- mock_delete.assert_has_calls([
- mock.call("/usr/share/ca-certificates/"),
- mock.call("/etc/ssl/certs/")])
-
- mock_write.assert_called_once_with(
- "/etc/ca-certificates.conf", "", mode=0o644)
-
- mock_subp.assert_called_once_with(
- ('debconf-set-selections', '-'),
- "ca-certificates ca-certificates/trust_new_crts select no")
diff --git a/tests/unittests/test_handler/test_handler_chef.py b/tests/unittests/test_handler/test_handler_chef.py
deleted file mode 100644
index 7a1bc317..00000000
--- a/tests/unittests/test_handler/test_handler_chef.py
+++ /dev/null
@@ -1,192 +0,0 @@
-import json
-import logging
-import os
-import shutil
-import six
-import tempfile
-
-from cloudinit import cloud
-from cloudinit.config import cc_chef
-from cloudinit import distros
-from cloudinit import helpers
-from cloudinit.sources import DataSourceNone
-from cloudinit import util
-
-from .. import helpers as t_help
-
-LOG = logging.getLogger(__name__)
-
-CLIENT_TEMPL = os.path.sep.join(["templates", "chef_client.rb.tmpl"])
-
-
-class TestChef(t_help.FilesystemMockingTestCase):
- def setUp(self):
- super(TestChef, self).setUp()
- self.tmp = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp)
-
- def fetch_cloud(self, distro_kind):
- cls = distros.fetch(distro_kind)
- paths = helpers.Paths({})
- distro = cls(distro_kind, {}, paths)
- ds = DataSourceNone.DataSourceNone({}, distro, paths, None)
- return cloud.Cloud(ds, paths, {}, distro, None)
-
- def test_no_config(self):
- self.patchUtils(self.tmp)
- self.patchOS(self.tmp)
-
- cfg = {}
- cc_chef.handle('chef', cfg, self.fetch_cloud('ubuntu'), LOG, [])
- for d in cc_chef.CHEF_DIRS:
- self.assertFalse(os.path.isdir(d))
-
- @t_help.skipIf(not os.path.isfile(CLIENT_TEMPL),
- CLIENT_TEMPL + " is not available")
- def test_basic_config(self):
- """
- test basic config looks sane
-
- # This should create a file of the format...
- # Created by cloud-init v. 0.7.6 on Sat, 11 Oct 2014 23:57:21 +0000
- log_level :info
- ssl_verify_mode :verify_none
- log_location "/var/log/chef/client.log"
- validation_client_name "bob"
- validation_key "/etc/chef/validation.pem"
- client_key "/etc/chef/client.pem"
- chef_server_url "localhost"
- environment "_default"
- node_name "iid-datasource-none"
- json_attribs "/etc/chef/firstboot.json"
- file_cache_path "/var/cache/chef"
- file_backup_path "/var/backups/chef"
- pid_file "/var/run/chef/client.pid"
- Chef::Log::Formatter.show_time = true
- """
- tpl_file = util.load_file('templates/chef_client.rb.tmpl')
- self.patchUtils(self.tmp)
- self.patchOS(self.tmp)
-
- util.write_file('/etc/cloud/templates/chef_client.rb.tmpl', tpl_file)
- cfg = {
- 'chef': {
- 'server_url': 'localhost',
- 'validation_name': 'bob',
- 'validation_key': "/etc/chef/vkey.pem",
- 'validation_cert': "this is my cert",
- },
- }
- cc_chef.handle('chef', cfg, self.fetch_cloud('ubuntu'), LOG, [])
- for d in cc_chef.CHEF_DIRS:
- self.assertTrue(os.path.isdir(d))
- c = util.load_file(cc_chef.CHEF_RB_PATH)
-
- # the content of these keys is not expected to be rendered to tmpl
- unrendered_keys = ('validation_cert',)
- for k, v in cfg['chef'].items():
- if k in unrendered_keys:
- continue
- self.assertIn(v, c)
- for k, v in cc_chef.CHEF_RB_TPL_DEFAULTS.items():
- if k in unrendered_keys:
- continue
- # the value from the cfg overrides that in the default
- val = cfg['chef'].get(k, v)
- if isinstance(val, six.string_types):
- self.assertIn(val, c)
- c = util.load_file(cc_chef.CHEF_FB_PATH)
- self.assertEqual({}, json.loads(c))
-
- def test_firstboot_json(self):
- self.patchUtils(self.tmp)
- self.patchOS(self.tmp)
-
- cfg = {
- 'chef': {
- 'server_url': 'localhost',
- 'validation_name': 'bob',
- 'run_list': ['a', 'b', 'c'],
- 'initial_attributes': {
- 'c': 'd',
- }
- },
- }
- cc_chef.handle('chef', cfg, self.fetch_cloud('ubuntu'), LOG, [])
- c = util.load_file(cc_chef.CHEF_FB_PATH)
- self.assertEqual(
- {
- 'run_list': ['a', 'b', 'c'],
- 'c': 'd',
- }, json.loads(c))
-
- @t_help.skipIf(not os.path.isfile(CLIENT_TEMPL),
- CLIENT_TEMPL + " is not available")
- def test_template_deletes(self):
- tpl_file = util.load_file('templates/chef_client.rb.tmpl')
- self.patchUtils(self.tmp)
- self.patchOS(self.tmp)
-
- util.write_file('/etc/cloud/templates/chef_client.rb.tmpl', tpl_file)
- cfg = {
- 'chef': {
- 'server_url': 'localhost',
- 'validation_name': 'bob',
- 'json_attribs': None,
- 'show_time': None,
- },
- }
- cc_chef.handle('chef', cfg, self.fetch_cloud('ubuntu'), LOG, [])
- c = util.load_file(cc_chef.CHEF_RB_PATH)
- self.assertNotIn('json_attribs', c)
- self.assertNotIn('Formatter.show_time', c)
-
- @t_help.skipIf(not os.path.isfile(CLIENT_TEMPL),
- CLIENT_TEMPL + " is not available")
- def test_validation_cert_and_validation_key(self):
- # test validation_cert content is written to validation_key path
- tpl_file = util.load_file('templates/chef_client.rb.tmpl')
- self.patchUtils(self.tmp)
- self.patchOS(self.tmp)
-
- util.write_file('/etc/cloud/templates/chef_client.rb.tmpl', tpl_file)
- v_path = '/etc/chef/vkey.pem'
- v_cert = 'this is my cert'
- cfg = {
- 'chef': {
- 'server_url': 'localhost',
- 'validation_name': 'bob',
- 'validation_key': v_path,
- 'validation_cert': v_cert
- },
- }
- cc_chef.handle('chef', cfg, self.fetch_cloud('ubuntu'), LOG, [])
- content = util.load_file(cc_chef.CHEF_RB_PATH)
- self.assertIn(v_path, content)
- util.load_file(v_path)
- self.assertEqual(v_cert, util.load_file(v_path))
-
- def test_validation_cert_with_system(self):
- # test validation_cert content is not written over system file
- tpl_file = util.load_file('templates/chef_client.rb.tmpl')
- self.patchUtils(self.tmp)
- self.patchOS(self.tmp)
-
- v_path = '/etc/chef/vkey.pem'
- v_cert = "system"
- expected_cert = "this is the system file certificate"
- cfg = {
- 'chef': {
- 'server_url': 'localhost',
- 'validation_name': 'bob',
- 'validation_key': v_path,
- 'validation_cert': v_cert
- },
- }
- util.write_file('/etc/cloud/templates/chef_client.rb.tmpl', tpl_file)
- util.write_file(v_path, expected_cert)
- cc_chef.handle('chef', cfg, self.fetch_cloud('ubuntu'), LOG, [])
- content = util.load_file(cc_chef.CHEF_RB_PATH)
- self.assertIn(v_path, content)
- util.load_file(v_path)
- self.assertEqual(expected_cert, util.load_file(v_path))
diff --git a/tests/unittests/test_handler/test_handler_debug.py b/tests/unittests/test_handler/test_handler_debug.py
deleted file mode 100644
index 80708d7b..00000000
--- a/tests/unittests/test_handler/test_handler_debug.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# vi: ts=4 expandtab
-#
-# Copyright (C) 2014 Yahoo! Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 3, as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-from cloudinit.config import cc_debug
-
-from cloudinit import cloud
-from cloudinit import distros
-from cloudinit import helpers
-from cloudinit import util
-
-from cloudinit.sources import DataSourceNone
-
-from .. import helpers as t_help
-
-import logging
-import shutil
-import tempfile
-
-LOG = logging.getLogger(__name__)
-
-
-class TestDebug(t_help.FilesystemMockingTestCase):
- def setUp(self):
- super(TestDebug, self).setUp()
- self.new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.new_root)
-
- def _get_cloud(self, distro, metadata=None):
- self.patchUtils(self.new_root)
- paths = helpers.Paths({})
- cls = distros.fetch(distro)
- d = cls(distro, {}, paths)
- ds = DataSourceNone.DataSourceNone({}, d, paths)
- if metadata:
- ds.metadata.update(metadata)
- return cloud.Cloud(ds, paths, {}, d, None)
-
- def test_debug_write(self):
- cfg = {
- 'abc': '123',
- 'c': u'\u20a0',
- 'debug': {
- 'verbose': True,
- # Does not actually write here due to mocking...
- 'output': '/var/log/cloud-init-debug.log',
- },
- }
- cc = self._get_cloud('ubuntu')
- cc_debug.handle('cc_debug', cfg, cc, LOG, [])
- contents = util.load_file('/var/log/cloud-init-debug.log')
- # Some basic sanity tests...
- self.assertNotEqual(0, len(contents))
- for k in cfg.keys():
- self.assertIn(k, contents)
-
- def test_debug_no_write(self):
- cfg = {
- 'abc': '123',
- 'debug': {
- 'verbose': False,
- # Does not actually write here due to mocking...
- 'output': '/var/log/cloud-init-debug.log',
- },
- }
- cc = self._get_cloud('ubuntu')
- cc_debug.handle('cc_debug', cfg, cc, LOG, [])
- self.assertRaises(IOError,
- util.load_file, '/var/log/cloud-init-debug.log')
diff --git a/tests/unittests/test_handler/test_handler_disk_setup.py b/tests/unittests/test_handler/test_handler_disk_setup.py
deleted file mode 100644
index ddef8d48..00000000
--- a/tests/unittests/test_handler/test_handler_disk_setup.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from cloudinit.config import cc_disk_setup
-from ..helpers import ExitStack, mock, TestCase
-
-
-class TestIsDiskUsed(TestCase):
-
- def setUp(self):
- super(TestIsDiskUsed, self).setUp()
- self.patches = ExitStack()
- mod_name = 'cloudinit.config.cc_disk_setup'
- self.enumerate_disk = self.patches.enter_context(
- mock.patch('{0}.enumerate_disk'.format(mod_name)))
- self.check_fs = self.patches.enter_context(
- mock.patch('{0}.check_fs'.format(mod_name)))
-
- def test_multiple_child_nodes_returns_true(self):
- self.enumerate_disk.return_value = (mock.MagicMock() for _ in range(2))
- self.check_fs.return_value = (mock.MagicMock(), None, mock.MagicMock())
- self.assertTrue(cc_disk_setup.is_disk_used(mock.MagicMock()))
-
- def test_valid_filesystem_returns_true(self):
- self.enumerate_disk.return_value = (mock.MagicMock() for _ in range(1))
- self.check_fs.return_value = (
- mock.MagicMock(), 'ext4', mock.MagicMock())
- self.assertTrue(cc_disk_setup.is_disk_used(mock.MagicMock()))
-
- def test_one_child_nodes_and_no_fs_returns_false(self):
- self.enumerate_disk.return_value = (mock.MagicMock() for _ in range(1))
- self.check_fs.return_value = (mock.MagicMock(), None, mock.MagicMock())
- self.assertFalse(cc_disk_setup.is_disk_used(mock.MagicMock()))
diff --git a/tests/unittests/test_handler/test_handler_growpart.py b/tests/unittests/test_handler/test_handler_growpart.py
deleted file mode 100644
index e653488a..00000000
--- a/tests/unittests/test_handler/test_handler_growpart.py
+++ /dev/null
@@ -1,220 +0,0 @@
-from cloudinit import cloud
-from cloudinit.config import cc_growpart
-from cloudinit import util
-
-from ..helpers import TestCase
-
-import errno
-import logging
-import os
-import re
-import unittest
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-try:
- from contextlib import ExitStack
-except ImportError:
- from contextlib2 import ExitStack
-
-# growpart:
-# mode: auto # off, on, auto, 'growpart'
-# devices: ['root']
-
-HELP_GROWPART_RESIZE = """
-growpart disk partition
- rewrite partition table so that partition takes up all the space it can
- options:
- -h | --help print Usage and exit
-<SNIP>
- -u | --update R update the the kernel partition table info after growing
- this requires kernel support and 'partx --update'
- R is one of:
- - 'auto' : [default] update partition if possible
-<SNIP>
- Example:
- - growpart /dev/sda 1
- Resize partition 1 on /dev/sda
-"""
-
-HELP_GROWPART_NO_RESIZE = """
-growpart disk partition
- rewrite partition table so that partition takes up all the space it can
- options:
- -h | --help print Usage and exit
-<SNIP>
- Example:
- - growpart /dev/sda 1
- Resize partition 1 on /dev/sda
-"""
-
-
-class TestDisabled(unittest.TestCase):
- def setUp(self):
- super(TestDisabled, self).setUp()
- self.name = "growpart"
- self.cloud_init = None
- self.log = logging.getLogger("TestDisabled")
- self.args = []
-
- self.handle = cc_growpart.handle
-
- def test_mode_off(self):
- # Test that nothing is done if mode is off.
-
- # this really only verifies that resizer_factory isn't called
- config = {'growpart': {'mode': 'off'}}
-
- with mock.patch.object(cc_growpart, 'resizer_factory') as mockobj:
- self.handle(self.name, config, self.cloud_init, self.log,
- self.args)
- self.assertEqual(mockobj.call_count, 0)
-
-
-class TestConfig(TestCase):
- def setUp(self):
- super(TestConfig, self).setUp()
- self.name = "growpart"
- self.paths = None
- self.cloud = cloud.Cloud(None, self.paths, None, None, None)
- self.log = logging.getLogger("TestConfig")
- self.args = []
- os.environ = {}
-
- self.cloud_init = None
- self.handle = cc_growpart.handle
-
- def test_no_resizers_auto_is_fine(self):
- with mock.patch.object(
- util, 'subp',
- return_value=(HELP_GROWPART_NO_RESIZE, "")) as mockobj:
-
- config = {'growpart': {'mode': 'auto'}}
- self.handle(self.name, config, self.cloud_init, self.log,
- self.args)
-
- mockobj.assert_called_once_with(
- ['growpart', '--help'], env={'LANG': 'C'})
-
- def test_no_resizers_mode_growpart_is_exception(self):
- with mock.patch.object(
- util, 'subp',
- return_value=(HELP_GROWPART_NO_RESIZE, "")) as mockobj:
- config = {'growpart': {'mode': "growpart"}}
- self.assertRaises(
- ValueError, self.handle, self.name, config,
- self.cloud_init, self.log, self.args)
-
- mockobj.assert_called_once_with(
- ['growpart', '--help'], env={'LANG': 'C'})
-
- def test_mode_auto_prefers_growpart(self):
- with mock.patch.object(
- util, 'subp',
- return_value=(HELP_GROWPART_RESIZE, "")) as mockobj:
- ret = cc_growpart.resizer_factory(mode="auto")
- self.assertIsInstance(ret, cc_growpart.ResizeGrowPart)
-
- mockobj.assert_called_once_with(
- ['growpart', '--help'], env={'LANG': 'C'})
-
- def test_handle_with_no_growpart_entry(self):
- # if no 'growpart' entry in config, then mode=auto should be used
-
- myresizer = object()
- retval = (("/", cc_growpart.RESIZE.CHANGED, "my-message",),)
-
- with ExitStack() as mocks:
- factory = mocks.enter_context(
- mock.patch.object(cc_growpart, 'resizer_factory',
- return_value=myresizer))
- rsdevs = mocks.enter_context(
- mock.patch.object(cc_growpart, 'resize_devices',
- return_value=retval))
- mocks.enter_context(
- mock.patch.object(cc_growpart, 'RESIZERS',
- (('mysizer', object),)
- ))
-
- self.handle(self.name, {}, self.cloud_init, self.log, self.args)
-
- factory.assert_called_once_with('auto')
- rsdevs.assert_called_once_with(myresizer, ['/'])
-
-
-class TestResize(unittest.TestCase):
- def setUp(self):
- super(TestResize, self).setUp()
- self.name = "growpart"
- self.log = logging.getLogger("TestResize")
-
- def test_simple_devices(self):
- # test simple device list
- # this patches out devent2dev, os.stat, and device_part_info
- # so in the end, doesn't test a lot
- devs = ["/dev/XXda1", "/dev/YYda2"]
- devstat_ret = Bunch(st_mode=25008, st_ino=6078, st_dev=5,
- st_nlink=1, st_uid=0, st_gid=6, st_size=0,
- st_atime=0, st_mtime=0, st_ctime=0)
- enoent = ["/dev/NOENT"]
- real_stat = os.stat
- resize_calls = []
-
- class myresizer(object):
- def resize(self, diskdev, partnum, partdev):
- resize_calls.append((diskdev, partnum, partdev))
- if partdev == "/dev/YYda2":
- return (1024, 2048)
- return (1024, 1024) # old size, new size
-
- def mystat(path):
- if path in devs:
- return devstat_ret
- if path in enoent:
- e = OSError("%s: does not exist" % path)
- e.errno = errno.ENOENT
- raise e
- return real_stat(path)
-
- try:
- opinfo = cc_growpart.device_part_info
- cc_growpart.device_part_info = simple_device_part_info
- os.stat = mystat
-
- resized = cc_growpart.resize_devices(myresizer(), devs + enoent)
-
- def find(name, res):
- for f in res:
- if f[0] == name:
- return f
- return None
-
- self.assertEqual(cc_growpart.RESIZE.NOCHANGE,
- find("/dev/XXda1", resized)[1])
- self.assertEqual(cc_growpart.RESIZE.CHANGED,
- find("/dev/YYda2", resized)[1])
- self.assertEqual(cc_growpart.RESIZE.SKIPPED,
- find(enoent[0], resized)[1])
- # self.assertEqual(resize_calls,
- # [("/dev/XXda", "1", "/dev/XXda1"),
- # ("/dev/YYda", "2", "/dev/YYda2")])
- finally:
- cc_growpart.device_part_info = opinfo
- os.stat = real_stat
-
-
-def simple_device_part_info(devpath):
- # simple stupid return (/dev/vda, 1) for /dev/vda
- ret = re.search("([^0-9]*)([0-9]*)$", devpath)
- x = (ret.group(1), ret.group(2))
- return x
-
-
-class Bunch(object):
- def __init__(self, **kwds):
- self.__dict__.update(kwds)
-
-
-# vi: ts=4 expandtab
diff --git a/tests/unittests/test_handler/test_handler_locale.py b/tests/unittests/test_handler/test_handler_locale.py
deleted file mode 100644
index c91908f4..00000000
--- a/tests/unittests/test_handler/test_handler_locale.py
+++ /dev/null
@@ -1,67 +0,0 @@
-# Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
-#
-# Author: Juerg Haefliger <juerg.haefliger@hp.com>
-#
-# Based on test_handler_set_hostname.py
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 3, as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-from cloudinit.config import cc_locale
-
-from cloudinit import cloud
-from cloudinit import distros
-from cloudinit import helpers
-from cloudinit import util
-
-from cloudinit.sources import DataSourceNoCloud
-
-from .. import helpers as t_help
-
-from configobj import ConfigObj
-
-from six import BytesIO
-
-import logging
-import shutil
-import tempfile
-
-LOG = logging.getLogger(__name__)
-
-
-class TestLocale(t_help.FilesystemMockingTestCase):
- def setUp(self):
- super(TestLocale, self).setUp()
- self.new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.new_root)
-
- def _get_cloud(self, distro):
- self.patchUtils(self.new_root)
- paths = helpers.Paths({})
-
- cls = distros.fetch(distro)
- d = cls(distro, {}, paths)
- ds = DataSourceNoCloud.DataSourceNoCloud({}, d, paths)
- cc = cloud.Cloud(ds, paths, {}, d, None)
- return cc
-
- def test_set_locale_sles(self):
-
- cfg = {
- 'locale': 'My.Locale',
- }
- cc = self._get_cloud('sles')
- cc_locale.handle('cc_locale', cfg, cc, LOG, [])
-
- contents = util.load_file('/etc/sysconfig/language', decode=False)
- n_cfg = ConfigObj(BytesIO(contents))
- self.assertEqual({'RC_LANG': cfg['locale']}, dict(n_cfg))
diff --git a/tests/unittests/test_handler/test_handler_lxd.py b/tests/unittests/test_handler/test_handler_lxd.py
deleted file mode 100644
index 6f90defb..00000000
--- a/tests/unittests/test_handler/test_handler_lxd.py
+++ /dev/null
@@ -1,134 +0,0 @@
-from cloudinit.config import cc_lxd
-from cloudinit.sources import DataSourceNoCloud
-from cloudinit import (distros, helpers, cloud)
-from .. import helpers as t_help
-
-import logging
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-
-LOG = logging.getLogger(__name__)
-
-
-class TestLxd(t_help.TestCase):
- lxd_cfg = {
- 'lxd': {
- 'init': {
- 'network_address': '0.0.0.0',
- 'storage_backend': 'zfs',
- 'storage_pool': 'poolname',
- }
- }
- }
-
- def setUp(self):
- super(TestLxd, self).setUp()
-
- def _get_cloud(self, distro):
- cls = distros.fetch(distro)
- paths = helpers.Paths({})
- d = cls(distro, {}, paths)
- ds = DataSourceNoCloud.DataSourceNoCloud({}, d, paths)
- cc = cloud.Cloud(ds, paths, {}, d, None)
- return cc
-
- @mock.patch("cloudinit.config.cc_lxd.util")
- def test_lxd_init(self, mock_util):
- cc = self._get_cloud('ubuntu')
- mock_util.which.return_value = True
- cc_lxd.handle('cc_lxd', self.lxd_cfg, cc, LOG, [])
- self.assertTrue(mock_util.which.called)
- init_call = mock_util.subp.call_args_list[0][0][0]
- self.assertEqual(init_call,
- ['lxd', 'init', '--auto',
- '--network-address=0.0.0.0',
- '--storage-backend=zfs',
- '--storage-pool=poolname'])
-
- @mock.patch("cloudinit.config.cc_lxd.util")
- def test_lxd_install(self, mock_util):
- cc = self._get_cloud('ubuntu')
- cc.distro = mock.MagicMock()
- mock_util.which.return_value = None
- cc_lxd.handle('cc_lxd', self.lxd_cfg, cc, LOG, [])
- self.assertTrue(cc.distro.install_packages.called)
- install_pkg = cc.distro.install_packages.call_args_list[0][0][0]
- self.assertEqual(sorted(install_pkg), ['lxd', 'zfs'])
-
- @mock.patch("cloudinit.config.cc_lxd.util")
- def test_no_init_does_nothing(self, mock_util):
- cc = self._get_cloud('ubuntu')
- cc.distro = mock.MagicMock()
- cc_lxd.handle('cc_lxd', {'lxd': {}}, cc, LOG, [])
- self.assertFalse(cc.distro.install_packages.called)
- self.assertFalse(mock_util.subp.called)
-
- @mock.patch("cloudinit.config.cc_lxd.util")
- def test_no_lxd_does_nothing(self, mock_util):
- cc = self._get_cloud('ubuntu')
- cc.distro = mock.MagicMock()
- cc_lxd.handle('cc_lxd', {'package_update': True}, cc, LOG, [])
- self.assertFalse(cc.distro.install_packages.called)
- self.assertFalse(mock_util.subp.called)
-
- def test_lxd_debconf_new_full(self):
- data = {"mode": "new",
- "name": "testbr0",
- "ipv4_address": "10.0.8.1",
- "ipv4_netmask": "24",
- "ipv4_dhcp_first": "10.0.8.2",
- "ipv4_dhcp_last": "10.0.8.254",
- "ipv4_dhcp_leases": "250",
- "ipv4_nat": "true",
- "ipv6_address": "fd98:9e0:3744::1",
- "ipv6_netmask": "64",
- "ipv6_nat": "true",
- "domain": "lxd"}
- self.assertEqual(
- cc_lxd.bridge_to_debconf(data),
- {"lxd/setup-bridge": "true",
- "lxd/bridge-name": "testbr0",
- "lxd/bridge-ipv4": "true",
- "lxd/bridge-ipv4-address": "10.0.8.1",
- "lxd/bridge-ipv4-netmask": "24",
- "lxd/bridge-ipv4-dhcp-first": "10.0.8.2",
- "lxd/bridge-ipv4-dhcp-last": "10.0.8.254",
- "lxd/bridge-ipv4-dhcp-leases": "250",
- "lxd/bridge-ipv4-nat": "true",
- "lxd/bridge-ipv6": "true",
- "lxd/bridge-ipv6-address": "fd98:9e0:3744::1",
- "lxd/bridge-ipv6-netmask": "64",
- "lxd/bridge-ipv6-nat": "true",
- "lxd/bridge-domain": "lxd"})
-
- def test_lxd_debconf_new_partial(self):
- data = {"mode": "new",
- "ipv6_address": "fd98:9e0:3744::1",
- "ipv6_netmask": "64",
- "ipv6_nat": "true"}
- self.assertEqual(
- cc_lxd.bridge_to_debconf(data),
- {"lxd/setup-bridge": "true",
- "lxd/bridge-ipv6": "true",
- "lxd/bridge-ipv6-address": "fd98:9e0:3744::1",
- "lxd/bridge-ipv6-netmask": "64",
- "lxd/bridge-ipv6-nat": "true"})
-
- def test_lxd_debconf_existing(self):
- data = {"mode": "existing",
- "name": "testbr0"}
- self.assertEqual(
- cc_lxd.bridge_to_debconf(data),
- {"lxd/setup-bridge": "false",
- "lxd/use-existing-bridge": "true",
- "lxd/bridge-name": "testbr0"})
-
- def test_lxd_debconf_none(self):
- data = {"mode": "none"}
- self.assertEqual(
- cc_lxd.bridge_to_debconf(data),
- {"lxd/setup-bridge": "false",
- "lxd/bridge-name": ""})
diff --git a/tests/unittests/test_handler/test_handler_mcollective.py b/tests/unittests/test_handler/test_handler_mcollective.py
deleted file mode 100644
index 6aefb93d..00000000
--- a/tests/unittests/test_handler/test_handler_mcollective.py
+++ /dev/null
@@ -1,148 +0,0 @@
-from cloudinit import (cloud, distros, helpers, util)
-from cloudinit.config import cc_mcollective
-from cloudinit.sources import DataSourceNoCloud
-
-from .. import helpers as t_help
-
-import configobj
-import logging
-import os
-import shutil
-from six import BytesIO
-import tempfile
-
-LOG = logging.getLogger(__name__)
-
-
-STOCK_CONFIG = """\
-main_collective = mcollective
-collectives = mcollective
-libdir = /usr/share/mcollective/plugins
-logfile = /var/log/mcollective.log
-loglevel = info
-daemonize = 1
-
-# Plugins
-securityprovider = psk
-plugin.psk = unset
-
-connector = activemq
-plugin.activemq.pool.size = 1
-plugin.activemq.pool.1.host = stomp1
-plugin.activemq.pool.1.port = 61613
-plugin.activemq.pool.1.user = mcollective
-plugin.activemq.pool.1.password = marionette
-
-# Facts
-factsource = yaml
-plugin.yaml = /etc/mcollective/facts.yaml
-"""
-
-
-class TestConfig(t_help.FilesystemMockingTestCase):
- def setUp(self):
- super(TestConfig, self).setUp()
- self.tmp = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp)
- # "./": make os.path.join behave correctly with abs path as second arg
- self.server_cfg = os.path.join(
- self.tmp, "./" + cc_mcollective.SERVER_CFG)
- self.pubcert_file = os.path.join(
- self.tmp, "./" + cc_mcollective.PUBCERT_FILE)
- self.pricert_file= os.path.join(
- self.tmp, self.tmp, "./" + cc_mcollective.PRICERT_FILE)
-
- def test_basic_config(self):
- cfg = {
- 'mcollective': {
- 'conf': {
- 'loglevel': 'debug',
- 'connector': 'rabbitmq',
- 'logfile': '/var/log/mcollective.log',
- 'ttl': '4294957',
- 'collectives': 'mcollective',
- 'main_collective': 'mcollective',
- 'securityprovider': 'psk',
- 'daemonize': '1',
- 'factsource': 'yaml',
- 'direct_addressing': '1',
- 'plugin.psk': 'unset',
- 'libdir': '/usr/share/mcollective/plugins',
- 'identity': '1',
- },
- },
- }
- expected = cfg['mcollective']['conf']
-
- self.patchUtils(self.tmp)
- cc_mcollective.configure(cfg['mcollective']['conf'])
- contents = util.load_file(cc_mcollective.SERVER_CFG, decode=False)
- contents = configobj.ConfigObj(BytesIO(contents))
- self.assertEqual(expected, dict(contents))
-
- def test_existing_config_is_saved(self):
- cfg = {'loglevel': 'warn'}
- util.write_file(self.server_cfg, STOCK_CONFIG)
- cc_mcollective.configure(config=cfg, server_cfg=self.server_cfg)
- self.assertTrue(os.path.exists(self.server_cfg))
- self.assertTrue(os.path.exists(self.server_cfg + ".old"))
- self.assertEqual(util.load_file(self.server_cfg + ".old"), STOCK_CONFIG)
-
- def test_existing_updated(self):
- cfg = {'loglevel': 'warn'}
- util.write_file(self.server_cfg, STOCK_CONFIG)
- cc_mcollective.configure(config=cfg, server_cfg=self.server_cfg)
- cfgobj = configobj.ConfigObj(self.server_cfg)
- self.assertEqual(cfg['loglevel'], cfgobj['loglevel'])
-
- def test_certificats_written(self):
- # check public-cert and private-cert keys in config get written
- cfg = {'loglevel': 'debug',
- 'public-cert': "this is my public-certificate",
- 'private-cert': "secret private certificate"}
-
- cc_mcollective.configure(config=cfg,
- server_cfg=self.server_cfg, pricert_file=self.pricert_file,
- pubcert_file=self.pubcert_file)
-
- found = configobj.ConfigObj(self.server_cfg)
-
- # make sure these didnt get written in
- self.assertFalse('public-cert' in found)
- self.assertFalse('private-cert' in found)
-
- # these need updating to the specified paths
- self.assertEqual(found['plugin.ssl_server_public'], self.pubcert_file)
- self.assertEqual(found['plugin.ssl_server_private'], self.pricert_file)
-
- # and the security provider should be ssl
- self.assertEqual(found['securityprovider'], 'ssl')
-
- self.assertEqual(
- util.load_file(self.pricert_file), cfg['private-cert'])
- self.assertEqual(
- util.load_file(self.pubcert_file), cfg['public-cert'])
-
-
-class TestHandler(t_help.TestCase):
- def _get_cloud(self, distro):
- cls = distros.fetch(distro)
- paths = helpers.Paths({})
- d = cls(distro, {}, paths)
- ds = DataSourceNoCloud.DataSourceNoCloud({}, d, paths)
- cc = cloud.Cloud(ds, paths, {}, d, None)
- return cc
-
- @t_help.mock.patch("cloudinit.config.cc_mcollective.util")
- def test_mcollective_install(self, mock_util):
- cc = self._get_cloud('ubuntu')
- cc.distro = t_help.mock.MagicMock()
- mycfg = {'mcollective': {'conf': {'loglevel': 'debug'}}}
- cc_mcollective.handle('cc_mcollective', mycfg, cc, LOG, [])
- self.assertTrue(cc.distro.install_packages.called)
- install_pkg = cc.distro.install_packages.call_args_list[0][0][0]
- self.assertEqual(install_pkg, ('mcollective',))
-
- self.assertTrue(mock_util.subp.called)
- self.assertEqual(mock_util.subp.call_args_list[0][0][0],
- ['service', 'mcollective', 'restart'])
diff --git a/tests/unittests/test_handler/test_handler_mounts.py b/tests/unittests/test_handler/test_handler_mounts.py
deleted file mode 100644
index 355674b2..00000000
--- a/tests/unittests/test_handler/test_handler_mounts.py
+++ /dev/null
@@ -1,133 +0,0 @@
-import os.path
-import shutil
-import tempfile
-
-from cloudinit.config import cc_mounts
-
-from .. import helpers as test_helpers
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-
-
-class TestSanitizeDevname(test_helpers.FilesystemMockingTestCase):
-
- def setUp(self):
- super(TestSanitizeDevname, self).setUp()
- self.new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.new_root)
- self.patchOS(self.new_root)
-
- def _touch(self, path):
- path = os.path.join(self.new_root, path.lstrip('/'))
- basedir = os.path.dirname(path)
- if not os.path.exists(basedir):
- os.makedirs(basedir)
- open(path, 'a').close()
-
- def _makedirs(self, directory):
- directory = os.path.join(self.new_root, directory.lstrip('/'))
- if not os.path.exists(directory):
- os.makedirs(directory)
-
- def mock_existence_of_disk(self, disk_path):
- self._touch(disk_path)
- self._makedirs(os.path.join('/sys/block', disk_path.split('/')[-1]))
-
- def mock_existence_of_partition(self, disk_path, partition_number):
- self.mock_existence_of_disk(disk_path)
- self._touch(disk_path + str(partition_number))
- disk_name = disk_path.split('/')[-1]
- self._makedirs(os.path.join('/sys/block',
- disk_name,
- disk_name + str(partition_number)))
-
- def test_existent_full_disk_path_is_returned(self):
- disk_path = '/dev/sda'
- self.mock_existence_of_disk(disk_path)
- self.assertEqual(disk_path,
- cc_mounts.sanitize_devname(disk_path,
- lambda x: None,
- mock.Mock()))
-
- def test_existent_disk_name_returns_full_path(self):
- disk_name = 'sda'
- disk_path = '/dev/' + disk_name
- self.mock_existence_of_disk(disk_path)
- self.assertEqual(disk_path,
- cc_mounts.sanitize_devname(disk_name,
- lambda x: None,
- mock.Mock()))
-
- def test_existent_meta_disk_is_returned(self):
- actual_disk_path = '/dev/sda'
- self.mock_existence_of_disk(actual_disk_path)
- self.assertEqual(
- actual_disk_path,
- cc_mounts.sanitize_devname('ephemeral0',
- lambda x: actual_disk_path,
- mock.Mock()))
-
- def test_existent_meta_partition_is_returned(self):
- disk_name, partition_part = '/dev/sda', '1'
- actual_partition_path = disk_name + partition_part
- self.mock_existence_of_partition(disk_name, partition_part)
- self.assertEqual(
- actual_partition_path,
- cc_mounts.sanitize_devname('ephemeral0.1',
- lambda x: disk_name,
- mock.Mock()))
-
- def test_existent_meta_partition_with_p_is_returned(self):
- disk_name, partition_part = '/dev/sda', 'p1'
- actual_partition_path = disk_name + partition_part
- self.mock_existence_of_partition(disk_name, partition_part)
- self.assertEqual(
- actual_partition_path,
- cc_mounts.sanitize_devname('ephemeral0.1',
- lambda x: disk_name,
- mock.Mock()))
-
- def test_first_partition_returned_if_existent_disk_is_partitioned(self):
- disk_name, partition_part = '/dev/sda', '1'
- actual_partition_path = disk_name + partition_part
- self.mock_existence_of_partition(disk_name, partition_part)
- self.assertEqual(
- actual_partition_path,
- cc_mounts.sanitize_devname('ephemeral0',
- lambda x: disk_name,
- mock.Mock()))
-
- def test_nth_partition_returned_if_requested(self):
- disk_name, partition_part = '/dev/sda', '3'
- actual_partition_path = disk_name + partition_part
- self.mock_existence_of_partition(disk_name, partition_part)
- self.assertEqual(
- actual_partition_path,
- cc_mounts.sanitize_devname('ephemeral0.3',
- lambda x: disk_name,
- mock.Mock()))
-
- def test_transformer_returning_none_returns_none(self):
- self.assertIsNone(
- cc_mounts.sanitize_devname(
- 'ephemeral0', lambda x: None, mock.Mock()))
-
- def test_missing_device_returns_none(self):
- self.assertIsNone(
- cc_mounts.sanitize_devname('/dev/sda', None, mock.Mock()))
-
- def test_missing_sys_returns_none(self):
- disk_path = '/dev/sda'
- self._makedirs(disk_path)
- self.assertIsNone(
- cc_mounts.sanitize_devname(disk_path, None, mock.Mock()))
-
- def test_existent_disk_but_missing_partition_returns_none(self):
- disk_path = '/dev/sda'
- self.mock_existence_of_disk(disk_path)
- self.assertIsNone(
- cc_mounts.sanitize_devname(
- 'ephemeral0.1', lambda x: disk_path, mock.Mock()))
diff --git a/tests/unittests/test_handler/test_handler_power_state.py b/tests/unittests/test_handler/test_handler_power_state.py
deleted file mode 100644
index feff319d..00000000
--- a/tests/unittests/test_handler/test_handler_power_state.py
+++ /dev/null
@@ -1,127 +0,0 @@
-import sys
-
-from cloudinit.config import cc_power_state_change as psc
-
-from .. import helpers as t_help
-from ..helpers import mock
-
-
-class TestLoadPowerState(t_help.TestCase):
- def setUp(self):
- super(self.__class__, self).setUp()
-
- def test_no_config(self):
- # completely empty config should mean do nothing
- (cmd, _timeout, _condition) = psc.load_power_state({})
- self.assertEqual(cmd, None)
-
- def test_irrelevant_config(self):
- # no power_state field in config should return None for cmd
- (cmd, _timeout, _condition) = psc.load_power_state({'foo': 'bar'})
- self.assertEqual(cmd, None)
-
- def test_invalid_mode(self):
- cfg = {'power_state': {'mode': 'gibberish'}}
- self.assertRaises(TypeError, psc.load_power_state, cfg)
-
- cfg = {'power_state': {'mode': ''}}
- self.assertRaises(TypeError, psc.load_power_state, cfg)
-
- def test_empty_mode(self):
- cfg = {'power_state': {'message': 'goodbye'}}
- self.assertRaises(TypeError, psc.load_power_state, cfg)
-
- def test_valid_modes(self):
- cfg = {'power_state': {}}
- for mode in ('halt', 'poweroff', 'reboot'):
- cfg['power_state']['mode'] = mode
- check_lps_ret(psc.load_power_state(cfg), mode=mode)
-
- def test_invalid_delay(self):
- cfg = {'power_state': {'mode': 'poweroff', 'delay': 'goodbye'}}
- self.assertRaises(TypeError, psc.load_power_state, cfg)
-
- def test_valid_delay(self):
- cfg = {'power_state': {'mode': 'poweroff', 'delay': ''}}
- for delay in ("now", "+1", "+30"):
- cfg['power_state']['delay'] = delay
- check_lps_ret(psc.load_power_state(cfg))
-
- def test_message_present(self):
- cfg = {'power_state': {'mode': 'poweroff', 'message': 'GOODBYE'}}
- ret = psc.load_power_state(cfg)
- check_lps_ret(psc.load_power_state(cfg))
- self.assertIn(cfg['power_state']['message'], ret[0])
-
- def test_no_message(self):
- # if message is not present, then no argument should be passed for it
- cfg = {'power_state': {'mode': 'poweroff'}}
- (cmd, _timeout, _condition) = psc.load_power_state(cfg)
- self.assertNotIn("", cmd)
- check_lps_ret(psc.load_power_state(cfg))
- self.assertTrue(len(cmd) == 3)
-
- def test_condition_null_raises(self):
- cfg = {'power_state': {'mode': 'poweroff', 'condition': None}}
- self.assertRaises(TypeError, psc.load_power_state, cfg)
-
- def test_condition_default_is_true(self):
- cfg = {'power_state': {'mode': 'poweroff'}}
- _cmd, _timeout, cond = psc.load_power_state(cfg)
- self.assertEqual(cond, True)
-
-
-class TestCheckCondition(t_help.TestCase):
- def cmd_with_exit(self, rc):
- return([sys.executable, '-c', 'import sys; sys.exit(%s)' % rc])
-
- def test_true_is_true(self):
- self.assertEqual(psc.check_condition(True), True)
-
- def test_false_is_false(self):
- self.assertEqual(psc.check_condition(False), False)
-
- def test_cmd_exit_zero_true(self):
- self.assertEqual(psc.check_condition(self.cmd_with_exit(0)), True)
-
- def test_cmd_exit_one_false(self):
- self.assertEqual(psc.check_condition(self.cmd_with_exit(1)), False)
-
- def test_cmd_exit_nonzero_warns(self):
- mocklog = mock.Mock()
- self.assertEqual(
- psc.check_condition(self.cmd_with_exit(2), mocklog), False)
- self.assertEqual(mocklog.warn.call_count, 1)
-
-
-def check_lps_ret(psc_return, mode=None):
- if len(psc_return) != 3:
- raise TypeError("length returned = %d" % len(psc_return))
-
- errs = []
- cmd = psc_return[0]
- timeout = psc_return[1]
- condition = psc_return[2]
-
- if 'shutdown' not in psc_return[0][0]:
- errs.append("string 'shutdown' not in cmd")
-
- if condition is None:
- errs.append("condition was not returned")
-
- if mode is not None:
- opt = {'halt': '-H', 'poweroff': '-P', 'reboot': '-r'}[mode]
- if opt not in psc_return[0]:
- errs.append("opt '%s' not in cmd: %s" % (opt, cmd))
-
- if len(cmd) != 3 and len(cmd) != 4:
- errs.append("Invalid command length: %s" % len(cmd))
-
- try:
- float(timeout)
- except Exception:
- errs.append("timeout failed convert to float")
-
- if len(errs):
- lines = ["Errors in result: %s" % str(psc_return)] + errs
- raise Exception('\n'.join(lines))
diff --git a/tests/unittests/test_handler/test_handler_rsyslog.py b/tests/unittests/test_handler/test_handler_rsyslog.py
deleted file mode 100644
index 38636063..00000000
--- a/tests/unittests/test_handler/test_handler_rsyslog.py
+++ /dev/null
@@ -1,174 +0,0 @@
-import os
-import shutil
-import tempfile
-
-from cloudinit.config.cc_rsyslog import (
- apply_rsyslog_changes, DEF_DIR, DEF_FILENAME, DEF_RELOAD, load_config,
- parse_remotes_line, remotes_to_rsyslog_cfg)
-from cloudinit import util
-
-from .. import helpers as t_help
-
-
-class TestLoadConfig(t_help.TestCase):
- def setUp(self):
- super(TestLoadConfig, self).setUp()
- self.basecfg = {
- 'config_filename': DEF_FILENAME,
- 'config_dir': DEF_DIR,
- 'service_reload_command': DEF_RELOAD,
- 'configs': [],
- 'remotes': {},
- }
-
- def test_legacy_full(self):
- found = load_config({
- 'rsyslog': ['*.* @192.168.1.1'],
- 'rsyslog_dir': "mydir",
- 'rsyslog_filename': "myfilename"})
- self.basecfg.update({
- 'configs': ['*.* @192.168.1.1'],
- 'config_dir': "mydir",
- 'config_filename': 'myfilename',
- 'service_reload_command': 'auto'}
- )
-
- self.assertEqual(found, self.basecfg)
-
- def test_legacy_defaults(self):
- found = load_config({
- 'rsyslog': ['*.* @192.168.1.1']})
- self.basecfg.update({
- 'configs': ['*.* @192.168.1.1']})
- self.assertEqual(found, self.basecfg)
-
- def test_new_defaults(self):
- self.assertEqual(load_config({}), self.basecfg)
-
- def test_new_configs(self):
- cfgs = ['*.* myhost', '*.* my2host']
- self.basecfg.update({'configs': cfgs})
- self.assertEqual(
- load_config({'rsyslog': {'configs': cfgs}}),
- self.basecfg)
-
-
-class TestApplyChanges(t_help.TestCase):
- def setUp(self):
- self.tmp = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp)
-
- def test_simple(self):
- cfgline = "*.* foohost"
- changed = apply_rsyslog_changes(
- configs=[cfgline], def_fname="foo.cfg", cfg_dir=self.tmp)
-
- fname = os.path.join(self.tmp, "foo.cfg")
- self.assertEqual([fname], changed)
- self.assertEqual(
- util.load_file(fname), cfgline + "\n")
-
- def test_multiple_files(self):
- configs = [
- '*.* foohost',
- {'content': 'abc', 'filename': 'my.cfg'},
- {'content': 'filefoo-content',
- 'filename': os.path.join(self.tmp, 'mydir/mycfg')},
- ]
-
- changed = apply_rsyslog_changes(
- configs=configs, def_fname="default.cfg", cfg_dir=self.tmp)
-
- expected = [
- (os.path.join(self.tmp, "default.cfg"),
- "*.* foohost\n"),
- (os.path.join(self.tmp, "my.cfg"), "abc\n"),
- (os.path.join(self.tmp, "mydir/mycfg"), "filefoo-content\n"),
- ]
- self.assertEqual([f[0] for f in expected], changed)
- actual = []
- for fname, _content in expected:
- util.load_file(fname)
- actual.append((fname, util.load_file(fname),))
- self.assertEqual(expected, actual)
-
- def test_repeat_def(self):
- configs = ['*.* foohost', "*.warn otherhost"]
-
- changed = apply_rsyslog_changes(
- configs=configs, def_fname="default.cfg", cfg_dir=self.tmp)
-
- fname = os.path.join(self.tmp, "default.cfg")
- self.assertEqual([fname], changed)
-
- expected_content = '\n'.join([c for c in configs]) + '\n'
- found_content = util.load_file(fname)
- self.assertEqual(expected_content, found_content)
-
- def test_multiline_content(self):
- configs = ['line1', 'line2\nline3\n']
-
- apply_rsyslog_changes(
- configs=configs, def_fname="default.cfg", cfg_dir=self.tmp)
-
- fname = os.path.join(self.tmp, "default.cfg")
- expected_content = '\n'.join([c for c in configs])
- found_content = util.load_file(fname)
- self.assertEqual(expected_content, found_content)
-
-
-class TestParseRemotesLine(t_help.TestCase):
- def test_valid_port(self):
- r = parse_remotes_line("foo:9")
- self.assertEqual(9, r.port)
-
- def test_invalid_port(self):
- with self.assertRaises(ValueError):
- parse_remotes_line("*.* foo:abc")
-
- def test_valid_ipv6(self):
- r = parse_remotes_line("*.* [::1]")
- self.assertEqual("*.* @[::1]", str(r))
-
- def test_valid_ipv6_with_port(self):
- r = parse_remotes_line("*.* [::1]:100")
- self.assertEqual(r.port, 100)
- self.assertEqual(r.addr, "::1")
- self.assertEqual("*.* @[::1]:100", str(r))
-
- def test_invalid_multiple_colon(self):
- with self.assertRaises(ValueError):
- parse_remotes_line("*.* ::1:100")
-
- def test_name_in_string(self):
- r = parse_remotes_line("syslog.host", name="foobar")
- self.assertEqual("*.* @syslog.host # foobar", str(r))
-
-
-class TestRemotesToSyslog(t_help.TestCase):
- def test_simple(self):
- # str rendered line must appear in remotes_to_ryslog_cfg return
- mycfg = "*.* myhost"
- myline = str(parse_remotes_line(mycfg, name="myname"))
- r = remotes_to_rsyslog_cfg({'myname': mycfg})
- lines = r.splitlines()
- self.assertEqual(1, len(lines))
- self.assertTrue(myline in r.splitlines())
-
- def test_header_footer(self):
- header = "#foo head"
- footer = "#foo foot"
- r = remotes_to_rsyslog_cfg(
- {'myname': "*.* myhost"}, header=header, footer=footer)
- lines = r.splitlines()
- self.assertTrue(header, lines[0])
- self.assertTrue(footer, lines[-1])
-
- def test_with_empty_or_null(self):
- mycfg = "*.* myhost"
- myline = str(parse_remotes_line(mycfg, name="myname"))
- r = remotes_to_rsyslog_cfg(
- {'myname': mycfg, 'removed': None, 'removed2': ""})
- lines = r.splitlines()
- self.assertEqual(1, len(lines))
- self.assertTrue(myline in r.splitlines())
diff --git a/tests/unittests/test_handler/test_handler_seed_random.py b/tests/unittests/test_handler/test_handler_seed_random.py
deleted file mode 100644
index a0390da9..00000000
--- a/tests/unittests/test_handler/test_handler_seed_random.py
+++ /dev/null
@@ -1,227 +0,0 @@
-# Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
-#
-# Author: Juerg Haefliger <juerg.haefliger@hp.com>
-#
-# Based on test_handler_set_hostname.py
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 3, as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-from cloudinit.config import cc_seed_random
-
-import gzip
-import tempfile
-
-from six import BytesIO
-
-from cloudinit import cloud
-from cloudinit import distros
-from cloudinit import helpers
-from cloudinit import util
-
-from cloudinit.sources import DataSourceNone
-
-from .. import helpers as t_help
-
-import logging
-
-LOG = logging.getLogger(__name__)
-
-
-class TestRandomSeed(t_help.TestCase):
- def setUp(self):
- super(TestRandomSeed, self).setUp()
- self._seed_file = tempfile.mktemp()
- self.unapply = []
-
- # by default 'which' has nothing in its path
- self.apply_patches([(util, 'which', self._which)])
- self.apply_patches([(util, 'subp', self._subp)])
- self.subp_called = []
- self.whichdata = {}
-
- def tearDown(self):
- apply_patches([i for i in reversed(self.unapply)])
- util.del_file(self._seed_file)
-
- def apply_patches(self, patches):
- ret = apply_patches(patches)
- self.unapply += ret
-
- def _which(self, program):
- return self.whichdata.get(program)
-
- def _subp(self, *args, **kwargs):
- # supports subp calling with cmd as args or kwargs
- if 'args' not in kwargs:
- kwargs['args'] = args[0]
- self.subp_called.append(kwargs)
- return
-
- def _compress(self, text):
- contents = BytesIO()
- gz_fh = gzip.GzipFile(mode='wb', fileobj=contents)
- gz_fh.write(text)
- gz_fh.close()
- return contents.getvalue()
-
- def _get_cloud(self, distro, metadata=None):
- paths = helpers.Paths({})
- cls = distros.fetch(distro)
- ubuntu_distro = cls(distro, {}, paths)
- ds = DataSourceNone.DataSourceNone({}, ubuntu_distro, paths)
- if metadata:
- ds.metadata = metadata
- return cloud.Cloud(ds, paths, {}, ubuntu_distro, None)
-
- def test_append_random(self):
- cfg = {
- 'random_seed': {
- 'file': self._seed_file,
- 'data': 'tiny-tim-was-here',
- }
- }
- cc_seed_random.handle('test', cfg, self._get_cloud('ubuntu'), LOG, [])
- contents = util.load_file(self._seed_file)
- self.assertEqual("tiny-tim-was-here", contents)
-
- def test_append_random_unknown_encoding(self):
- data = self._compress(b"tiny-toe")
- cfg = {
- 'random_seed': {
- 'file': self._seed_file,
- 'data': data,
- 'encoding': 'special_encoding',
- }
- }
- self.assertRaises(IOError, cc_seed_random.handle, 'test', cfg,
- self._get_cloud('ubuntu'), LOG, [])
-
- def test_append_random_gzip(self):
- data = self._compress(b"tiny-toe")
- cfg = {
- 'random_seed': {
- 'file': self._seed_file,
- 'data': data,
- 'encoding': 'gzip',
- }
- }
- cc_seed_random.handle('test', cfg, self._get_cloud('ubuntu'), LOG, [])
- contents = util.load_file(self._seed_file)
- self.assertEqual("tiny-toe", contents)
-
- def test_append_random_gz(self):
- data = self._compress(b"big-toe")
- cfg = {
- 'random_seed': {
- 'file': self._seed_file,
- 'data': data,
- 'encoding': 'gz',
- }
- }
- cc_seed_random.handle('test', cfg, self._get_cloud('ubuntu'), LOG, [])
- contents = util.load_file(self._seed_file)
- self.assertEqual("big-toe", contents)
-
- def test_append_random_base64(self):
- data = util.b64e('bubbles')
- cfg = {
- 'random_seed': {
- 'file': self._seed_file,
- 'data': data,
- 'encoding': 'base64',
- }
- }
- cc_seed_random.handle('test', cfg, self._get_cloud('ubuntu'), LOG, [])
- contents = util.load_file(self._seed_file)
- self.assertEqual("bubbles", contents)
-
- def test_append_random_b64(self):
- data = util.b64e('kit-kat')
- cfg = {
- 'random_seed': {
- 'file': self._seed_file,
- 'data': data,
- 'encoding': 'b64',
- }
- }
- cc_seed_random.handle('test', cfg, self._get_cloud('ubuntu'), LOG, [])
- contents = util.load_file(self._seed_file)
- self.assertEqual("kit-kat", contents)
-
- def test_append_random_metadata(self):
- cfg = {
- 'random_seed': {
- 'file': self._seed_file,
- 'data': 'tiny-tim-was-here',
- }
- }
- c = self._get_cloud('ubuntu', {'random_seed': '-so-was-josh'})
- cc_seed_random.handle('test', cfg, c, LOG, [])
- contents = util.load_file(self._seed_file)
- self.assertEqual('tiny-tim-was-here-so-was-josh', contents)
-
- def test_seed_command_provided_and_available(self):
- c = self._get_cloud('ubuntu', {})
- self.whichdata = {'pollinate': '/usr/bin/pollinate'}
- cfg = {'random_seed': {'command': ['pollinate', '-q']}}
- cc_seed_random.handle('test', cfg, c, LOG, [])
-
- subp_args = [f['args'] for f in self.subp_called]
- self.assertIn(['pollinate', '-q'], subp_args)
-
- def test_seed_command_not_provided(self):
- c = self._get_cloud('ubuntu', {})
- self.whichdata = {}
- cc_seed_random.handle('test', {}, c, LOG, [])
-
- # subp should not have been called as which would say not available
- self.assertFalse(self.subp_called)
-
- def test_unavailable_seed_command_and_required_raises_error(self):
- c = self._get_cloud('ubuntu', {})
- self.whichdata = {}
- cfg = {'random_seed': {'command': ['THIS_NO_COMMAND'],
- 'command_required': True}}
- self.assertRaises(ValueError, cc_seed_random.handle,
- 'test', cfg, c, LOG, [])
-
- def test_seed_command_and_required(self):
- c = self._get_cloud('ubuntu', {})
- self.whichdata = {'foo': 'foo'}
- cfg = {'random_seed': {'command_required': True, 'command': ['foo']}}
- cc_seed_random.handle('test', cfg, c, LOG, [])
-
- self.assertIn(['foo'], [f['args'] for f in self.subp_called])
-
- def test_file_in_environment_for_command(self):
- c = self._get_cloud('ubuntu', {})
- self.whichdata = {'foo': 'foo'}
- cfg = {'random_seed': {'command_required': True, 'command': ['foo'],
- 'file': self._seed_file}}
- cc_seed_random.handle('test', cfg, c, LOG, [])
-
- # this just instists that the first time subp was called,
- # RANDOM_SEED_FILE was in the environment set up correctly
- subp_env = [f['env'] for f in self.subp_called]
- self.assertEqual(subp_env[0].get('RANDOM_SEED_FILE'), self._seed_file)
-
-
-def apply_patches(patches):
- ret = []
- for (ref, name, replace) in patches:
- if replace is None:
- continue
- orig = getattr(ref, name)
- setattr(ref, name, replace)
- ret.append((ref, name, orig))
- return ret
diff --git a/tests/unittests/test_handler/test_handler_set_hostname.py b/tests/unittests/test_handler/test_handler_set_hostname.py
deleted file mode 100644
index 7effa124..00000000
--- a/tests/unittests/test_handler/test_handler_set_hostname.py
+++ /dev/null
@@ -1,72 +0,0 @@
-from cloudinit.config import cc_set_hostname
-
-from cloudinit import cloud
-from cloudinit import distros
-from cloudinit import helpers
-from cloudinit import util
-
-from .. import helpers as t_help
-
-from configobj import ConfigObj
-import logging
-import shutil
-from six import BytesIO
-import tempfile
-
-LOG = logging.getLogger(__name__)
-
-
-class TestHostname(t_help.FilesystemMockingTestCase):
- def setUp(self):
- super(TestHostname, self).setUp()
- self.tmp = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp)
-
- def _fetch_distro(self, kind):
- cls = distros.fetch(kind)
- paths = helpers.Paths({})
- return cls(kind, {}, paths)
-
- def test_write_hostname_rhel(self):
- cfg = {
- 'hostname': 'blah.blah.blah.yahoo.com',
- }
- distro = self._fetch_distro('rhel')
- paths = helpers.Paths({})
- ds = None
- cc = cloud.Cloud(ds, paths, {}, distro, None)
- self.patchUtils(self.tmp)
- cc_set_hostname.handle('cc_set_hostname',
- cfg, cc, LOG, [])
- if not distro.uses_systemd():
- contents = util.load_file("/etc/sysconfig/network", decode=False)
- n_cfg = ConfigObj(BytesIO(contents))
- self.assertEqual({'HOSTNAME': 'blah.blah.blah.yahoo.com'},
- dict(n_cfg))
-
- def test_write_hostname_debian(self):
- cfg = {
- 'hostname': 'blah.blah.blah.yahoo.com',
- }
- distro = self._fetch_distro('debian')
- paths = helpers.Paths({})
- ds = None
- cc = cloud.Cloud(ds, paths, {}, distro, None)
- self.patchUtils(self.tmp)
- cc_set_hostname.handle('cc_set_hostname',
- cfg, cc, LOG, [])
- contents = util.load_file("/etc/hostname")
- self.assertEqual('blah', contents.strip())
-
- def test_write_hostname_sles(self):
- cfg = {
- 'hostname': 'blah.blah.blah.suse.com',
- }
- distro = self._fetch_distro('sles')
- paths = helpers.Paths({})
- ds = None
- cc = cloud.Cloud(ds, paths, {}, distro, None)
- self.patchUtils(self.tmp)
- cc_set_hostname.handle('cc_set_hostname', cfg, cc, LOG, [])
- contents = util.load_file("/etc/HOSTNAME")
- self.assertEqual('blah', contents.strip())
diff --git a/tests/unittests/test_handler/test_handler_snappy.py b/tests/unittests/test_handler/test_handler_snappy.py
deleted file mode 100644
index 57dce1bc..00000000
--- a/tests/unittests/test_handler/test_handler_snappy.py
+++ /dev/null
@@ -1,306 +0,0 @@
-from cloudinit.config.cc_snappy import (
- makeop, get_package_ops, render_snap_op)
-from cloudinit import util
-
-from .. import helpers as t_help
-
-import os
-import shutil
-import tempfile
-import yaml
-
-ALLOWED = (dict, list, int, str)
-
-
-class TestInstallPackages(t_help.TestCase):
- def setUp(self):
- super(TestInstallPackages, self).setUp()
- self.unapply = []
-
- # by default 'which' has nothing in its path
- self.apply_patches([(util, 'subp', self._subp)])
- self.subp_called = []
- self.snapcmds = []
- self.tmp = tempfile.mkdtemp(prefix="TestInstallPackages")
-
- def tearDown(self):
- apply_patches([i for i in reversed(self.unapply)])
- shutil.rmtree(self.tmp)
-
- def apply_patches(self, patches):
- ret = apply_patches(patches)
- self.unapply += ret
-
- def populate_tmp(self, files):
- return t_help.populate_dir(self.tmp, files)
-
- def _subp(self, *args, **kwargs):
- # supports subp calling with cmd as args or kwargs
- if 'args' not in kwargs:
- kwargs['args'] = args[0]
- self.subp_called.append(kwargs)
- args = kwargs['args']
- # here we basically parse the snappy command invoked
- # and append to snapcmds a list of (mode, pkg, config)
- if args[0:2] == ['snappy', 'config']:
- if args[3] == "-":
- config = kwargs.get('data', '')
- else:
- with open(args[3], "rb") as fp:
- config = yaml.safe_load(fp.read())
- self.snapcmds.append(['config', args[2], config])
- elif args[0:2] == ['snappy', 'install']:
- config = None
- pkg = None
- for arg in args[2:]:
- if arg.startswith("-"):
- continue
- if not pkg:
- pkg = arg
- elif not config:
- cfgfile = arg
- if cfgfile == "-":
- config = kwargs.get('data', '')
- elif cfgfile:
- with open(cfgfile, "rb") as fp:
- config = yaml.safe_load(fp.read())
- self.snapcmds.append(['install', pkg, config])
-
- def test_package_ops_1(self):
- ret = get_package_ops(
- packages=['pkg1', 'pkg2', 'pkg3'],
- configs={'pkg2': b'mycfg2'}, installed=[])
- self.assertEqual(
- ret, [makeop('install', 'pkg1', None, None),
- makeop('install', 'pkg2', b'mycfg2', None),
- makeop('install', 'pkg3', None, None)])
-
- def test_package_ops_config_only(self):
- ret = get_package_ops(
- packages=None,
- configs={'pkg2': b'mycfg2'}, installed=['pkg1', 'pkg2'])
- self.assertEqual(
- ret, [makeop('config', 'pkg2', b'mycfg2')])
-
- def test_package_ops_install_and_config(self):
- ret = get_package_ops(
- packages=['pkg3', 'pkg2'],
- configs={'pkg2': b'mycfg2', 'xinstalled': b'xcfg'},
- installed=['xinstalled'])
- self.assertEqual(
- ret, [makeop('install', 'pkg3'),
- makeop('install', 'pkg2', b'mycfg2'),
- makeop('config', 'xinstalled', b'xcfg')])
-
- def test_package_ops_install_long_config_short(self):
- # a package can be installed by full name, but have config by short
- cfg = {'k1': 'k2'}
- ret = get_package_ops(
- packages=['config-example.canonical'],
- configs={'config-example': cfg}, installed=[])
- self.assertEqual(
- ret, [makeop('install', 'config-example.canonical', cfg)])
-
- def test_package_ops_with_file(self):
- self.populate_tmp(
- {"snapf1.snap": b"foo1", "snapf1.config": b"snapf1cfg",
- "snapf2.snap": b"foo2", "foo.bar": "ignored"})
- ret = get_package_ops(
- packages=['pkg1'], configs={}, installed=[], fspath=self.tmp)
- self.assertEqual(
- ret,
- [makeop_tmpd(self.tmp, 'install', 'snapf1', path="snapf1.snap",
- cfgfile="snapf1.config"),
- makeop_tmpd(self.tmp, 'install', 'snapf2', path="snapf2.snap"),
- makeop('install', 'pkg1')])
-
- def test_package_ops_common_filename(self):
- # fish package name from filename
- # package names likely look like: pkgname.namespace_version_arch.snap
-
- # find filenames
- self.populate_tmp(
- {"pkg-ws.smoser_0.3.4_all.snap": "pkg-ws-snapdata",
- "pkg-ws.config": "pkg-ws-config",
- "pkg1.smoser_1.2.3_all.snap": "pkg1.snapdata",
- "pkg1.smoser.config": "pkg1.smoser.config-data",
- "pkg1.config": "pkg1.config-data",
- "pkg2.smoser_0.0_amd64.snap": "pkg2-snapdata",
- "pkg2.smoser_0.0_amd64.config": "pkg2.config"})
-
- ret = get_package_ops(
- packages=[], configs={}, installed=[], fspath=self.tmp)
- self.assertEqual(
- ret,
- [makeop_tmpd(self.tmp, 'install', 'pkg-ws.smoser',
- path="pkg-ws.smoser_0.3.4_all.snap",
- cfgfile="pkg-ws.config"),
- makeop_tmpd(self.tmp, 'install', 'pkg1.smoser',
- path="pkg1.smoser_1.2.3_all.snap",
- cfgfile="pkg1.smoser.config"),
- makeop_tmpd(self.tmp, 'install', 'pkg2.smoser',
- path="pkg2.smoser_0.0_amd64.snap",
- cfgfile="pkg2.smoser_0.0_amd64.config"),
- ])
-
- def test_package_ops_config_overrides_file(self):
- # config data overrides local file .config
- self.populate_tmp(
- {"snapf1.snap": b"foo1", "snapf1.config": b"snapf1cfg"})
- ret = get_package_ops(
- packages=[], configs={'snapf1': 'snapf1cfg-config'},
- installed=[], fspath=self.tmp)
- self.assertEqual(
- ret, [makeop_tmpd(self.tmp, 'install', 'snapf1',
- path="snapf1.snap", config="snapf1cfg-config")])
-
- def test_package_ops_namespacing(self):
- cfgs = {
- 'config-example': {'k1': 'v1'},
- 'pkg1': {'p1': 'p2'},
- 'ubuntu-core': {'c1': 'c2'},
- 'notinstalled.smoser': {'s1': 's2'},
- }
- ret = get_package_ops(
- packages=['config-example.canonical'], configs=cfgs,
- installed=['config-example.smoser', 'pkg1.canonical',
- 'ubuntu-core'])
-
- expected_configs = [
- makeop('config', 'pkg1', config=cfgs['pkg1']),
- makeop('config', 'ubuntu-core', config=cfgs['ubuntu-core'])]
- expected_installs = [
- makeop('install', 'config-example.canonical',
- config=cfgs['config-example'])]
-
- installs = [i for i in ret if i['op'] == 'install']
- configs = [c for c in ret if c['op'] == 'config']
-
- self.assertEqual(installs, expected_installs)
- # configs are not ordered
- self.assertEqual(len(configs), len(expected_configs))
- self.assertTrue(all(found in expected_configs for found in configs))
-
- def test_render_op_localsnap(self):
- self.populate_tmp({"snapf1.snap": b"foo1"})
- op = makeop_tmpd(self.tmp, 'install', 'snapf1',
- path='snapf1.snap')
- render_snap_op(**op)
- self.assertEqual(
- self.snapcmds, [['install', op['path'], None]])
-
- def test_render_op_localsnap_localconfig(self):
- self.populate_tmp(
- {"snapf1.snap": b"foo1", 'snapf1.config': b'snapf1cfg'})
- op = makeop_tmpd(self.tmp, 'install', 'snapf1',
- path='snapf1.snap', cfgfile='snapf1.config')
- render_snap_op(**op)
- self.assertEqual(
- self.snapcmds, [['install', op['path'], 'snapf1cfg']])
-
- def test_render_op_snap(self):
- op = makeop('install', 'snapf1')
- render_snap_op(**op)
- self.assertEqual(
- self.snapcmds, [['install', 'snapf1', None]])
-
- def test_render_op_snap_config(self):
- mycfg = {'key1': 'value1'}
- name = "snapf1"
- op = makeop('install', name, config=mycfg)
- render_snap_op(**op)
- self.assertEqual(
- self.snapcmds, [['install', name, {'config': {name: mycfg}}]])
-
- def test_render_op_config_bytes(self):
- name = "snapf1"
- mycfg = b'myconfig'
- op = makeop('config', name, config=mycfg)
- render_snap_op(**op)
- self.assertEqual(
- self.snapcmds, [['config', 'snapf1', {'config': {name: mycfg}}]])
-
- def test_render_op_config_string(self):
- name = 'snapf1'
- mycfg = 'myconfig: foo\nhisconfig: bar\n'
- op = makeop('config', name, config=mycfg)
- render_snap_op(**op)
- self.assertEqual(
- self.snapcmds, [['config', 'snapf1', {'config': {name: mycfg}}]])
-
- def test_render_op_config_dict(self):
- # config entry for package can be a dict, not a string blob
- mycfg = {'foo': 'bar'}
- name = 'snapf1'
- op = makeop('config', name, config=mycfg)
- render_snap_op(**op)
- # snapcmds is a list of 3-entry lists. data_found will be the
- # blob of data in the file in 'snappy install --config=<file>'
- data_found = self.snapcmds[0][2]
- self.assertEqual(mycfg, data_found['config'][name])
-
- def test_render_op_config_list(self):
- # config entry for package can be a list, not a string blob
- mycfg = ['foo', 'bar', 'wark', {'f1': 'b1'}]
- name = "snapf1"
- op = makeop('config', name, config=mycfg)
- render_snap_op(**op)
- data_found = self.snapcmds[0][2]
- self.assertEqual(mycfg, data_found['config'][name])
-
- def test_render_op_config_int(self):
- # config entry for package can be a list, not a string blob
- mycfg = 1
- name = 'snapf1'
- op = makeop('config', name, config=mycfg)
- render_snap_op(**op)
- data_found = self.snapcmds[0][2]
- self.assertEqual(mycfg, data_found['config'][name])
-
- def test_render_long_configs_short(self):
- # install a namespaced package should have un-namespaced config
- mycfg = {'k1': 'k2'}
- name = 'snapf1'
- op = makeop('install', name + ".smoser", config=mycfg)
- render_snap_op(**op)
- data_found = self.snapcmds[0][2]
- self.assertEqual(mycfg, data_found['config'][name])
-
- def test_render_does_not_pad_cfgfile(self):
- # package_ops with cfgfile should not modify --file= content.
- mydata = "foo1: bar1\nk: [l1, l2, l3]\n"
- self.populate_tmp(
- {"snapf1.snap": b"foo1", "snapf1.config": mydata.encode()})
- ret = get_package_ops(
- packages=[], configs={}, installed=[], fspath=self.tmp)
- self.assertEqual(
- ret,
- [makeop_tmpd(self.tmp, 'install', 'snapf1', path="snapf1.snap",
- cfgfile="snapf1.config")])
-
- # now the op was ok, but test that render didn't mess it up.
- render_snap_op(**ret[0])
- data_found = self.snapcmds[0][2]
- # the data found gets loaded in the snapcmd interpretation
- # so this comparison is a bit lossy, but input to snappy config
- # is expected to be yaml loadable, so it should be OK.
- self.assertEqual(yaml.safe_load(mydata), data_found)
-
-
-def makeop_tmpd(tmpd, op, name, config=None, path=None, cfgfile=None):
- if cfgfile:
- cfgfile = os.path.sep.join([tmpd, cfgfile])
- if path:
- path = os.path.sep.join([tmpd, path])
- return(makeop(op=op, name=name, config=config, path=path, cfgfile=cfgfile))
-
-
-def apply_patches(patches):
- ret = []
- for (ref, name, replace) in patches:
- if replace is None:
- continue
- orig = getattr(ref, name)
- setattr(ref, name, replace)
- ret.append((ref, name, orig))
- return ret
diff --git a/tests/unittests/test_handler/test_handler_timezone.py b/tests/unittests/test_handler/test_handler_timezone.py
deleted file mode 100644
index b7e6b03d..00000000
--- a/tests/unittests/test_handler/test_handler_timezone.py
+++ /dev/null
@@ -1,76 +0,0 @@
-# Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
-#
-# Author: Juerg Haefliger <juerg.haefliger@hp.com>
-#
-# Based on test_handler_set_hostname.py
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 3, as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-from cloudinit.config import cc_timezone
-
-from cloudinit import cloud
-from cloudinit import distros
-from cloudinit import helpers
-from cloudinit import util
-
-from cloudinit.sources import DataSourceNoCloud
-
-from .. import helpers as t_help
-
-from configobj import ConfigObj
-import logging
-import shutil
-from six import BytesIO
-import tempfile
-
-LOG = logging.getLogger(__name__)
-
-
-class TestTimezone(t_help.FilesystemMockingTestCase):
- def setUp(self):
- super(TestTimezone, self).setUp()
- self.new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.new_root)
-
- def _get_cloud(self, distro):
- self.patchUtils(self.new_root)
- self.patchOS(self.new_root)
-
- paths = helpers.Paths({})
-
- cls = distros.fetch(distro)
- d = cls(distro, {}, paths)
- ds = DataSourceNoCloud.DataSourceNoCloud({}, d, paths)
- cc = cloud.Cloud(ds, paths, {}, d, None)
- return cc
-
- def test_set_timezone_sles(self):
-
- cfg = {
- 'timezone': 'Tatooine/Bestine',
- }
- cc = self._get_cloud('sles')
-
- # Create a dummy timezone file
- dummy_contents = '0123456789abcdefgh'
- util.write_file('/usr/share/zoneinfo/%s' % cfg['timezone'],
- dummy_contents)
-
- cc_timezone.handle('cc_timezone', cfg, cc, LOG, [])
-
- contents = util.load_file('/etc/sysconfig/clock', decode=False)
- n_cfg = ConfigObj(BytesIO(contents))
- self.assertEqual({'TIMEZONE': cfg['timezone']}, dict(n_cfg))
-
- contents = util.load_file('/etc/localtime')
- self.assertEqual(dummy_contents, contents.strip())
diff --git a/tests/unittests/test_handler/test_handler_write_files.py b/tests/unittests/test_handler/test_handler_write_files.py
deleted file mode 100644
index 466e45f8..00000000
--- a/tests/unittests/test_handler/test_handler_write_files.py
+++ /dev/null
@@ -1,112 +0,0 @@
-from cloudinit.config.cc_write_files import write_files
-from cloudinit import log as logging
-from cloudinit import util
-
-from ..helpers import FilesystemMockingTestCase
-
-import base64
-import gzip
-import shutil
-import six
-import tempfile
-
-LOG = logging.getLogger(__name__)
-
-YAML_TEXT = """
-write_files:
- - encoding: gzip
- content: !!binary |
- H4sIAIDb/U8C/1NW1E/KzNMvzuBKTc7IV8hIzcnJVyjPL8pJ4QIA6N+MVxsAAAA=
- path: /usr/bin/hello
- permissions: '0755'
- - content: !!binary |
- Zm9vYmFyCg==
- path: /wark
- permissions: '0755'
- - content: |
- hi mom line 1
- hi mom line 2
- path: /tmp/message
-"""
-
-YAML_CONTENT_EXPECTED = {
- '/usr/bin/hello': "#!/bin/sh\necho hello world\n",
- '/wark': "foobar\n",
- '/tmp/message': "hi mom line 1\nhi mom line 2\n",
-}
-
-
-class TestWriteFiles(FilesystemMockingTestCase):
- def setUp(self):
- super(TestWriteFiles, self).setUp()
- self.tmp = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp)
-
- def test_simple(self):
- self.patchUtils(self.tmp)
- expected = "hello world\n"
- filename = "/tmp/my.file"
- write_files(
- "test_simple", [{"content": expected, "path": filename}], LOG)
- self.assertEqual(util.load_file(filename), expected)
-
- def test_yaml_binary(self):
- self.patchUtils(self.tmp)
- data = util.load_yaml(YAML_TEXT)
- write_files("testname", data['write_files'], LOG)
- for path, content in YAML_CONTENT_EXPECTED.items():
- self.assertEqual(util.load_file(path), content)
-
- def test_all_decodings(self):
- self.patchUtils(self.tmp)
-
- # build a 'files' array that has a dictionary of encodings
- # for 'gz', 'gzip', 'gz+base64' ...
- data = b"foobzr"
- utf8_valid = b"foobzr"
- utf8_invalid = b'ab\xaadef'
- files = []
- expected = []
-
- gz_aliases = ('gz', 'gzip')
- gz_b64_aliases = ('gz+base64', 'gzip+base64', 'gz+b64', 'gzip+b64')
- b64_aliases = ('base64', 'b64')
-
- datum = (("utf8", utf8_valid), ("no-utf8", utf8_invalid))
- for name, data in datum:
- gz = (_gzip_bytes(data), gz_aliases)
- gz_b64 = (base64.b64encode(_gzip_bytes(data)), gz_b64_aliases)
- b64 = (base64.b64encode(data), b64_aliases)
- for content, aliases in (gz, gz_b64, b64):
- for enc in aliases:
- cur = {'content': content,
- 'path': '/tmp/file-%s-%s' % (name, enc),
- 'encoding': enc}
- files.append(cur)
- expected.append((cur['path'], data))
-
- write_files("test_decoding", files, LOG)
-
- for path, content in expected:
- self.assertEqual(util.load_file(path, decode=False), content)
-
- # make sure we actually wrote *some* files.
- flen_expected = (
- len(gz_aliases + gz_b64_aliases + b64_aliases) * len(datum))
- self.assertEqual(len(expected), flen_expected)
-
-
-def _gzip_bytes(data):
- buf = six.BytesIO()
- fp = None
- try:
- fp = gzip.GzipFile(fileobj=buf, mode="wb")
- fp.write(data)
- fp.close()
- return buf.getvalue()
- finally:
- if fp:
- fp.close()
-
-
-# vi: ts=4 expandtab
diff --git a/tests/unittests/test_handler/test_handler_yum_add_repo.py b/tests/unittests/test_handler/test_handler_yum_add_repo.py
deleted file mode 100644
index 28b060f8..00000000
--- a/tests/unittests/test_handler/test_handler_yum_add_repo.py
+++ /dev/null
@@ -1,68 +0,0 @@
-from cloudinit.config import cc_yum_add_repo
-from cloudinit import util
-
-from .. import helpers
-
-import configobj
-import logging
-import shutil
-from six import BytesIO
-import tempfile
-
-LOG = logging.getLogger(__name__)
-
-
-class TestConfig(helpers.FilesystemMockingTestCase):
- def setUp(self):
- super(TestConfig, self).setUp()
- self.tmp = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp)
-
- def test_bad_config(self):
- cfg = {
- 'yum_repos': {
- 'epel-testing': {
- 'name': 'Extra Packages for Enterprise Linux 5 - Testing',
- # Missing this should cause the repo not to be written
- # 'baseurl': 'http://blah.org/pub/epel/testing/5/$barch',
- 'enabled': False,
- 'gpgcheck': True,
- 'gpgkey': 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL',
- 'failovermethod': 'priority',
- },
- },
- }
- self.patchUtils(self.tmp)
- cc_yum_add_repo.handle('yum_add_repo', cfg, None, LOG, [])
- self.assertRaises(IOError, util.load_file,
- "/etc/yum.repos.d/epel_testing.repo")
-
- def test_write_config(self):
- cfg = {
- 'yum_repos': {
- 'epel-testing': {
- 'name': 'Extra Packages for Enterprise Linux 5 - Testing',
- 'baseurl': 'http://blah.org/pub/epel/testing/5/$basearch',
- 'enabled': False,
- 'gpgcheck': True,
- 'gpgkey': 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL',
- 'failovermethod': 'priority',
- },
- },
- }
- self.patchUtils(self.tmp)
- cc_yum_add_repo.handle('yum_add_repo', cfg, None, LOG, [])
- contents = util.load_file("/etc/yum.repos.d/epel_testing.repo",
- decode=False)
- contents = configobj.ConfigObj(BytesIO(contents))
- expected = {
- 'epel_testing': {
- 'name': 'Extra Packages for Enterprise Linux 5 - Testing',
- 'failovermethod': 'priority',
- 'gpgkey': 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL',
- 'enabled': '0',
- 'baseurl': 'http://blah.org/pub/epel/testing/5/$basearch',
- 'gpgcheck': '1',
- }
- }
- self.assertEqual(expected, dict(contents))
diff --git a/tests/unittests/test_helpers.py b/tests/unittests/test_helpers.py
deleted file mode 100644
index 943a5723..00000000
--- a/tests/unittests/test_helpers.py
+++ /dev/null
@@ -1,33 +0,0 @@
-"""Tests of the built-in user data handlers."""
-
-import os
-
-from . import helpers as test_helpers
-
-from cloudinit import sources
-
-
-class MyDataSource(sources.DataSource):
- _instance_id = None
-
- def get_instance_id(self):
- return self._instance_id
-
-
-class TestPaths(test_helpers.ResourceUsingTestCase):
- def test_get_ipath_and_instance_id_with_slashes(self):
- myds = MyDataSource(sys_cfg={}, distro=None, paths={})
- myds._instance_id = "/foo/bar"
- safe_iid = "_foo_bar"
- mypaths = self.getCloudPaths(myds)
-
- self.assertEqual(
- os.path.join(mypaths.cloud_dir, 'instances', safe_iid),
- mypaths.get_ipath())
-
- def test_get_ipath_and_empty_instance_id_returns_none(self):
- myds = MyDataSource(sys_cfg={}, distro=None, paths={})
- myds._instance_id = None
- mypaths = self.getCloudPaths(myds)
-
- self.assertEqual(None, mypaths.get_ipath())
diff --git a/tests/unittests/test_merging.py b/tests/unittests/test_merging.py
deleted file mode 100644
index a33ec184..00000000
--- a/tests/unittests/test_merging.py
+++ /dev/null
@@ -1,257 +0,0 @@
-from . import helpers
-
-from cloudinit.handlers import cloud_config
-from cloudinit.handlers import (CONTENT_START, CONTENT_END)
-
-from cloudinit import helpers as c_helpers
-from cloudinit import util
-
-import collections
-import glob
-import os
-import random
-import re
-import six
-import string
-
-SOURCE_PAT = "source*.*yaml"
-EXPECTED_PAT = "expected%s.yaml"
-TYPES = [dict, str, list, tuple, None]
-TYPES.extend(six.integer_types)
-
-
-def _old_mergedict(src, cand):
- """
- Merge values from C{cand} into C{src}.
- If C{src} has a key C{cand} will not override.
- Nested dictionaries are merged recursively.
- """
- if isinstance(src, dict) and isinstance(cand, dict):
- for (k, v) in cand.items():
- if k not in src:
- src[k] = v
- else:
- src[k] = _old_mergedict(src[k], v)
- return src
-
-
-def _old_mergemanydict(*args):
- out = {}
- for a in args:
- out = _old_mergedict(out, a)
- return out
-
-
-def _random_str(rand):
- base = ''
- for _i in range(rand.randint(1, 2 ** 8)):
- base += rand.choice(string.ascii_letters + string.digits)
- return base
-
-
-class _NoMoreException(Exception):
- pass
-
-
-def _make_dict(current_depth, max_depth, rand):
- if current_depth >= max_depth:
- raise _NoMoreException()
- if current_depth == 0:
- t = dict
- else:
- t = rand.choice(TYPES)
- base = None
- if t in [None]:
- return base
- if t in [dict, list, tuple]:
- if t in [dict]:
- amount = rand.randint(0, 5)
- keys = [_random_str(rand) for _i in range(0, amount)]
- base = {}
- for k in keys:
- try:
- base[k] = _make_dict(current_depth + 1, max_depth, rand)
- except _NoMoreException:
- pass
- elif t in [list, tuple]:
- base = []
- amount = rand.randint(0, 5)
- for _i in range(0, amount):
- try:
- base.append(_make_dict(current_depth + 1, max_depth, rand))
- except _NoMoreException:
- pass
- if t in [tuple]:
- base = tuple(base)
- elif t in six.integer_types:
- base = rand.randint(0, 2 ** 8)
- elif t in [str]:
- base = _random_str(rand)
- return base
-
-
-def make_dict(max_depth, seed=None):
- max_depth = max(1, max_depth)
- rand = random.Random(seed)
- return _make_dict(0, max_depth, rand)
-
-
-class TestSimpleRun(helpers.ResourceUsingTestCase):
- def _load_merge_files(self):
- merge_root = self.resourceLocation('merge_sources')
- tests = []
- source_ids = collections.defaultdict(list)
- expected_files = {}
- for fn in glob.glob(os.path.join(merge_root, SOURCE_PAT)):
- base_fn = os.path.basename(fn)
- file_id = re.match(r"source(\d+)\-(\d+)[.]yaml", base_fn)
- if not file_id:
- raise IOError("File %s does not have a numeric identifier"
- % (fn))
- file_id = int(file_id.group(1))
- source_ids[file_id].append(fn)
- expected_fn = os.path.join(merge_root, EXPECTED_PAT % (file_id))
- if not os.path.isfile(expected_fn):
- raise IOError("No expected file found at %s" % (expected_fn))
- expected_files[file_id] = expected_fn
- for i in sorted(source_ids.keys()):
- source_file_contents = []
- for fn in sorted(source_ids[i]):
- source_file_contents.append([fn, util.load_file(fn)])
- expected = util.load_yaml(util.load_file(expected_files[i]))
- entry = [source_file_contents, [expected, expected_files[i]]]
- tests.append(entry)
- return tests
-
- def test_seed_runs(self):
- test_dicts = []
- for i in range(1, 10):
- base_dicts = []
- for j in range(1, 10):
- base_dicts.append(make_dict(5, i * j))
- test_dicts.append(base_dicts)
- for test in test_dicts:
- c = _old_mergemanydict(*test)
- d = util.mergemanydict(test)
- self.assertEqual(c, d)
-
- def test_merge_cc_samples(self):
- tests = self._load_merge_files()
- paths = c_helpers.Paths({})
- cc_handler = cloud_config.CloudConfigPartHandler(paths)
- cc_handler.cloud_fn = None
- for (payloads, (expected_merge, expected_fn)) in tests:
- cc_handler.handle_part(None, CONTENT_START, None,
- None, None, None)
- merging_fns = []
- for (fn, contents) in payloads:
- cc_handler.handle_part(None, None, "%s.yaml" % (fn),
- contents, None, {})
- merging_fns.append(fn)
- merged_buf = cc_handler.cloud_buf
- cc_handler.handle_part(None, CONTENT_END, None,
- None, None, None)
- fail_msg = "Equality failure on checking %s with %s: %s != %s"
- fail_msg = fail_msg % (expected_fn,
- ",".join(merging_fns), merged_buf,
- expected_merge)
- self.assertEqual(expected_merge, merged_buf, msg=fail_msg)
-
- def test_compat_merges_dict(self):
- a = {
- '1': '2',
- 'b': 'c',
- }
- b = {
- 'b': 'e',
- }
- c = _old_mergedict(a, b)
- d = util.mergemanydict([a, b])
- self.assertEqual(c, d)
-
- def test_compat_merges_dict2(self):
- a = {
- 'Blah': 1,
- 'Blah2': 2,
- 'Blah3': 3,
- }
- b = {
- 'Blah': 1,
- 'Blah2': 2,
- 'Blah3': [1],
- }
- c = _old_mergedict(a, b)
- d = util.mergemanydict([a, b])
- self.assertEqual(c, d)
-
- def test_compat_merges_list(self):
- a = {'b': [1, 2, 3]}
- b = {'b': [4, 5]}
- c = {'b': [6, 7]}
- e = _old_mergemanydict(a, b, c)
- f = util.mergemanydict([a, b, c])
- self.assertEqual(e, f)
-
- def test_compat_merges_str(self):
- a = {'b': "hi"}
- b = {'b': "howdy"}
- c = {'b': "hallo"}
- e = _old_mergemanydict(a, b, c)
- f = util.mergemanydict([a, b, c])
- self.assertEqual(e, f)
-
- def test_compat_merge_sub_dict(self):
- a = {
- '1': '2',
- 'b': {
- 'f': 'g',
- 'e': 'c',
- 'h': 'd',
- 'hh': {
- '1': 2,
- },
- }
- }
- b = {
- 'b': {
- 'e': 'c',
- 'hh': {
- '3': 4,
- }
- }
- }
- c = _old_mergedict(a, b)
- d = util.mergemanydict([a, b])
- self.assertEqual(c, d)
-
- def test_compat_merge_sub_dict2(self):
- a = {
- '1': '2',
- 'b': {
- 'f': 'g',
- }
- }
- b = {
- 'b': {
- 'e': 'c',
- }
- }
- c = _old_mergedict(a, b)
- d = util.mergemanydict([a, b])
- self.assertEqual(c, d)
-
- def test_compat_merge_sub_list(self):
- a = {
- '1': '2',
- 'b': {
- 'f': ['1'],
- }
- }
- b = {
- 'b': {
- 'f': [],
- }
- }
- c = _old_mergedict(a, b)
- d = util.mergemanydict([a, b])
- self.assertEqual(c, d)
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
deleted file mode 100644
index 41b9a6d0..00000000
--- a/tests/unittests/test_net.py
+++ /dev/null
@@ -1,689 +0,0 @@
-from cloudinit import net
-from cloudinit.net import cmdline
-from cloudinit.net import eni
-from cloudinit.net import network_state
-from cloudinit.net import sysconfig
-from cloudinit.sources.helpers import openstack
-from cloudinit import util
-
-from .helpers import dir2dict
-from .helpers import mock
-from .helpers import TestCase
-
-import base64
-import copy
-import gzip
-import io
-import json
-import os
-import shutil
-import tempfile
-import textwrap
-import yaml
-
-DHCP_CONTENT_1 = """
-DEVICE='eth0'
-PROTO='dhcp'
-IPV4ADDR='192.168.122.89'
-IPV4BROADCAST='192.168.122.255'
-IPV4NETMASK='255.255.255.0'
-IPV4GATEWAY='192.168.122.1'
-IPV4DNS0='192.168.122.1'
-IPV4DNS1='0.0.0.0'
-HOSTNAME='foohost'
-DNSDOMAIN=''
-NISDOMAIN=''
-ROOTSERVER='192.168.122.1'
-ROOTPATH=''
-filename=''
-UPTIME='21'
-DHCPLEASETIME='3600'
-DOMAINSEARCH='foo.com'
-"""
-
-DHCP_EXPECTED_1 = {
- 'name': 'eth0',
- 'type': 'physical',
- 'subnets': [{'broadcast': '192.168.122.255',
- 'control': 'manual',
- 'gateway': '192.168.122.1',
- 'dns_search': ['foo.com'],
- 'type': 'dhcp',
- 'netmask': '255.255.255.0',
- 'dns_nameservers': ['192.168.122.1']}],
-}
-
-
-STATIC_CONTENT_1 = """
-DEVICE='eth1'
-PROTO='static'
-IPV4ADDR='10.0.0.2'
-IPV4BROADCAST='10.0.0.255'
-IPV4NETMASK='255.255.255.0'
-IPV4GATEWAY='10.0.0.1'
-IPV4DNS0='10.0.1.1'
-IPV4DNS1='0.0.0.0'
-HOSTNAME='foohost'
-UPTIME='21'
-DHCPLEASETIME='3600'
-DOMAINSEARCH='foo.com'
-"""
-
-STATIC_EXPECTED_1 = {
- 'name': 'eth1',
- 'type': 'physical',
- 'subnets': [{'broadcast': '10.0.0.255', 'control': 'manual',
- 'gateway': '10.0.0.1',
- 'dns_search': ['foo.com'], 'type': 'static',
- 'netmask': '255.255.255.0',
- 'dns_nameservers': ['10.0.1.1']}],
-}
-
-# Examples (and expected outputs for various renderers).
-OS_SAMPLES = [
- {
- 'in_data': {
- "services": [{"type": "dns", "address": "172.19.0.12"}],
- "networks": [{
- "network_id": "dacd568d-5be6-4786-91fe-750c374b78b4",
- "type": "ipv4", "netmask": "255.255.252.0",
- "link": "tap1a81968a-79",
- "routes": [{
- "netmask": "0.0.0.0",
- "network": "0.0.0.0",
- "gateway": "172.19.3.254",
- }],
- "ip_address": "172.19.1.34", "id": "network0"
- }],
- "links": [
- {
- "ethernet_mac_address": "fa:16:3e:ed:9a:59",
- "mtu": None, "type": "bridge", "id":
- "tap1a81968a-79",
- "vif_id": "1a81968a-797a-400f-8a80-567f997eb93f"
- },
- ],
- },
- 'in_macs': {
- 'fa:16:3e:ed:9a:59': 'eth0',
- },
- 'out_sysconfig': [
- ('etc/sysconfig/network-scripts/ifcfg-eth0',
- """
-# Created by cloud-init on instance boot automatically, do not edit.
-#
-BOOTPROTO=static
-DEFROUTE=yes
-DEVICE=eth0
-GATEWAY=172.19.3.254
-HWADDR=fa:16:3e:ed:9a:59
-IPADDR=172.19.1.34
-NETMASK=255.255.252.0
-NM_CONTROLLED=no
-ONBOOT=yes
-TYPE=Ethernet
-USERCTL=no
-""".lstrip()),
- ('etc/sysconfig/network-scripts/route-eth0',
- """
-# Created by cloud-init on instance boot automatically, do not edit.
-#
-ADDRESS0=0.0.0.0
-GATEWAY0=172.19.3.254
-NETMASK0=0.0.0.0
-""".lstrip()),
- ('etc/resolv.conf',
- """
-; Created by cloud-init on instance boot automatically, do not edit.
-;
-nameserver 172.19.0.12
-""".lstrip()),
- ('etc/udev/rules.d/70-persistent-net.rules',
- "".join(['SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ',
- 'ATTR{address}=="fa:16:3e:ed:9a:59", NAME="eth0"\n']))]
- }
-]
-
-EXAMPLE_ENI = """
-auto lo
-iface lo inet loopback
- dns-nameservers 10.0.0.1
- dns-search foo.com
-
-auto eth0
-iface eth0 inet static
- address 1.2.3.12
- netmask 255.255.255.248
- broadcast 1.2.3.15
- gateway 1.2.3.9
- dns-nameservers 69.9.160.191 69.9.191.4
-auto eth1
-iface eth1 inet static
- address 10.248.2.4
- netmask 255.255.255.248
- broadcast 10.248.2.7
-"""
-
-RENDERED_ENI = """
-auto lo
-iface lo inet loopback
- dns-nameservers 10.0.0.1
- dns-search foo.com
-
-auto eth0
-iface eth0 inet static
- address 1.2.3.12
- broadcast 1.2.3.15
- dns-nameservers 69.9.160.191 69.9.191.4
- gateway 1.2.3.9
- netmask 255.255.255.248
-
-auto eth1
-iface eth1 inet static
- address 10.248.2.4
- broadcast 10.248.2.7
- netmask 255.255.255.248
-""".lstrip()
-
-NETWORK_CONFIGS = {
- 'small': {
- 'expected_eni': textwrap.dedent("""\
- auto lo
- iface lo inet loopback
- dns-nameservers 1.2.3.4 5.6.7.8
- dns-search wark.maas
-
- iface eth1 inet manual
-
- auto eth99
- iface eth99 inet dhcp
- post-up ifup eth99:1
-
-
- auto eth99:1
- iface eth99:1 inet static
- address 192.168.21.3/24
- dns-nameservers 8.8.8.8 8.8.4.4
- dns-search barley.maas sach.maas
- post-up route add default gw 65.61.151.37 || true
- pre-down route del default gw 65.61.151.37 || true
- """).rstrip(' '),
- 'yaml': textwrap.dedent("""
- version: 1
- config:
- # Physical interfaces.
- - type: physical
- name: eth99
- mac_address: "c0:d6:9f:2c:e8:80"
- subnets:
- - type: dhcp4
- - type: static
- address: 192.168.21.3/24
- dns_nameservers:
- - 8.8.8.8
- - 8.8.4.4
- dns_search: barley.maas sach.maas
- routes:
- - gateway: 65.61.151.37
- netmask: 0.0.0.0
- network: 0.0.0.0
- metric: 2
- - type: physical
- name: eth1
- mac_address: "cf:d6:af:48:e8:80"
- - type: nameserver
- address:
- - 1.2.3.4
- - 5.6.7.8
- search:
- - wark.maas
- """),
- },
- 'all': {
- 'expected_eni': ("""\
-auto lo
-iface lo inet loopback
- dns-nameservers 8.8.8.8 4.4.4.4 8.8.4.4
- dns-search barley.maas wark.maas foobar.maas
-
-iface eth0 inet manual
-
-auto eth1
-iface eth1 inet manual
- bond-master bond0
- bond-mode active-backup
-
-auto eth2
-iface eth2 inet manual
- bond-master bond0
- bond-mode active-backup
-
-iface eth3 inet manual
-
-iface eth4 inet manual
-
-# control-manual eth5
-iface eth5 inet dhcp
-
-auto bond0
-iface bond0 inet6 dhcp
- bond-mode active-backup
- bond-slaves none
- hwaddress aa:bb:cc:dd:ee:ff
-
-auto br0
-iface br0 inet static
- address 192.168.14.2/24
- bridge_ports eth3 eth4
- bridge_stp off
- post-up ifup br0:1
-
-
-auto br0:1
-iface br0:1 inet6 static
- address 2001:1::1/64
-
-auto bond0.200
-iface bond0.200 inet dhcp
- vlan-raw-device bond0
- vlan_id 200
-
-auto eth0.101
-iface eth0.101 inet static
- address 192.168.0.2/24
- dns-nameservers 192.168.0.10 10.23.23.134
- dns-search barley.maas sacchromyces.maas brettanomyces.maas
- gateway 192.168.0.1
- mtu 1500
- vlan-raw-device eth0
- vlan_id 101
- post-up ifup eth0.101:1
-
-
-auto eth0.101:1
-iface eth0.101:1 inet static
- address 192.168.2.10/24
-
-post-up route add -net 10.0.0.0 netmask 255.0.0.0 gw 11.0.0.1 metric 3 || true
-pre-down route del -net 10.0.0.0 netmask 255.0.0.0 gw 11.0.0.1 metric 3 || true
-"""),
- 'yaml': textwrap.dedent("""
- version: 1
- config:
- # Physical interfaces.
- - type: physical
- name: eth0
- mac_address: "c0:d6:9f:2c:e8:80"
- - type: physical
- name: eth1
- mac_address: "aa:d6:9f:2c:e8:80"
- - type: physical
- name: eth2
- mac_address: "c0:bb:9f:2c:e8:80"
- - type: physical
- name: eth3
- mac_address: "66:bb:9f:2c:e8:80"
- - type: physical
- name: eth4
- mac_address: "98:bb:9f:2c:e8:80"
- # specify how ifupdown should treat iface
- # control is one of ['auto', 'hotplug', 'manual']
- # with manual meaning ifup/ifdown should not affect the iface
- # useful for things like iscsi root + dhcp
- - type: physical
- name: eth5
- mac_address: "98:bb:9f:2c:e8:8a"
- subnets:
- - type: dhcp
- control: manual
- # VLAN interface.
- - type: vlan
- name: eth0.101
- vlan_link: eth0
- vlan_id: 101
- mtu: 1500
- subnets:
- - type: static
- address: 192.168.0.2/24
- gateway: 192.168.0.1
- dns_nameservers:
- - 192.168.0.10
- - 10.23.23.134
- dns_search:
- - barley.maas
- - sacchromyces.maas
- - brettanomyces.maas
- - type: static
- address: 192.168.2.10/24
- # Bond.
- - type: bond
- name: bond0
- # if 'mac_address' is omitted, the MAC is taken from
- # the first slave.
- mac_address: "aa:bb:cc:dd:ee:ff"
- bond_interfaces:
- - eth1
- - eth2
- params:
- bond-mode: active-backup
- subnets:
- - type: dhcp6
- # A Bond VLAN.
- - type: vlan
- name: bond0.200
- vlan_link: bond0
- vlan_id: 200
- subnets:
- - type: dhcp4
- # A bridge.
- - type: bridge
- name: br0
- bridge_interfaces:
- - eth3
- - eth4
- ipv4_conf:
- rp_filter: 1
- proxy_arp: 0
- forwarding: 1
- ipv6_conf:
- autoconf: 1
- disable_ipv6: 1
- use_tempaddr: 1
- forwarding: 1
- # basically anything in /proc/sys/net/ipv6/conf/.../
- params:
- bridge_stp: 'off'
- bridge_fd: 0
- bridge_maxwait: 0
- subnets:
- - type: static
- address: 192.168.14.2/24
- - type: static
- address: 2001:1::1/64 # default to /64
- # A global nameserver.
- - type: nameserver
- address: 8.8.8.8
- search: barley.maas
- # global nameservers and search in list form
- - type: nameserver
- address:
- - 4.4.4.4
- - 8.8.4.4
- search:
- - wark.maas
- - foobar.maas
- # A global route.
- - type: route
- destination: 10.0.0.0/8
- gateway: 11.0.0.1
- metric: 3
- """).lstrip(),
- }
-}
-
-
-def _setup_test(tmp_dir, mock_get_devicelist, mock_sys_netdev_info,
- mock_sys_dev_path):
- mock_get_devicelist.return_value = ['eth1000']
- dev_characteristics = {
- 'eth1000': {
- "bridge": False,
- "carrier": False,
- "dormant": False,
- "operstate": "down",
- "address": "07-1C-C6-75-A4-BE",
- }
- }
-
- def netdev_info(name, field):
- return dev_characteristics[name][field]
-
- mock_sys_netdev_info.side_effect = netdev_info
-
- def sys_dev_path(devname, path=""):
- return tmp_dir + devname + "/" + path
-
- for dev in dev_characteristics:
- os.makedirs(os.path.join(tmp_dir, dev))
- with open(os.path.join(tmp_dir, dev, 'operstate'), 'w') as fh:
- fh.write("down")
-
- mock_sys_dev_path.side_effect = sys_dev_path
-
-
-class TestSysConfigRendering(TestCase):
-
- @mock.patch("cloudinit.net.sys_dev_path")
- @mock.patch("cloudinit.net.sys_netdev_info")
- @mock.patch("cloudinit.net.get_devicelist")
- def test_default_generation(self, mock_get_devicelist,
- mock_sys_netdev_info,
- mock_sys_dev_path):
- tmp_dir = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, tmp_dir)
- _setup_test(tmp_dir, mock_get_devicelist,
- mock_sys_netdev_info, mock_sys_dev_path)
-
- network_cfg = net.generate_fallback_config()
- ns = network_state.parse_net_config_data(network_cfg,
- skip_broken=False)
-
- render_dir = os.path.join(tmp_dir, "render")
- os.makedirs(render_dir)
-
- renderer = sysconfig.Renderer()
- renderer.render_network_state(render_dir, ns)
-
- render_file = 'etc/sysconfig/network-scripts/ifcfg-eth1000'
- with open(os.path.join(render_dir, render_file)) as fh:
- content = fh.read()
- expected_content = """
-# Created by cloud-init on instance boot automatically, do not edit.
-#
-BOOTPROTO=dhcp
-DEVICE=eth1000
-HWADDR=07-1C-C6-75-A4-BE
-NM_CONTROLLED=no
-ONBOOT=yes
-TYPE=Ethernet
-USERCTL=no
-""".lstrip()
- self.assertEqual(expected_content, content)
-
- def test_openstack_rendering_samples(self):
- tmp_dir = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, tmp_dir)
- render_dir = os.path.join(tmp_dir, "render")
- for os_sample in OS_SAMPLES:
- ex_input = os_sample['in_data']
- ex_mac_addrs = os_sample['in_macs']
- network_cfg = openstack.convert_net_json(
- ex_input, known_macs=ex_mac_addrs)
- ns = network_state.parse_net_config_data(network_cfg,
- skip_broken=False)
- renderer = sysconfig.Renderer()
- renderer.render_network_state(render_dir, ns)
- for fn, expected_content in os_sample.get('out_sysconfig', []):
- with open(os.path.join(render_dir, fn)) as fh:
- self.assertEqual(expected_content, fh.read())
-
-
-class TestEniNetRendering(TestCase):
-
- @mock.patch("cloudinit.net.sys_dev_path")
- @mock.patch("cloudinit.net.sys_netdev_info")
- @mock.patch("cloudinit.net.get_devicelist")
- def test_default_generation(self, mock_get_devicelist,
- mock_sys_netdev_info,
- mock_sys_dev_path):
- tmp_dir = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, tmp_dir)
- _setup_test(tmp_dir, mock_get_devicelist,
- mock_sys_netdev_info, mock_sys_dev_path)
-
- network_cfg = net.generate_fallback_config()
- ns = network_state.parse_net_config_data(network_cfg,
- skip_broken=False)
-
- render_dir = os.path.join(tmp_dir, "render")
- os.makedirs(render_dir)
-
- renderer = eni.Renderer(
- {'links_path_prefix': None,
- 'eni_path': 'interfaces', 'netrules_path': None,
- })
- renderer.render_network_state(render_dir, ns)
-
- self.assertTrue(os.path.exists(os.path.join(render_dir,
- 'interfaces')))
- with open(os.path.join(render_dir, 'interfaces')) as fh:
- contents = fh.read()
-
- expected = """
-auto lo
-iface lo inet loopback
-
-auto eth1000
-iface eth1000 inet dhcp
-"""
- self.assertEqual(expected.lstrip(), contents.lstrip())
-
-
-class TestEniNetworkStateToEni(TestCase):
- mycfg = {
- 'config': [{"type": "physical", "name": "eth0",
- "mac_address": "c0:d6:9f:2c:e8:80",
- "subnets": [{"type": "dhcp"}]}],
- 'version': 1}
- my_mac = 'c0:d6:9f:2c:e8:80'
-
- def test_no_header(self):
- rendered = eni.network_state_to_eni(
- network_state=network_state.parse_net_config_data(self.mycfg),
- render_hwaddress=True)
- self.assertIn(self.my_mac, rendered)
- self.assertIn("hwaddress", rendered)
-
- def test_with_header(self):
- header = "# hello world\n"
- rendered = eni.network_state_to_eni(
- network_state=network_state.parse_net_config_data(self.mycfg),
- header=header, render_hwaddress=True)
- self.assertIn(header, rendered)
- self.assertIn(self.my_mac, rendered)
-
- def test_no_hwaddress(self):
- rendered = eni.network_state_to_eni(
- network_state=network_state.parse_net_config_data(self.mycfg),
- render_hwaddress=False)
- self.assertNotIn(self.my_mac, rendered)
- self.assertNotIn("hwaddress", rendered)
-
-
-class TestCmdlineConfigParsing(TestCase):
- simple_cfg = {
- 'config': [{"type": "physical", "name": "eth0",
- "mac_address": "c0:d6:9f:2c:e8:80",
- "subnets": [{"type": "dhcp"}]}]}
-
- def test_cmdline_convert_dhcp(self):
- found = cmdline._klibc_to_config_entry(DHCP_CONTENT_1)
- self.assertEqual(found, ('eth0', DHCP_EXPECTED_1))
-
- def test_cmdline_convert_static(self):
- found = cmdline._klibc_to_config_entry(STATIC_CONTENT_1)
- self.assertEqual(found, ('eth1', STATIC_EXPECTED_1))
-
- def test_config_from_cmdline_net_cfg(self):
- files = []
- pairs = (('net-eth0.cfg', DHCP_CONTENT_1),
- ('net-eth1.cfg', STATIC_CONTENT_1))
-
- macs = {'eth1': 'b8:ae:ed:75:ff:2b',
- 'eth0': 'b8:ae:ed:75:ff:2a'}
-
- dhcp = copy.deepcopy(DHCP_EXPECTED_1)
- dhcp['mac_address'] = macs['eth0']
-
- static = copy.deepcopy(STATIC_EXPECTED_1)
- static['mac_address'] = macs['eth1']
-
- expected = {'version': 1, 'config': [dhcp, static]}
- with util.tempdir() as tmpd:
- for fname, content in pairs:
- fp = os.path.join(tmpd, fname)
- files.append(fp)
- util.write_file(fp, content)
-
- found = cmdline.config_from_klibc_net_cfg(files=files,
- mac_addrs=macs)
- self.assertEqual(found, expected)
-
- def test_cmdline_with_b64(self):
- data = base64.b64encode(json.dumps(self.simple_cfg).encode())
- encoded_text = data.decode()
- raw_cmdline = 'ro network-config=' + encoded_text + ' root=foo'
- found = cmdline.read_kernel_cmdline_config(cmdline=raw_cmdline)
- self.assertEqual(found, self.simple_cfg)
-
- def test_cmdline_with_b64_gz(self):
- data = _gzip_data(json.dumps(self.simple_cfg).encode())
- encoded_text = base64.b64encode(data).decode()
- raw_cmdline = 'ro network-config=' + encoded_text + ' root=foo'
- found = cmdline.read_kernel_cmdline_config(cmdline=raw_cmdline)
- self.assertEqual(found, self.simple_cfg)
-
-
-class TestEniRoundTrip(TestCase):
- def setUp(self):
- super(TestCase, self).setUp()
- self.tmp_dir = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp_dir)
-
- def _render_and_read(self, network_config=None, state=None, eni_path=None,
- links_prefix=None, netrules_path=None):
- if network_config:
- ns = network_state.parse_net_config_data(network_config)
- elif state:
- ns = state
- else:
- raise ValueError("Expected data or state, got neither")
-
- if eni_path is None:
- eni_path = 'etc/network/interfaces'
-
- renderer = eni.Renderer(
- config={'eni_path': eni_path, 'links_path_prefix': links_prefix,
- 'netrules_path': netrules_path})
-
- renderer.render_network_state(self.tmp_dir, ns)
- return dir2dict(self.tmp_dir)
-
- def testsimple_convert_and_render(self):
- network_config = eni.convert_eni_data(EXAMPLE_ENI)
- files = self._render_and_read(network_config=network_config)
- self.assertEqual(
- RENDERED_ENI.splitlines(),
- files['/etc/network/interfaces'].splitlines())
-
- def testsimple_render_all(self):
- entry = NETWORK_CONFIGS['all']
- files = self._render_and_read(network_config=yaml.load(entry['yaml']))
- self.assertEqual(
- entry['expected_eni'].splitlines(),
- files['/etc/network/interfaces'].splitlines())
-
- def testsimple_render_small(self):
- entry = NETWORK_CONFIGS['small']
- files = self._render_and_read(network_config=yaml.load(entry['yaml']))
- self.assertEqual(
- entry['expected_eni'].splitlines(),
- files['/etc/network/interfaces'].splitlines())
-
-
-def _gzip_data(data):
- with io.BytesIO() as iobuf:
- gzfp = gzip.GzipFile(mode="wb", fileobj=iobuf)
- gzfp.write(data)
- gzfp.close()
- return iobuf.getvalue()
diff --git a/tests/unittests/test_pathprefix2dict.py b/tests/unittests/test_pathprefix2dict.py
deleted file mode 100644
index 38fd75b6..00000000
--- a/tests/unittests/test_pathprefix2dict.py
+++ /dev/null
@@ -1,44 +0,0 @@
-from cloudinit import util
-
-from .helpers import TestCase, populate_dir
-
-import shutil
-import tempfile
-
-
-class TestPathPrefix2Dict(TestCase):
-
- def setUp(self):
- super(TestPathPrefix2Dict, self).setUp()
- self.tmp = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp)
-
- def test_required_only(self):
- dirdata = {'f1': b'f1content', 'f2': b'f2content'}
- populate_dir(self.tmp, dirdata)
-
- ret = util.pathprefix2dict(self.tmp, required=['f1', 'f2'])
- self.assertEqual(dirdata, ret)
-
- def test_required_missing(self):
- dirdata = {'f1': b'f1content'}
- populate_dir(self.tmp, dirdata)
- kwargs = {'required': ['f1', 'f2']}
- self.assertRaises(ValueError, util.pathprefix2dict, self.tmp, **kwargs)
-
- def test_no_required_and_optional(self):
- dirdata = {'f1': b'f1c', 'f2': b'f2c'}
- populate_dir(self.tmp, dirdata)
-
- ret = util.pathprefix2dict(self.tmp, required=None,
- optional=['f1', 'f2'])
- self.assertEqual(dirdata, ret)
-
- def test_required_and_optional(self):
- dirdata = {'f1': b'f1c', 'f2': b'f2c'}
- populate_dir(self.tmp, dirdata)
-
- ret = util.pathprefix2dict(self.tmp, required=['f1'], optional=['f2'])
- self.assertEqual(dirdata, ret)
-
-# vi: ts=4 expandtab
diff --git a/tests/unittests/test_registry.py b/tests/unittests/test_registry.py
deleted file mode 100644
index bcf01475..00000000
--- a/tests/unittests/test_registry.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from cloudinit.registry import DictRegistry
-
-from .helpers import (mock, TestCase)
-
-
-class TestDictRegistry(TestCase):
-
- def test_added_item_included_in_output(self):
- registry = DictRegistry()
- item_key, item_to_register = 'test_key', mock.Mock()
- registry.register_item(item_key, item_to_register)
- self.assertEqual({item_key: item_to_register},
- registry.registered_items)
-
- def test_registry_starts_out_empty(self):
- self.assertEqual({}, DictRegistry().registered_items)
-
- def test_modifying_registered_items_isnt_exposed_to_other_callers(self):
- registry = DictRegistry()
- registry.registered_items['test_item'] = mock.Mock()
- self.assertEqual({}, registry.registered_items)
-
- def test_keys_cannot_be_replaced(self):
- registry = DictRegistry()
- item_key = 'test_key'
- registry.register_item(item_key, mock.Mock())
- self.assertRaises(ValueError,
- registry.register_item, item_key, mock.Mock())
diff --git a/tests/unittests/test_reporting.py b/tests/unittests/test_reporting.py
deleted file mode 100644
index 20ca23df..00000000
--- a/tests/unittests/test_reporting.py
+++ /dev/null
@@ -1,371 +0,0 @@
-# Copyright 2015 Canonical Ltd.
-# This file is part of cloud-init. See LICENCE file for license information.
-#
-# vi: ts=4 expandtab
-
-from cloudinit import reporting
-from cloudinit.reporting import events
-from cloudinit.reporting import handlers
-
-import mock
-
-from .helpers import TestCase
-
-
-def _fake_registry():
- return mock.Mock(registered_items={'a': mock.MagicMock(),
- 'b': mock.MagicMock()})
-
-
-class TestReportStartEvent(TestCase):
-
- @mock.patch('cloudinit.reporting.events.instantiated_handler_registry',
- new_callable=_fake_registry)
- def test_report_start_event_passes_something_with_as_string_to_handlers(
- self, instantiated_handler_registry):
- event_name, event_description = 'my_test_event', 'my description'
- events.report_start_event(event_name, event_description)
- expected_string_representation = ': '.join(
- ['start', event_name, event_description])
- for _, handler in (
- instantiated_handler_registry.registered_items.items()):
- self.assertEqual(1, handler.publish_event.call_count)
- event = handler.publish_event.call_args[0][0]
- self.assertEqual(expected_string_representation, event.as_string())
-
-
-class TestReportFinishEvent(TestCase):
-
- def _report_finish_event(self, result=events.status.SUCCESS):
- event_name, event_description = 'my_test_event', 'my description'
- events.report_finish_event(
- event_name, event_description, result=result)
- return event_name, event_description
-
- def assertHandlersPassedObjectWithAsString(
- self, handlers, expected_as_string):
- for _, handler in handlers.items():
- self.assertEqual(1, handler.publish_event.call_count)
- event = handler.publish_event.call_args[0][0]
- self.assertEqual(expected_as_string, event.as_string())
-
- @mock.patch('cloudinit.reporting.events.instantiated_handler_registry',
- new_callable=_fake_registry)
- def test_report_finish_event_passes_something_with_as_string_to_handlers(
- self, instantiated_handler_registry):
- event_name, event_description = self._report_finish_event()
- expected_string_representation = ': '.join(
- ['finish', event_name, events.status.SUCCESS,
- event_description])
- self.assertHandlersPassedObjectWithAsString(
- instantiated_handler_registry.registered_items,
- expected_string_representation)
-
- @mock.patch('cloudinit.reporting.events.instantiated_handler_registry',
- new_callable=_fake_registry)
- def test_reporting_successful_finish_has_sensible_string_repr(
- self, instantiated_handler_registry):
- event_name, event_description = self._report_finish_event(
- result=events.status.SUCCESS)
- expected_string_representation = ': '.join(
- ['finish', event_name, events.status.SUCCESS,
- event_description])
- self.assertHandlersPassedObjectWithAsString(
- instantiated_handler_registry.registered_items,
- expected_string_representation)
-
- @mock.patch('cloudinit.reporting.events.instantiated_handler_registry',
- new_callable=_fake_registry)
- def test_reporting_unsuccessful_finish_has_sensible_string_repr(
- self, instantiated_handler_registry):
- event_name, event_description = self._report_finish_event(
- result=events.status.FAIL)
- expected_string_representation = ': '.join(
- ['finish', event_name, events.status.FAIL, event_description])
- self.assertHandlersPassedObjectWithAsString(
- instantiated_handler_registry.registered_items,
- expected_string_representation)
-
- def test_invalid_result_raises_attribute_error(self):
- self.assertRaises(ValueError, self._report_finish_event, ("BOGUS",))
-
-
-class TestReportingEvent(TestCase):
-
- def test_as_string(self):
- event_type, name, description = 'test_type', 'test_name', 'test_desc'
- event = events.ReportingEvent(event_type, name, description)
- expected_string_representation = ': '.join(
- [event_type, name, description])
- self.assertEqual(expected_string_representation, event.as_string())
-
- def test_as_dict(self):
- event_type, name, desc = 'test_type', 'test_name', 'test_desc'
- event = events.ReportingEvent(event_type, name, desc)
- expected = {'event_type': event_type, 'name': name,
- 'description': desc, 'origin': 'cloudinit'}
-
- # allow for timestamp to differ, but must be present
- as_dict = event.as_dict()
- self.assertIn('timestamp', as_dict)
- del as_dict['timestamp']
-
- self.assertEqual(expected, as_dict)
-
-
-class TestFinishReportingEvent(TestCase):
- def test_as_has_result(self):
- result = events.status.SUCCESS
- name, desc = 'test_name', 'test_desc'
- event = events.FinishReportingEvent(name, desc, result)
- ret = event.as_dict()
- self.assertTrue('result' in ret)
- self.assertEqual(ret['result'], result)
-
-
-class TestBaseReportingHandler(TestCase):
-
- def test_base_reporting_handler_is_abstract(self):
- regexp = r".*abstract.*publish_event.*"
- self.assertRaisesRegexp(TypeError, regexp, handlers.ReportingHandler)
-
-
-class TestLogHandler(TestCase):
-
- @mock.patch.object(reporting.handlers.logging, 'getLogger')
- def test_appropriate_logger_used(self, getLogger):
- event_type, event_name = 'test_type', 'test_name'
- event = events.ReportingEvent(event_type, event_name, 'description')
- reporting.handlers.LogHandler().publish_event(event)
- self.assertEqual(
- [mock.call(
- 'cloudinit.reporting.{0}.{1}'.format(event_type, event_name))],
- getLogger.call_args_list)
-
- @mock.patch.object(reporting.handlers.logging, 'getLogger')
- def test_single_log_message_at_info_published(self, getLogger):
- event = events.ReportingEvent('type', 'name', 'description')
- reporting.handlers.LogHandler().publish_event(event)
- self.assertEqual(1, getLogger.return_value.log.call_count)
-
- @mock.patch.object(reporting.handlers.logging, 'getLogger')
- def test_log_message_uses_event_as_string(self, getLogger):
- event = events.ReportingEvent('type', 'name', 'description')
- reporting.handlers.LogHandler(level="INFO").publish_event(event)
- self.assertIn(event.as_string(),
- getLogger.return_value.log.call_args[0][1])
-
-
-class TestDefaultRegisteredHandler(TestCase):
-
- def test_log_handler_registered_by_default(self):
- registered_items = (
- reporting.instantiated_handler_registry.registered_items)
- for _, item in registered_items.items():
- if isinstance(item, reporting.handlers.LogHandler):
- break
- else:
- self.fail('No reporting LogHandler registered by default.')
-
-
-class TestReportingConfiguration(TestCase):
-
- @mock.patch.object(reporting, 'instantiated_handler_registry')
- def test_empty_configuration_doesnt_add_handlers(
- self, instantiated_handler_registry):
- reporting.update_configuration({})
- self.assertEqual(
- 0, instantiated_handler_registry.register_item.call_count)
-
- @mock.patch.object(
- reporting, 'instantiated_handler_registry', reporting.DictRegistry())
- @mock.patch.object(reporting, 'available_handlers')
- def test_looks_up_handler_by_type_and_adds_it(self, available_handlers):
- handler_type_name = 'test_handler'
- handler_cls = mock.Mock()
- available_handlers.registered_items = {handler_type_name: handler_cls}
- handler_name = 'my_test_handler'
- reporting.update_configuration(
- {handler_name: {'type': handler_type_name}})
- self.assertEqual(
- {handler_name: handler_cls.return_value},
- reporting.instantiated_handler_registry.registered_items)
-
- @mock.patch.object(
- reporting, 'instantiated_handler_registry', reporting.DictRegistry())
- @mock.patch.object(reporting, 'available_handlers')
- def test_uses_non_type_parts_of_config_dict_as_kwargs(
- self, available_handlers):
- handler_type_name = 'test_handler'
- handler_cls = mock.Mock()
- available_handlers.registered_items = {handler_type_name: handler_cls}
- extra_kwargs = {'foo': 'bar', 'bar': 'baz'}
- handler_config = extra_kwargs.copy()
- handler_config.update({'type': handler_type_name})
- handler_name = 'my_test_handler'
- reporting.update_configuration({handler_name: handler_config})
- self.assertEqual(
- handler_cls.return_value,
- reporting.instantiated_handler_registry.registered_items[
- handler_name])
- self.assertEqual([mock.call(**extra_kwargs)],
- handler_cls.call_args_list)
-
- @mock.patch.object(
- reporting, 'instantiated_handler_registry', reporting.DictRegistry())
- @mock.patch.object(reporting, 'available_handlers')
- def test_handler_config_not_modified(self, available_handlers):
- handler_type_name = 'test_handler'
- handler_cls = mock.Mock()
- available_handlers.registered_items = {handler_type_name: handler_cls}
- handler_config = {'type': handler_type_name, 'foo': 'bar'}
- expected_handler_config = handler_config.copy()
- reporting.update_configuration({'my_test_handler': handler_config})
- self.assertEqual(expected_handler_config, handler_config)
-
- @mock.patch.object(
- reporting, 'instantiated_handler_registry', reporting.DictRegistry())
- @mock.patch.object(reporting, 'available_handlers')
- def test_handlers_removed_if_falseish_specified(self, available_handlers):
- handler_type_name = 'test_handler'
- handler_cls = mock.Mock()
- available_handlers.registered_items = {handler_type_name: handler_cls}
- handler_name = 'my_test_handler'
- reporting.update_configuration(
- {handler_name: {'type': handler_type_name}})
- self.assertEqual(
- 1, len(reporting.instantiated_handler_registry.registered_items))
- reporting.update_configuration({handler_name: None})
- self.assertEqual(
- 0, len(reporting.instantiated_handler_registry.registered_items))
-
-
-class TestReportingEventStack(TestCase):
- @mock.patch('cloudinit.reporting.events.report_finish_event')
- @mock.patch('cloudinit.reporting.events.report_start_event')
- def test_start_and_finish_success(self, report_start, report_finish):
- with events.ReportEventStack(name="myname", description="mydesc"):
- pass
- self.assertEqual(
- [mock.call('myname', 'mydesc')], report_start.call_args_list)
- self.assertEqual(
- [mock.call('myname', 'mydesc', events.status.SUCCESS,
- post_files=[])],
- report_finish.call_args_list)
-
- @mock.patch('cloudinit.reporting.events.report_finish_event')
- @mock.patch('cloudinit.reporting.events.report_start_event')
- def test_finish_exception_defaults_fail(self, report_start, report_finish):
- name = "myname"
- desc = "mydesc"
- try:
- with events.ReportEventStack(name, description=desc):
- raise ValueError("This didnt work")
- except ValueError:
- pass
- self.assertEqual([mock.call(name, desc)], report_start.call_args_list)
- self.assertEqual(
- [mock.call(name, desc, events.status.FAIL, post_files=[])],
- report_finish.call_args_list)
-
- @mock.patch('cloudinit.reporting.events.report_finish_event')
- @mock.patch('cloudinit.reporting.events.report_start_event')
- def test_result_on_exception_used(self, report_start, report_finish):
- name = "myname"
- desc = "mydesc"
- try:
- with events.ReportEventStack(
- name, desc, result_on_exception=events.status.WARN):
- raise ValueError("This didnt work")
- except ValueError:
- pass
- self.assertEqual([mock.call(name, desc)], report_start.call_args_list)
- self.assertEqual(
- [mock.call(name, desc, events.status.WARN, post_files=[])],
- report_finish.call_args_list)
-
- @mock.patch('cloudinit.reporting.events.report_start_event')
- def test_child_fullname_respects_parent(self, report_start):
- parent_name = "topname"
- c1_name = "c1name"
- c2_name = "c2name"
- c2_expected_fullname = '/'.join([parent_name, c1_name, c2_name])
- c1_expected_fullname = '/'.join([parent_name, c1_name])
-
- parent = events.ReportEventStack(parent_name, "topdesc")
- c1 = events.ReportEventStack(c1_name, "c1desc", parent=parent)
- c2 = events.ReportEventStack(c2_name, "c2desc", parent=c1)
- with c1:
- report_start.assert_called_with(c1_expected_fullname, "c1desc")
- with c2:
- report_start.assert_called_with(c2_expected_fullname, "c2desc")
-
- @mock.patch('cloudinit.reporting.events.report_finish_event')
- @mock.patch('cloudinit.reporting.events.report_start_event')
- def test_child_result_bubbles_up(self, report_start, report_finish):
- parent = events.ReportEventStack("topname", "topdesc")
- child = events.ReportEventStack("c_name", "c_desc", parent=parent)
- with parent:
- with child:
- child.result = events.status.WARN
-
- report_finish.assert_called_with(
- "topname", "topdesc", events.status.WARN, post_files=[])
-
- @mock.patch('cloudinit.reporting.events.report_finish_event')
- def test_message_used_in_finish(self, report_finish):
- with events.ReportEventStack("myname", "mydesc",
- message="mymessage"):
- pass
- self.assertEqual(
- [mock.call("myname", "mymessage", events.status.SUCCESS,
- post_files=[])],
- report_finish.call_args_list)
-
- @mock.patch('cloudinit.reporting.events.report_finish_event')
- def test_message_updatable(self, report_finish):
- with events.ReportEventStack("myname", "mydesc") as c:
- c.message = "all good"
- self.assertEqual(
- [mock.call("myname", "all good", events.status.SUCCESS,
- post_files=[])],
- report_finish.call_args_list)
-
- @mock.patch('cloudinit.reporting.events.report_start_event')
- @mock.patch('cloudinit.reporting.events.report_finish_event')
- def test_reporting_disabled_does_not_report_events(
- self, report_start, report_finish):
- with events.ReportEventStack("a", "b", reporting_enabled=False):
- pass
- self.assertEqual(report_start.call_count, 0)
- self.assertEqual(report_finish.call_count, 0)
-
- @mock.patch('cloudinit.reporting.events.report_start_event')
- @mock.patch('cloudinit.reporting.events.report_finish_event')
- def test_reporting_child_default_to_parent(
- self, report_start, report_finish):
- parent = events.ReportEventStack(
- "pname", "pdesc", reporting_enabled=False)
- child = events.ReportEventStack("cname", "cdesc", parent=parent)
- with parent:
- with child:
- pass
- pass
- self.assertEqual(report_start.call_count, 0)
- self.assertEqual(report_finish.call_count, 0)
-
- def test_reporting_event_has_sane_repr(self):
- myrep = events.ReportEventStack("fooname", "foodesc",
- reporting_enabled=True).__repr__()
- self.assertIn("fooname", myrep)
- self.assertIn("foodesc", myrep)
- self.assertIn("True", myrep)
-
- def test_set_invalid_result_raises_value_error(self):
- f = events.ReportEventStack("myname", "mydesc")
- self.assertRaises(ValueError, setattr, f, "result", "BOGUS")
-
-
-class TestStatusAccess(TestCase):
- def test_invalid_status_access_raises_value_error(self):
- self.assertRaises(AttributeError, getattr, events.status, "BOGUS")
diff --git a/tests/unittests/test_rh_subscription.py b/tests/unittests/test_rh_subscription.py
deleted file mode 100644
index 891dbe77..00000000
--- a/tests/unittests/test_rh_subscription.py
+++ /dev/null
@@ -1,226 +0,0 @@
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 3, as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-import logging
-
-from cloudinit.config import cc_rh_subscription
-from cloudinit import util
-
-from .helpers import TestCase, mock
-
-
-class GoodTests(TestCase):
- def setUp(self):
- super(GoodTests, self).setUp()
- self.name = "cc_rh_subscription"
- self.cloud_init = None
- self.log = logging.getLogger("good_tests")
- self.args = []
- self.handle = cc_rh_subscription.handle
- self.SM = cc_rh_subscription.SubscriptionManager
-
- self.config = {'rh_subscription':
- {'username': 'scooby@do.com',
- 'password': 'scooby-snacks'
- }}
- self.config_full = {'rh_subscription':
- {'username': 'scooby@do.com',
- 'password': 'scooby-snacks',
- 'auto-attach': True,
- 'service-level': 'self-support',
- 'add-pool': ['pool1', 'pool2', 'pool3'],
- 'enable-repo': ['repo1', 'repo2', 'repo3'],
- 'disable-repo': ['repo4', 'repo5']
- }}
-
- def test_already_registered(self):
- '''
- Emulates a system that is already registered. Ensure it gets
- a non-ProcessExecution error from is_registered()
- '''
- with mock.patch.object(cc_rh_subscription.SubscriptionManager,
- '_sub_man_cli') as mockobj:
- self.SM.log_success = mock.MagicMock()
- self.handle(self.name, self.config, self.cloud_init,
- self.log, self.args)
- self.assertEqual(self.SM.log_success.call_count, 1)
- self.assertEqual(mockobj.call_count, 1)
-
- def test_simple_registration(self):
- '''
- Simple registration with username and password
- '''
- self.SM.log_success = mock.MagicMock()
- reg = "The system has been registered with ID:" \
- " 12345678-abde-abcde-1234-1234567890abc"
- self.SM._sub_man_cli = mock.MagicMock(
- side_effect=[util.ProcessExecutionError, (reg, 'bar')])
- self.handle(self.name, self.config, self.cloud_init,
- self.log, self.args)
- self.assertIn(mock.call(['identity']),
- self.SM._sub_man_cli.call_args_list)
- self.assertIn(mock.call(['register', '--username=scooby@do.com',
- '--password=scooby-snacks'],
- logstring_val=True),
- self.SM._sub_man_cli.call_args_list)
-
- self.assertEqual(self.SM.log_success.call_count, 1)
- self.assertEqual(self.SM._sub_man_cli.call_count, 2)
-
- def test_full_registration(self):
- '''
- Registration with auto-attach, service-level, adding pools,
- and enabling and disabling yum repos
- '''
- call_lists = []
- call_lists.append(['attach', '--pool=pool1', '--pool=pool3'])
- call_lists.append(['repos', '--enable=repo2', '--enable=repo3',
- '--disable=repo5'])
- call_lists.append(['attach', '--auto', '--servicelevel=self-support'])
- self.SM.log_success = mock.MagicMock()
- reg = "The system has been registered with ID:" \
- " 12345678-abde-abcde-1234-1234567890abc"
- self.SM._sub_man_cli = mock.MagicMock(
- side_effect=[util.ProcessExecutionError, (reg, 'bar'),
- ('Service level set to: self-support', ''),
- ('pool1\npool3\n', ''), ('pool2\n', ''), ('', ''),
- ('Repo ID: repo1\nRepo ID: repo5\n', ''),
- ('Repo ID: repo2\nRepo ID: repo3\nRepo ID: '
- 'repo4', ''),
- ('', '')])
- self.handle(self.name, self.config_full, self.cloud_init,
- self.log, self.args)
- for call in call_lists:
- self.assertIn(mock.call(call), self.SM._sub_man_cli.call_args_list)
- self.assertEqual(self.SM.log_success.call_count, 1)
- self.assertEqual(self.SM._sub_man_cli.call_count, 9)
-
-
-class TestBadInput(TestCase):
- name = "cc_rh_subscription"
- cloud_init = None
- log = logging.getLogger("bad_tests")
- args = []
- SM = cc_rh_subscription.SubscriptionManager
- reg = "The system has been registered with ID:" \
- " 12345678-abde-abcde-1234-1234567890abc"
-
- config_no_password = {'rh_subscription':
- {'username': 'scooby@do.com'
- }}
-
- config_no_key = {'rh_subscription':
- {'activation-key': '1234abcde',
- }}
-
- config_service = {'rh_subscription':
- {'username': 'scooby@do.com',
- 'password': 'scooby-snacks',
- 'service-level': 'self-support'
- }}
-
- config_badpool = {'rh_subscription':
- {'username': 'scooby@do.com',
- 'password': 'scooby-snacks',
- 'add-pool': 'not_a_list'
- }}
- config_badrepo = {'rh_subscription':
- {'username': 'scooby@do.com',
- 'password': 'scooby-snacks',
- 'enable-repo': 'not_a_list'
- }}
- config_badkey = {'rh_subscription':
- {'activation-key': 'abcdef1234',
- 'fookey': 'bar',
- 'org': '123',
- }}
-
- def setUp(self):
- super(TestBadInput, self).setUp()
- self.handle = cc_rh_subscription.handle
-
- def test_no_password(self):
- '''
- Attempt to register without the password key/value
- '''
- self.SM._sub_man_cli = mock.MagicMock(
- side_effect=[util.ProcessExecutionError, (self.reg, 'bar')])
- self.handle(self.name, self.config_no_password, self.cloud_init,
- self.log, self.args)
- self.assertEqual(self.SM._sub_man_cli.call_count, 0)
-
- def test_no_org(self):
- '''
- Attempt to register without the org key/value
- '''
- self.input_is_missing_data(self.config_no_key)
-
- def test_service_level_without_auto(self):
- '''
- Attempt to register using service-level without the auto-attach key
- '''
- self.SM.log_warn = mock.MagicMock()
- self.SM._sub_man_cli = mock.MagicMock(
- side_effect=[util.ProcessExecutionError, (self.reg, 'bar')])
- self.handle(self.name, self.config_service, self.cloud_init,
- self.log, self.args)
- self.assertEqual(self.SM._sub_man_cli.call_count, 1)
- self.assertEqual(self.SM.log_warn.call_count, 2)
-
- def test_pool_not_a_list(self):
- '''
- Register with pools that are not in the format of a list
- '''
- self.SM.log_warn = mock.MagicMock()
- self.SM._sub_man_cli = mock.MagicMock(
- side_effect=[util.ProcessExecutionError, (self.reg, 'bar')])
- self.handle(self.name, self.config_badpool, self.cloud_init,
- self.log, self.args)
- self.assertEqual(self.SM._sub_man_cli.call_count, 2)
- self.assertEqual(self.SM.log_warn.call_count, 2)
-
- def test_repo_not_a_list(self):
- '''
- Register with repos that are not in the format of a list
- '''
- self.SM.log_warn = mock.MagicMock()
- self.SM._sub_man_cli = mock.MagicMock(
- side_effect=[util.ProcessExecutionError, (self.reg, 'bar')])
- self.handle(self.name, self.config_badrepo, self.cloud_init,
- self.log, self.args)
- self.assertEqual(self.SM.log_warn.call_count, 3)
- self.assertEqual(self.SM._sub_man_cli.call_count, 2)
-
- def test_bad_key_value(self):
- '''
- Attempt to register with a key that we don't know
- '''
- self.SM.log_warn = mock.MagicMock()
- self.SM._sub_man_cli = mock.MagicMock(
- side_effect=[util.ProcessExecutionError, (self.reg, 'bar')])
- self.handle(self.name, self.config_badkey, self.cloud_init,
- self.log, self.args)
- self.assertEqual(self.SM.log_warn.call_count, 2)
- self.assertEqual(self.SM._sub_man_cli.call_count, 1)
-
- def input_is_missing_data(self, config):
- '''
- Helper def for tests that having missing information
- '''
- self.SM.log_warn = mock.MagicMock()
- self.SM._sub_man_cli = mock.MagicMock(
- side_effect=[util.ProcessExecutionError])
- self.handle(self.name, config, self.cloud_init,
- self.log, self.args)
- self.SM._sub_man_cli.assert_called_with(['identity'])
- self.assertEqual(self.SM.log_warn.call_count, 4)
- self.assertEqual(self.SM._sub_man_cli.call_count, 1)
diff --git a/tests/unittests/test_runs/__init__.py b/tests/unittests/test_runs/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/unittests/test_runs/__init__.py
+++ /dev/null
diff --git a/tests/unittests/test_runs/test_merge_run.py b/tests/unittests/test_runs/test_merge_run.py
deleted file mode 100644
index ce43798e..00000000
--- a/tests/unittests/test_runs/test_merge_run.py
+++ /dev/null
@@ -1,54 +0,0 @@
-import os
-import shutil
-import tempfile
-
-from .. import helpers
-
-from cloudinit.settings import PER_INSTANCE
-from cloudinit import stages
-from cloudinit import util
-
-
-class TestMergeRun(helpers.FilesystemMockingTestCase):
- def _patchIn(self, root):
- self.patchOS(root)
- self.patchUtils(root)
-
- def test_none_ds(self):
- new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, new_root)
- self.replicateTestRoot('simple_ubuntu', new_root)
- cfg = {
- 'datasource_list': ['None'],
- 'cloud_init_modules': ['write-files'],
- }
- ud = self.readResource('user_data.1.txt')
- cloud_cfg = util.yaml_dumps(cfg)
- util.ensure_dir(os.path.join(new_root, 'etc', 'cloud'))
- util.write_file(os.path.join(new_root, 'etc',
- 'cloud', 'cloud.cfg'), cloud_cfg)
- self._patchIn(new_root)
-
- # Now start verifying whats created
- initer = stages.Init()
- initer.read_cfg()
- initer.initialize()
- initer.fetch()
- initer.datasource.userdata_raw = ud
- initer.instancify()
- initer.update()
- initer.cloudify().run('consume_data',
- initer.consume_data,
- args=[PER_INSTANCE],
- freq=PER_INSTANCE)
- mirrors = initer.distro.get_option('package_mirrors')
- self.assertEqual(1, len(mirrors))
- mirror = mirrors[0]
- self.assertEqual(mirror['arches'], ['i386', 'amd64', 'blah'])
- mods = stages.Modules(initer)
- (which_ran, failures) = mods.run_section('cloud_init_modules')
- self.assertTrue(len(failures) == 0)
- self.assertTrue(os.path.exists('/etc/blah.ini'))
- self.assertIn('write-files', which_ran)
- contents = util.load_file('/etc/blah.ini')
- self.assertEqual(contents, 'blah')
diff --git a/tests/unittests/test_runs/test_simple_run.py b/tests/unittests/test_runs/test_simple_run.py
deleted file mode 100644
index 07e7b1a8..00000000
--- a/tests/unittests/test_runs/test_simple_run.py
+++ /dev/null
@@ -1,81 +0,0 @@
-import os
-import shutil
-import tempfile
-
-from .. import helpers
-
-from cloudinit.settings import PER_INSTANCE
-from cloudinit import stages
-from cloudinit import util
-
-
-class TestSimpleRun(helpers.FilesystemMockingTestCase):
- def _patchIn(self, root):
- self.patchOS(root)
- self.patchUtils(root)
-
- def _pp_root(self, root, repatch=True):
- for (dirpath, dirnames, filenames) in os.walk(root):
- print(dirpath)
- for f in filenames:
- joined = os.path.join(dirpath, f)
- if os.path.islink(joined):
- print("f %s - (symlink)" % (f))
- else:
- print("f %s" % (f))
- for d in dirnames:
- joined = os.path.join(dirpath, d)
- if os.path.islink(joined):
- print("d %s - (symlink)" % (d))
- else:
- print("d %s" % (d))
- if repatch:
- self._patchIn(root)
-
- def test_none_ds(self):
- new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, new_root)
- self.replicateTestRoot('simple_ubuntu', new_root)
- cfg = {
- 'datasource_list': ['None'],
- 'write_files': [
- {
- 'path': '/etc/blah.ini',
- 'content': 'blah',
- 'permissions': 0o755,
- },
- ],
- 'cloud_init_modules': ['write-files'],
- }
- cloud_cfg = util.yaml_dumps(cfg)
- util.ensure_dir(os.path.join(new_root, 'etc', 'cloud'))
- util.write_file(os.path.join(new_root, 'etc',
- 'cloud', 'cloud.cfg'), cloud_cfg)
- self._patchIn(new_root)
-
- # Now start verifying whats created
- initer = stages.Init()
- initer.read_cfg()
- initer.initialize()
- self.assertTrue(os.path.exists("/var/lib/cloud"))
- for d in ['scripts', 'seed', 'instances', 'handlers', 'sem', 'data']:
- self.assertTrue(os.path.isdir(os.path.join("/var/lib/cloud", d)))
-
- initer.fetch()
- iid = initer.instancify()
- self.assertEqual(iid, 'iid-datasource-none')
- initer.update()
- self.assertTrue(os.path.islink("var/lib/cloud/instance"))
-
- initer.cloudify().run('consume_data',
- initer.consume_data,
- args=[PER_INSTANCE],
- freq=PER_INSTANCE)
-
- mods = stages.Modules(initer)
- (which_ran, failures) = mods.run_section('cloud_init_modules')
- self.assertTrue(len(failures) == 0)
- self.assertTrue(os.path.exists('/etc/blah.ini'))
- self.assertIn('write-files', which_ran)
- contents = util.load_file('/etc/blah.ini')
- self.assertEqual(contents, 'blah')
diff --git a/tests/unittests/test_sshutil.py b/tests/unittests/test_sshutil.py
deleted file mode 100644
index 9aeb1cde..00000000
--- a/tests/unittests/test_sshutil.py
+++ /dev/null
@@ -1,171 +0,0 @@
-from mock import patch
-
-from . import helpers as test_helpers
-from cloudinit import ssh_util
-
-
-VALID_CONTENT = {
- 'dsa': (
- "AAAAB3NzaC1kc3MAAACBAIrjOQSlSea19bExXBMBKBvcLhBoVvNBjCppNzllipF"
- "W4jgIOMcNanULRrZGjkOKat6MWJNetSbV1E6IOFDQ16rQgsh/OvYU9XhzM8seLa"
- "A21VszZuhIV7/2DE3vxu7B54zVzueG1O1Deq6goQCRGWBUnqO2yluJiG4HzrnDa"
- "jzRAAAAFQDMPO96qXd4F5A+5b2f2MO7SpVomQAAAIBpC3K2zIbDLqBBs1fn7rsv"
- "KcJvwihdlVjG7UXsDB76P2GNqVG+IlYPpJZ8TO/B/fzTMtrdXp9pSm9OY1+BgN4"
- "REsZ2WNcvfgY33aWaEM+ieCcQigvxrNAF2FTVcbUIIxAn6SmHuQSWrLSfdHc8H7"
- "hsrgeUPPdzjBD/cv2ZmqwZ1AAAAIAplIsScrJut5wJMgyK1JG0Kbw9JYQpLe95P"
- "obB069g8+mYR8U0fysmTEdR44mMu0VNU5E5OhTYoTGfXrVrkR134LqFM2zpVVbE"
- "JNDnIqDHxTkc6LY2vu8Y2pQ3/bVnllZZOda2oD5HQ7ovygQa6CH+fbaZHbdDUX/"
- "5z7u2rVAlDw=="
- ),
- 'ecdsa': (
- "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBITrGBB3cgJ"
- "J7fPxvtMW9H3oRisNpJ3OAslxZeyP7I0A9BPAW0RQIwHVtVnM7zrp4nI+JLZov/"
- "Ql7lc2leWL7CY="
- ),
- 'rsa': (
- "AAAAB3NzaC1yc2EAAAABIwAAAQEA3I7VUf2l5gSn5uavROsc5HRDpZdQueUq5oz"
- "emNSj8T7enqKHOEaFoU2VoPgGEWC9RyzSQVeyD6s7APMcE82EtmW4skVEgEGSbD"
- "c1pvxzxtchBj78hJP6Cf5TCMFSXw+Fz5rF1dR23QDbN1mkHs7adr8GW4kSWqU7Q"
- "7NDwfIrJJtO7Hi42GyXtvEONHbiRPOe8stqUly7MvUoN+5kfjBM8Qqpfl2+FNhT"
- "YWpMfYdPUnE7u536WqzFmsaqJctz3gBxH9Ex7dFtrxR4qiqEr9Qtlu3xGn7Bw07"
- "/+i1D+ey3ONkZLN+LQ714cgj8fRS4Hj29SCmXp5Kt5/82cD/VN3NtHw=="
- ),
-}
-
-TEST_OPTIONS = (
- "no-port-forwarding,no-agent-forwarding,no-X11-forwarding,"
- 'command="echo \'Please login as the user \"ubuntu\" rather than the'
- 'user \"root\".\';echo;sleep 10"')
-
-
-class TestAuthKeyLineParser(test_helpers.TestCase):
- def test_simple_parse(self):
- # test key line with common 3 fields (keytype, base64, comment)
- parser = ssh_util.AuthKeyLineParser()
- for ktype in ['rsa', 'ecdsa', 'dsa']:
- content = VALID_CONTENT[ktype]
- comment = 'user-%s@host' % ktype
- line = ' '.join((ktype, content, comment,))
- key = parser.parse(line)
-
- self.assertEqual(key.base64, content)
- self.assertFalse(key.options)
- self.assertEqual(key.comment, comment)
- self.assertEqual(key.keytype, ktype)
-
- def test_parse_no_comment(self):
- # test key line with key type and base64 only
- parser = ssh_util.AuthKeyLineParser()
- for ktype in ['rsa', 'ecdsa', 'dsa']:
- content = VALID_CONTENT[ktype]
- line = ' '.join((ktype, content,))
- key = parser.parse(line)
-
- self.assertEqual(key.base64, content)
- self.assertFalse(key.options)
- self.assertFalse(key.comment)
- self.assertEqual(key.keytype, ktype)
-
- def test_parse_with_keyoptions(self):
- # test key line with options in it
- parser = ssh_util.AuthKeyLineParser()
- options = TEST_OPTIONS
- for ktype in ['rsa', 'ecdsa', 'dsa']:
- content = VALID_CONTENT[ktype]
- comment = 'user-%s@host' % ktype
- line = ' '.join((options, ktype, content, comment,))
- key = parser.parse(line)
-
- self.assertEqual(key.base64, content)
- self.assertEqual(key.options, options)
- self.assertEqual(key.comment, comment)
- self.assertEqual(key.keytype, ktype)
-
- def test_parse_with_options_passed_in(self):
- # test key line with key type and base64 only
- parser = ssh_util.AuthKeyLineParser()
-
- baseline = ' '.join(("rsa", VALID_CONTENT['rsa'], "user@host"))
- myopts = "no-port-forwarding,no-agent-forwarding"
-
- key = parser.parse("allowedopt" + " " + baseline)
- self.assertEqual(key.options, "allowedopt")
-
- key = parser.parse("overridden_opt " + baseline, options=myopts)
- self.assertEqual(key.options, myopts)
-
- def test_parse_invalid_keytype(self):
- parser = ssh_util.AuthKeyLineParser()
- key = parser.parse(' '.join(["badkeytype", VALID_CONTENT['rsa']]))
-
- self.assertFalse(key.valid())
-
-
-class TestParseSSHConfig(test_helpers.TestCase):
-
- def setUp(self):
- self.load_file_patch = patch('cloudinit.ssh_util.util.load_file')
- self.load_file = self.load_file_patch.start()
- self.isfile_patch = patch('cloudinit.ssh_util.os.path.isfile')
- self.isfile = self.isfile_patch.start()
- self.isfile.return_value = True
-
- def tearDown(self):
- self.load_file_patch.stop()
- self.isfile_patch.stop()
-
- def test_not_a_file(self):
- self.isfile.return_value = False
- self.load_file.side_effect = IOError
- ret = ssh_util.parse_ssh_config('not a real file')
- self.assertEqual([], ret)
-
- def test_empty_file(self):
- self.load_file.return_value = ''
- ret = ssh_util.parse_ssh_config('some real file')
- self.assertEqual([], ret)
-
- def test_comment_line(self):
- comment_line = '# This is a comment'
- self.load_file.return_value = comment_line
- ret = ssh_util.parse_ssh_config('some real file')
- self.assertEqual(1, len(ret))
- self.assertEqual(comment_line, ret[0].line)
-
- def test_blank_lines(self):
- lines = ['', '\t', ' ']
- self.load_file.return_value = '\n'.join(lines)
- ret = ssh_util.parse_ssh_config('some real file')
- self.assertEqual(len(lines), len(ret))
- for line in ret:
- self.assertEqual('', line.line)
-
- def test_lower_case_config(self):
- self.load_file.return_value = 'foo bar'
- ret = ssh_util.parse_ssh_config('some real file')
- self.assertEqual(1, len(ret))
- self.assertEqual('foo', ret[0].key)
- self.assertEqual('bar', ret[0].value)
-
- def test_upper_case_config(self):
- self.load_file.return_value = 'Foo Bar'
- ret = ssh_util.parse_ssh_config('some real file')
- self.assertEqual(1, len(ret))
- self.assertEqual('foo', ret[0].key)
- self.assertEqual('Bar', ret[0].value)
-
- def test_lower_case_with_equals(self):
- self.load_file.return_value = 'foo=bar'
- ret = ssh_util.parse_ssh_config('some real file')
- self.assertEqual(1, len(ret))
- self.assertEqual('foo', ret[0].key)
- self.assertEqual('bar', ret[0].value)
-
- def test_upper_case_with_equals(self):
- self.load_file.return_value = 'Foo=bar'
- ret = ssh_util.parse_ssh_config('some real file')
- self.assertEqual(1, len(ret))
- self.assertEqual('foo', ret[0].key)
- self.assertEqual('bar', ret[0].value)
-
-# vi: ts=4 expandtab
diff --git a/tests/unittests/test_templating.py b/tests/unittests/test_templating.py
deleted file mode 100644
index 94b6e061..00000000
--- a/tests/unittests/test_templating.py
+++ /dev/null
@@ -1,119 +0,0 @@
-# vi: ts=4 expandtab
-#
-# Copyright (C) 2014 Yahoo! Inc.
-#
-# Author: Joshua Harlow <harlowja@yahoo-inc.com>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 3, as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-from __future__ import print_function
-
-from . import helpers as test_helpers
-import textwrap
-
-from cloudinit import templater
-
-try:
- import Cheetah
- HAS_CHEETAH = True
- Cheetah # make pyflakes happy, as Cheetah is not used here
-except ImportError:
- HAS_CHEETAH = False
-
-
-class TestTemplates(test_helpers.TestCase):
- def test_render_basic(self):
- in_data = textwrap.dedent("""
- ${b}
-
- c = d
- """)
- in_data = in_data.strip()
- expected_data = textwrap.dedent("""
- 2
-
- c = d
- """)
- out_data = templater.basic_render(in_data, {'b': 2})
- self.assertEqual(expected_data.strip(), out_data)
-
- @test_helpers.skipIf(not HAS_CHEETAH, 'cheetah renderer not available')
- def test_detection(self):
- blob = "## template:cheetah"
-
- (template_type, renderer, contents) = templater.detect_template(blob)
- self.assertIn("cheetah", template_type)
- self.assertEqual("", contents.strip())
-
- blob = "blahblah $blah"
- (template_type, renderer, contents) = templater.detect_template(blob)
- self.assertIn("cheetah", template_type)
- self.assertEqual(blob, contents)
-
- blob = '##template:something-new'
- self.assertRaises(ValueError, templater.detect_template, blob)
-
- def test_render_cheetah(self):
- blob = '''## template:cheetah
-$a,$b'''
- c = templater.render_string(blob, {"a": 1, "b": 2})
- self.assertEqual("1,2", c)
-
- def test_render_jinja(self):
- blob = '''## template:jinja
-{{a}},{{b}}'''
- c = templater.render_string(blob, {"a": 1, "b": 2})
- self.assertEqual("1,2", c)
-
- def test_render_default(self):
- blob = '''$a,$b'''
- c = templater.render_string(blob, {"a": 1, "b": 2})
- self.assertEqual("1,2", c)
-
- def test_render_basic_deeper(self):
- hn = 'myfoohost.yahoo.com'
- expected_data = "h=%s\nc=d\n" % hn
- in_data = "h=$hostname.canonical_name\nc=d\n"
- params = {
- "hostname": {
- "canonical_name": hn,
- },
- }
- out_data = templater.render_string(in_data, params)
- self.assertEqual(expected_data, out_data)
-
- def test_render_basic_no_parens(self):
- hn = "myfoohost"
- in_data = "h=$hostname\nc=d\n"
- expected_data = "h=%s\nc=d\n" % hn
- out_data = templater.basic_render(in_data, {'hostname': hn})
- self.assertEqual(expected_data, out_data)
-
- def test_render_basic_parens(self):
- hn = "myfoohost"
- in_data = "h = ${hostname}\nc=d\n"
- expected_data = "h = %s\nc=d\n" % hn
- out_data = templater.basic_render(in_data, {'hostname': hn})
- self.assertEqual(expected_data, out_data)
-
- def test_render_basic2(self):
- mirror = "mymirror"
- codename = "zany"
- in_data = "deb $mirror $codename-updates main contrib non-free"
- ex_data = "deb %s %s-updates main contrib non-free" % (mirror,
- codename)
-
- out_data = templater.basic_render(in_data,
- {'mirror': mirror,
- 'codename': codename})
- self.assertEqual(ex_data, out_data)
diff --git a/tests/unittests/test_util.py b/tests/unittests/test_util.py
deleted file mode 100644
index 37a984ac..00000000
--- a/tests/unittests/test_util.py
+++ /dev/null
@@ -1,489 +0,0 @@
-from __future__ import print_function
-
-import logging
-import os
-import shutil
-import stat
-import tempfile
-
-import six
-import yaml
-
-from cloudinit import importer, util
-from . import helpers
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-
-
-class FakeSelinux(object):
-
- def __init__(self, match_what):
- self.match_what = match_what
- self.restored = []
-
- def matchpathcon(self, path, mode):
- if path == self.match_what:
- return
- else:
- raise OSError("No match!")
-
- def is_selinux_enabled(self):
- return True
-
- def restorecon(self, path, recursive):
- self.restored.append(path)
-
-
-class TestGetCfgOptionListOrStr(helpers.TestCase):
- def test_not_found_no_default(self):
- """None is returned if key is not found and no default given."""
- config = {}
- result = util.get_cfg_option_list(config, "key")
- self.assertEqual(None, result)
-
- def test_not_found_with_default(self):
- """Default is returned if key is not found."""
- config = {}
- result = util.get_cfg_option_list(config, "key", default=["DEFAULT"])
- self.assertEqual(["DEFAULT"], result)
-
- def test_found_with_default(self):
- """Default is not returned if key is found."""
- config = {"key": ["value1"]}
- result = util.get_cfg_option_list(config, "key", default=["DEFAULT"])
- self.assertEqual(["value1"], result)
-
- def test_found_convert_to_list(self):
- """Single string is converted to one element list."""
- config = {"key": "value1"}
- result = util.get_cfg_option_list(config, "key")
- self.assertEqual(["value1"], result)
-
- def test_value_is_none(self):
- """If value is None empty list is returned."""
- config = {"key": None}
- result = util.get_cfg_option_list(config, "key")
- self.assertEqual([], result)
-
-
-class TestWriteFile(helpers.TestCase):
- def setUp(self):
- super(TestWriteFile, self).setUp()
- self.tmp = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp)
-
- def test_basic_usage(self):
- """Verify basic usage with default args."""
- path = os.path.join(self.tmp, "NewFile.txt")
- contents = "Hey there"
-
- util.write_file(path, contents)
-
- self.assertTrue(os.path.exists(path))
- self.assertTrue(os.path.isfile(path))
- with open(path) as f:
- create_contents = f.read()
- self.assertEqual(contents, create_contents)
- file_stat = os.stat(path)
- self.assertEqual(0o644, stat.S_IMODE(file_stat.st_mode))
-
- def test_dir_is_created_if_required(self):
- """Verifiy that directories are created is required."""
- dirname = os.path.join(self.tmp, "subdir")
- path = os.path.join(dirname, "NewFile.txt")
- contents = "Hey there"
-
- util.write_file(path, contents)
-
- self.assertTrue(os.path.isdir(dirname))
- self.assertTrue(os.path.isfile(path))
-
- def test_custom_mode(self):
- """Verify custom mode works properly."""
- path = os.path.join(self.tmp, "NewFile.txt")
- contents = "Hey there"
-
- util.write_file(path, contents, mode=0o666)
-
- self.assertTrue(os.path.exists(path))
- self.assertTrue(os.path.isfile(path))
- file_stat = os.stat(path)
- self.assertEqual(0o666, stat.S_IMODE(file_stat.st_mode))
-
- def test_custom_omode(self):
- """Verify custom omode works properly."""
- path = os.path.join(self.tmp, "NewFile.txt")
- contents = "Hey there"
-
- # Create file first with basic content
- with open(path, "wb") as f:
- f.write(b"LINE1\n")
- util.write_file(path, contents, omode="a")
-
- self.assertTrue(os.path.exists(path))
- self.assertTrue(os.path.isfile(path))
- with open(path) as f:
- create_contents = f.read()
- self.assertEqual("LINE1\nHey there", create_contents)
-
- def test_restorecon_if_possible_is_called(self):
- """Make sure the selinux guard is called correctly."""
- my_file = os.path.join(self.tmp, "my_file")
- with open(my_file, "w") as fp:
- fp.write("My Content")
-
- fake_se = FakeSelinux(my_file)
-
- with mock.patch.object(importer, 'import_module',
- return_value=fake_se) as mockobj:
- with util.SeLinuxGuard(my_file) as is_on:
- self.assertTrue(is_on)
-
- self.assertEqual(1, len(fake_se.restored))
- self.assertEqual(my_file, fake_se.restored[0])
-
- mockobj.assert_called_once_with('selinux')
-
-
-class TestDeleteDirContents(helpers.TestCase):
- def setUp(self):
- super(TestDeleteDirContents, self).setUp()
- self.tmp = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp)
-
- def assertDirEmpty(self, dirname):
- self.assertEqual([], os.listdir(dirname))
-
- def test_does_not_delete_dir(self):
- """Ensure directory itself is not deleted."""
- util.delete_dir_contents(self.tmp)
-
- self.assertTrue(os.path.isdir(self.tmp))
- self.assertDirEmpty(self.tmp)
-
- def test_deletes_files(self):
- """Single file should be deleted."""
- with open(os.path.join(self.tmp, "new_file.txt"), "wb") as f:
- f.write(b"DELETE ME")
-
- util.delete_dir_contents(self.tmp)
-
- self.assertDirEmpty(self.tmp)
-
- def test_deletes_empty_dirs(self):
- """Empty directories should be deleted."""
- os.mkdir(os.path.join(self.tmp, "new_dir"))
-
- util.delete_dir_contents(self.tmp)
-
- self.assertDirEmpty(self.tmp)
-
- def test_deletes_nested_dirs(self):
- """Nested directories should be deleted."""
- os.mkdir(os.path.join(self.tmp, "new_dir"))
- os.mkdir(os.path.join(self.tmp, "new_dir", "new_subdir"))
-
- util.delete_dir_contents(self.tmp)
-
- self.assertDirEmpty(self.tmp)
-
- def test_deletes_non_empty_dirs(self):
- """Non-empty directories should be deleted."""
- os.mkdir(os.path.join(self.tmp, "new_dir"))
- f_name = os.path.join(self.tmp, "new_dir", "new_file.txt")
- with open(f_name, "wb") as f:
- f.write(b"DELETE ME")
-
- util.delete_dir_contents(self.tmp)
-
- self.assertDirEmpty(self.tmp)
-
- def test_deletes_symlinks(self):
- """Symlinks should be deleted."""
- file_name = os.path.join(self.tmp, "new_file.txt")
- link_name = os.path.join(self.tmp, "new_file_link.txt")
- with open(file_name, "wb") as f:
- f.write(b"DELETE ME")
- os.symlink(file_name, link_name)
-
- util.delete_dir_contents(self.tmp)
-
- self.assertDirEmpty(self.tmp)
-
-
-class TestKeyValStrings(helpers.TestCase):
- def test_keyval_str_to_dict(self):
- expected = {'1': 'one', '2': 'one+one', 'ro': True}
- cmdline = "1=one ro 2=one+one"
- self.assertEqual(expected, util.keyval_str_to_dict(cmdline))
-
-
-class TestGetCmdline(helpers.TestCase):
- def test_cmdline_reads_debug_env(self):
- os.environ['DEBUG_PROC_CMDLINE'] = 'abcd 123'
- self.assertEqual(os.environ['DEBUG_PROC_CMDLINE'], util.get_cmdline())
-
-
-class TestLoadYaml(helpers.TestCase):
- mydefault = "7b03a8ebace993d806255121073fed52"
-
- def test_simple(self):
- mydata = {'1': "one", '2': "two"}
- self.assertEqual(util.load_yaml(yaml.dump(mydata)), mydata)
-
- def test_nonallowed_returns_default(self):
- # for now, anything not in the allowed list just returns the default.
- myyaml = yaml.dump({'1': "one"})
- self.assertEqual(util.load_yaml(blob=myyaml,
- default=self.mydefault,
- allowed=(str,)),
- self.mydefault)
-
- def test_bogus_returns_default(self):
- badyaml = "1\n 2:"
- self.assertEqual(util.load_yaml(blob=badyaml,
- default=self.mydefault),
- self.mydefault)
-
- def test_unsafe_types(self):
- # should not load complex types
- unsafe_yaml = yaml.dump((1, 2, 3,))
- self.assertEqual(util.load_yaml(blob=unsafe_yaml,
- default=self.mydefault),
- self.mydefault)
-
- def test_python_unicode(self):
- # complex type of python/unicode is explicitly allowed
- myobj = {'1': six.text_type("FOOBAR")}
- safe_yaml = yaml.dump(myobj)
- self.assertEqual(util.load_yaml(blob=safe_yaml,
- default=self.mydefault),
- myobj)
-
-
-class TestMountinfoParsing(helpers.ResourceUsingTestCase):
- def test_invalid_mountinfo(self):
- line = ("20 1 252:1 / / rw,relatime - ext4 /dev/mapper/vg0-root"
- "rw,errors=remount-ro,data=ordered")
- elements = line.split()
- for i in range(len(elements) + 1):
- lines = [' '.join(elements[0:i])]
- if i < 10:
- expected = None
- else:
- expected = ('/dev/mapper/vg0-root', 'ext4', '/')
- self.assertEqual(expected, util.parse_mount_info('/', lines))
-
- def test_precise_ext4_root(self):
-
- lines = self.readResource('mountinfo_precise_ext4.txt').splitlines()
-
- expected = ('/dev/mapper/vg0-root', 'ext4', '/')
- self.assertEqual(expected, util.parse_mount_info('/', lines))
- self.assertEqual(expected, util.parse_mount_info('/usr', lines))
- self.assertEqual(expected, util.parse_mount_info('/usr/bin', lines))
-
- expected = ('/dev/md0', 'ext4', '/boot')
- self.assertEqual(expected, util.parse_mount_info('/boot', lines))
- self.assertEqual(expected, util.parse_mount_info('/boot/grub', lines))
-
- expected = ('/dev/mapper/vg0-root', 'ext4', '/')
- self.assertEqual(expected, util.parse_mount_info('/home', lines))
- self.assertEqual(expected, util.parse_mount_info('/home/me', lines))
-
- expected = ('tmpfs', 'tmpfs', '/run')
- self.assertEqual(expected, util.parse_mount_info('/run', lines))
-
- expected = ('none', 'tmpfs', '/run/lock')
- self.assertEqual(expected, util.parse_mount_info('/run/lock', lines))
-
- def test_raring_btrfs_root(self):
- lines = self.readResource('mountinfo_raring_btrfs.txt').splitlines()
-
- expected = ('/dev/vda1', 'btrfs', '/')
- self.assertEqual(expected, util.parse_mount_info('/', lines))
- self.assertEqual(expected, util.parse_mount_info('/usr', lines))
- self.assertEqual(expected, util.parse_mount_info('/usr/bin', lines))
- self.assertEqual(expected, util.parse_mount_info('/boot', lines))
- self.assertEqual(expected, util.parse_mount_info('/boot/grub', lines))
-
- expected = ('/dev/vda1', 'btrfs', '/home')
- self.assertEqual(expected, util.parse_mount_info('/home', lines))
- self.assertEqual(expected, util.parse_mount_info('/home/me', lines))
-
- expected = ('tmpfs', 'tmpfs', '/run')
- self.assertEqual(expected, util.parse_mount_info('/run', lines))
-
- expected = ('none', 'tmpfs', '/run/lock')
- self.assertEqual(expected, util.parse_mount_info('/run/lock', lines))
-
-
-class TestReadDMIData(helpers.FilesystemMockingTestCase):
-
- def setUp(self):
- super(TestReadDMIData, self).setUp()
- self.new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.new_root)
- self.patchOS(self.new_root)
- self.patchUtils(self.new_root)
-
- def _create_sysfs_parent_directory(self):
- util.ensure_dir(os.path.join('sys', 'class', 'dmi', 'id'))
-
- def _create_sysfs_file(self, key, content):
- """Mocks the sys path found on Linux systems."""
- self._create_sysfs_parent_directory()
- dmi_key = "/sys/class/dmi/id/{0}".format(key)
- util.write_file(dmi_key, content)
-
- def _configure_dmidecode_return(self, key, content, error=None):
- """
- In order to test a missing sys path and call outs to dmidecode, this
- function fakes the results of dmidecode to test the results.
- """
- def _dmidecode_subp(cmd):
- if cmd[-1] != key:
- raise util.ProcessExecutionError()
- return (content, error)
-
- self.patched_funcs.enter_context(
- mock.patch.object(util, 'which', lambda _: True))
- self.patched_funcs.enter_context(
- mock.patch.object(util, 'subp', _dmidecode_subp))
-
- def patch_mapping(self, new_mapping):
- self.patched_funcs.enter_context(
- mock.patch('cloudinit.util.DMIDECODE_TO_DMI_SYS_MAPPING',
- new_mapping))
-
- def test_sysfs_used_with_key_in_mapping_and_file_on_disk(self):
- self.patch_mapping({'mapped-key': 'mapped-value'})
- expected_dmi_value = 'sys-used-correctly'
- self._create_sysfs_file('mapped-value', expected_dmi_value)
- self._configure_dmidecode_return('mapped-key', 'wrong-wrong-wrong')
- self.assertEqual(expected_dmi_value, util.read_dmi_data('mapped-key'))
-
- def test_dmidecode_used_if_no_sysfs_file_on_disk(self):
- self.patch_mapping({})
- self._create_sysfs_parent_directory()
- expected_dmi_value = 'dmidecode-used'
- self._configure_dmidecode_return('use-dmidecode', expected_dmi_value)
- self.assertEqual(expected_dmi_value,
- util.read_dmi_data('use-dmidecode'))
-
- def test_none_returned_if_neither_source_has_data(self):
- self.patch_mapping({})
- self._configure_dmidecode_return('key', 'value')
- self.assertEqual(None, util.read_dmi_data('expect-fail'))
-
- def test_none_returned_if_dmidecode_not_in_path(self):
- self.patched_funcs.enter_context(
- mock.patch.object(util, 'which', lambda _: False))
- self.patch_mapping({})
- self.assertEqual(None, util.read_dmi_data('expect-fail'))
-
- def test_dots_returned_instead_of_foxfox(self):
- # uninitialized dmi values show as \xff, return those as .
- my_len = 32
- dmi_value = b'\xff' * my_len + b'\n'
- expected = ""
- dmi_key = 'system-product-name'
- sysfs_key = 'product_name'
- self._create_sysfs_file(sysfs_key, dmi_value)
- self.assertEqual(expected, util.read_dmi_data(dmi_key))
-
-
-class TestMultiLog(helpers.FilesystemMockingTestCase):
-
- def _createConsole(self, root):
- os.mkdir(os.path.join(root, 'dev'))
- open(os.path.join(root, 'dev', 'console'), 'a').close()
-
- def setUp(self):
- super(TestMultiLog, self).setUp()
- self.root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.root)
- self.patchOS(self.root)
- self.patchUtils(self.root)
- self.patchOpen(self.root)
- self.stdout = six.StringIO()
- self.stderr = six.StringIO()
- self.patchStdoutAndStderr(self.stdout, self.stderr)
-
- def test_stderr_used_by_default(self):
- logged_string = 'test stderr output'
- util.multi_log(logged_string)
- self.assertEqual(logged_string, self.stderr.getvalue())
-
- def test_stderr_not_used_if_false(self):
- util.multi_log('should not see this', stderr=False)
- self.assertEqual('', self.stderr.getvalue())
-
- def test_logs_go_to_console_by_default(self):
- self._createConsole(self.root)
- logged_string = 'something very important'
- util.multi_log(logged_string)
- self.assertEqual(logged_string, open('/dev/console').read())
-
- def test_logs_dont_go_to_stdout_if_console_exists(self):
- self._createConsole(self.root)
- util.multi_log('something')
- self.assertEqual('', self.stdout.getvalue())
-
- def test_logs_go_to_stdout_if_console_does_not_exist(self):
- logged_string = 'something very important'
- util.multi_log(logged_string)
- self.assertEqual(logged_string, self.stdout.getvalue())
-
- def test_logs_go_to_log_if_given(self):
- log = mock.MagicMock()
- logged_string = 'something very important'
- util.multi_log(logged_string, log=log)
- self.assertEqual([((mock.ANY, logged_string), {})],
- log.log.call_args_list)
-
- def test_newlines_stripped_from_log_call(self):
- log = mock.MagicMock()
- expected_string = 'something very important'
- util.multi_log('{0}\n'.format(expected_string), log=log)
- self.assertEqual((mock.ANY, expected_string), log.log.call_args[0])
-
- def test_log_level_defaults_to_debug(self):
- log = mock.MagicMock()
- util.multi_log('message', log=log)
- self.assertEqual((logging.DEBUG, mock.ANY), log.log.call_args[0])
-
- def test_given_log_level_used(self):
- log = mock.MagicMock()
- log_level = mock.Mock()
- util.multi_log('message', log=log, log_level=log_level)
- self.assertEqual((log_level, mock.ANY), log.log.call_args[0])
-
-
-class TestMessageFromString(helpers.TestCase):
-
- def test_unicode_not_messed_up(self):
- roundtripped = util.message_from_string(u'\n').as_string()
- self.assertNotIn('\x00', roundtripped)
-
-
-class TestReadSeeded(helpers.TestCase):
- def setUp(self):
- super(TestReadSeeded, self).setUp()
- self.tmp = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self.tmp)
-
- def test_unicode_not_messed_up(self):
- ud = b"userdatablob"
- helpers.populate_dir(
- self.tmp, {'meta-data': "key1: val1", 'user-data': ud})
- sdir = self.tmp + os.path.sep
- (found_md, found_ud) = util.read_seeded(sdir)
-
- self.assertEqual(found_md, {'key1': 'val1'})
- self.assertEqual(found_ud, ud)
-
-# vi: ts=4 expandtab
diff --git a/tests/unittests/test_vmware_config_file.py b/tests/unittests/test_vmware_config_file.py
deleted file mode 100644
index d5c7367b..00000000
--- a/tests/unittests/test_vmware_config_file.py
+++ /dev/null
@@ -1,103 +0,0 @@
-# vi: ts=4 expandtab
-#
-# Copyright (C) 2015 Canonical Ltd.
-# Copyright (C) 2016 VMware INC.
-#
-# Author: Sankar Tanguturi <stanguturi@vmware.com>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 3, as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-import logging
-import sys
-import unittest
-
-from cloudinit.sources.helpers.vmware.imc.boot_proto import BootProtoEnum
-from cloudinit.sources.helpers.vmware.imc.config import Config
-from cloudinit.sources.helpers.vmware.imc.config_file import ConfigFile
-
-logging.basicConfig(level=logging.DEBUG, stream=sys.stdout)
-logger = logging.getLogger(__name__)
-
-
-class TestVmwareConfigFile(unittest.TestCase):
-
- def test_utility_methods(self):
- cf = ConfigFile("tests/data/vmware/cust-dhcp-2nic.cfg")
-
- cf.clear()
-
- self.assertEqual(0, len(cf), "clear size")
-
- cf._insertKey(" PASSWORD|-PASS ", " foo ")
- cf._insertKey("BAR", " ")
-
- self.assertEqual(2, len(cf), "insert size")
- self.assertEqual('foo', cf["PASSWORD|-PASS"], "password")
- self.assertTrue("PASSWORD|-PASS" in cf, "hasPassword")
- self.assertFalse(cf.should_keep_current_value("PASSWORD|-PASS"),
- "keepPassword")
- self.assertFalse(cf.should_remove_current_value("PASSWORD|-PASS"),
- "removePassword")
- self.assertFalse("FOO" in cf, "hasFoo")
- self.assertTrue(cf.should_keep_current_value("FOO"), "keepFoo")
- self.assertFalse(cf.should_remove_current_value("FOO"), "removeFoo")
- self.assertTrue("BAR" in cf, "hasBar")
- self.assertFalse(cf.should_keep_current_value("BAR"), "keepBar")
- self.assertTrue(cf.should_remove_current_value("BAR"), "removeBar")
-
- def test_configfile_static_2nics(self):
- cf = ConfigFile("tests/data/vmware/cust-static-2nic.cfg")
-
- conf = Config(cf)
-
- self.assertEqual('myhost1', conf.host_name, "hostName")
- self.assertEqual('Africa/Abidjan', conf.timezone, "tz")
- self.assertTrue(conf.utc, "utc")
-
- self.assertEqual(['10.20.145.1', '10.20.145.2'],
- conf.name_servers,
- "dns")
- self.assertEqual(['eng.vmware.com', 'proxy.vmware.com'],
- conf.dns_suffixes,
- "suffixes")
-
- nics = conf.nics
- ipv40 = nics[0].staticIpv4
-
- self.assertEqual(2, len(nics), "nics")
- self.assertEqual('NIC1', nics[0].name, "nic0")
- self.assertEqual('00:50:56:a6:8c:08', nics[0].mac, "mac0")
- self.assertEqual(BootProtoEnum.STATIC, nics[0].bootProto, "bootproto0")
- self.assertEqual('10.20.87.154', ipv40[0].ip, "ipv4Addr0")
- self.assertEqual('255.255.252.0', ipv40[0].netmask, "ipv4Mask0")
- self.assertEqual(2, len(ipv40[0].gateways), "ipv4Gw0")
- self.assertEqual('10.20.87.253', ipv40[0].gateways[0], "ipv4Gw0_0")
- self.assertEqual('10.20.87.105', ipv40[0].gateways[1], "ipv4Gw0_1")
-
- self.assertEqual(1, len(nics[0].staticIpv6), "ipv6Cnt0")
- self.assertEqual('fc00:10:20:87::154',
- nics[0].staticIpv6[0].ip,
- "ipv6Addr0")
-
- self.assertEqual('NIC2', nics[1].name, "nic1")
- self.assertTrue(not nics[1].staticIpv6, "ipv61 dhcp")
-
- def test_config_file_dhcp_2nics(self):
- cf = ConfigFile("tests/data/vmware/cust-dhcp-2nic.cfg")
-
- conf = Config(cf)
- nics = conf.nics
- self.assertEqual(2, len(nics), "nics")
- self.assertEqual('NIC1', nics[0].name, "nic0")
- self.assertEqual('00:50:56:a6:8c:08', nics[0].mac, "mac0")
- self.assertEqual(BootProtoEnum.DHCP, nics[0].bootProto, "bootproto0")