summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorƁukasz 'sil2100' Zemczak <lukasz.zemczak@ubuntu.com>2017-05-18 19:58:02 +0200
committerusd-importer <ubuntu-server@lists.ubuntu.com>2017-05-31 09:53:12 +0000
commit4fb0b5a09b26135ade285844da5d7dfe582a8d4c (patch)
tree09b1e5867d6e7501118cdd0af0012b51fc216530 /tests
parent473ad6fbfe0b9c3b362b530492928303f2b4c7f3 (diff)
downloadvyos-walinuxagent-4fb0b5a09b26135ade285844da5d7dfe582a8d4c.tar.gz
vyos-walinuxagent-4fb0b5a09b26135ade285844da5d7dfe582a8d4c.zip
Import patches-unapplied version 2.2.12-0ubuntu1 to ubuntu/artful-proposed
Imported using git-ubuntu import. Changelog parent: 473ad6fbfe0b9c3b362b530492928303f2b4c7f3 New changelog entries: * New upstream release (LP: #1690854). - Refreshed debian/patches/disable_import_test.patch.
Diffstat (limited to 'tests')
-rw-r--r--tests/common/osutil/test_default.py79
-rw-r--r--tests/common/test_conf.py61
-rw-r--r--tests/daemon/test_daemon.py27
-rw-r--r--tests/data/events/1478123456789000.tld1
-rw-r--r--tests/data/events/1478123456789001.tld1
-rw-r--r--tests/data/events/1479766858966718.tld1
-rw-r--r--tests/data/ext/sample_ext-1.2.0.zip (renamed from tests/data/ext/sample_ext.zip)bin878 -> 878 bytes
-rw-r--r--tests/data/ext/sample_ext-1.2.0/HandlerManifest.json (renamed from tests/data/ext/sample_ext/HandlerManifest.json)0
-rwxr-xr-xtests/data/ext/sample_ext-1.2.0/sample.py (renamed from tests/data/ext/sample_ext/sample.py)0
-rw-r--r--tests/data/ga/WALinuxAgent-2.2.11.zipbin0 -> 450878 bytes
-rw-r--r--tests/data/ga/WALinuxAgent-2.2.8.zipbin415285 -> 0 bytes
-rw-r--r--tests/data/ga/supported.json8
-rw-r--r--tests/data/metadata/vmagent_manifest1.json20
-rw-r--r--tests/data/metadata/vmagent_manifest2.json20
-rw-r--r--tests/data/metadata/vmagent_manifests.json7
-rw-r--r--tests/data/metadata/vmagent_manifests_invalid1.json10
-rw-r--r--tests/data/metadata/vmagent_manifests_invalid2.json10
-rw-r--r--tests/data/test_waagent.conf111
-rw-r--r--tests/ga/test_extension.py105
-rw-r--r--tests/ga/test_update.py233
-rw-r--r--tests/pa/test_deprovision.py108
-rw-r--r--tests/pa/test_provision.py48
-rw-r--r--tests/protocol/mockwiredata.py2
-rw-r--r--tests/protocol/test_hostplugin.py4
-rw-r--r--tests/protocol/test_metadata.py124
-rw-r--r--tests/protocol/test_wire.py53
-rw-r--r--tests/test_agent.py92
-rw-r--r--tests/utils/test_file_util.py30
28 files changed, 1082 insertions, 73 deletions
diff --git a/tests/common/osutil/test_default.py b/tests/common/osutil/test_default.py
index 933787b..87acc60 100644
--- a/tests/common/osutil/test_default.py
+++ b/tests/common/osutil/test_default.py
@@ -18,8 +18,11 @@
import socket
import glob
import mock
+
import azurelinuxagent.common.osutil.default as osutil
import azurelinuxagent.common.utils.shellutil as shellutil
+from azurelinuxagent.common.exception import OSUtilError
+from azurelinuxagent.common.future import ustr
from azurelinuxagent.common.osutil import get_osutil
from azurelinuxagent.common.utils import fileutil
from tests.tools import *
@@ -40,6 +43,50 @@ class TestOSUtil(AgentTestCase):
self.assertEqual(run_patch.call_count, retries)
self.assertEqual(run_patch.call_args_list[0][0][0], 'ifdown {0} && ifup {0}'.format(ifname))
+ def test_get_dvd_device_success(self):
+ with patch.object(os, 'listdir', return_value=['cpu', 'cdrom0']):
+ osutil.DefaultOSUtil().get_dvd_device()
+
+ def test_get_dvd_device_failure(self):
+ with patch.object(os, 'listdir', return_value=['cpu', 'notmatching']):
+ try:
+ osutil.DefaultOSUtil().get_dvd_device()
+ self.fail('OSUtilError was not raised')
+ except OSUtilError as ose:
+ self.assertTrue('notmatching' in ustr(ose))
+
+ @patch('time.sleep')
+ def test_mount_dvd_success(self, _):
+ msg = 'message'
+ with patch.object(osutil.DefaultOSUtil,
+ 'get_dvd_device',
+ return_value='/dev/cdrom'):
+ with patch.object(shellutil,
+ 'run_get_output',
+ return_value=(0, msg)) as patch_run:
+ with patch.object(os, 'makedirs'):
+ try:
+ osutil.DefaultOSUtil().mount_dvd()
+ except OSUtilError:
+ self.fail("mounting failed")
+
+ @patch('time.sleep')
+ def test_mount_dvd_failure(self, _):
+ msg = 'message'
+ with patch.object(osutil.DefaultOSUtil,
+ 'get_dvd_device',
+ return_value='/dev/cdrom'):
+ with patch.object(shellutil,
+ 'run_get_output',
+ return_value=(1, msg)) as patch_run:
+ with patch.object(os, 'makedirs'):
+ try:
+ osutil.DefaultOSUtil().mount_dvd()
+ self.fail('OSUtilError was not raised')
+ except OSUtilError as ose:
+ self.assertTrue(msg in ustr(ose))
+ self.assertTrue(patch_run.call_count == 6)
+
def test_get_first_if(self):
ifname, ipaddr = osutil.DefaultOSUtil().get_first_if()
self.assertTrue(ifname.startswith('eth'))
@@ -315,5 +362,37 @@ Match host 192.168.1.2\n\
conf.get_sshd_conf_file_path(),
expected_output)
+ @patch('os.path.isfile', return_value=True)
+ @patch('azurelinuxagent.common.utils.fileutil.read_file',
+ return_value="B9F3C233-9913-9F42-8EB3-BA656DF32502")
+ def test_get_instance_id_from_file(self, mock_read, mock_isfile):
+ util = osutil.DefaultOSUtil()
+ self.assertEqual(
+ "B9F3C233-9913-9F42-8EB3-BA656DF32502",
+ util.get_instance_id())
+
+ @patch('os.path.isfile', return_value=False)
+ @patch('azurelinuxagent.common.utils.shellutil.run_get_output',
+ return_value=[0, 'B9F3C233-9913-9F42-8EB3-BA656DF32502'])
+ def test_get_instance_id_from_dmidecode(self, mock_shell, mock_isfile):
+ util = osutil.DefaultOSUtil()
+ self.assertEqual(
+ "B9F3C233-9913-9F42-8EB3-BA656DF32502",
+ util.get_instance_id())
+
+ @patch('os.path.isfile', return_value=False)
+ @patch('azurelinuxagent.common.utils.shellutil.run_get_output',
+ return_value=[1, 'Error Value'])
+ def test_get_instance_id_missing(self, mock_shell, mock_isfile):
+ util = osutil.DefaultOSUtil()
+ self.assertEqual("", util.get_instance_id())
+
+ @patch('os.path.isfile', return_value=False)
+ @patch('azurelinuxagent.common.utils.shellutil.run_get_output',
+ return_value=[0, 'Unexpected Value'])
+ def test_get_instance_id_unexpected(self, mock_shell, mock_isfile):
+ util = osutil.DefaultOSUtil()
+ self.assertEqual("", util.get_instance_id())
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/common/test_conf.py b/tests/common/test_conf.py
new file mode 100644
index 0000000..1287b0d
--- /dev/null
+++ b/tests/common/test_conf.py
@@ -0,0 +1,61 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+
+import mock
+import os.path
+
+from azurelinuxagent.common.conf import *
+
+from tests.tools import *
+
+
+class TestConf(AgentTestCase):
+ def setUp(self):
+ AgentTestCase.setUp(self)
+ self.conf = ConfigurationProvider()
+ load_conf_from_file(
+ os.path.join(data_dir, "test_waagent.conf"),
+ self.conf)
+
+ def test_key_value_handling(self):
+ self.assertEqual("Value1", self.conf.get("FauxKey1", "Bad"))
+ self.assertEqual("Value2 Value2", self.conf.get("FauxKey2", "Bad"))
+
+ def test_get_ssh_dir(self):
+ self.assertTrue(get_ssh_dir(self.conf).startswith("/notareal/path"))
+
+ def test_get_sshd_conf_file_path(self):
+ self.assertTrue(get_sshd_conf_file_path(
+ self.conf).startswith("/notareal/path"))
+
+ def test_get_ssh_key_glob(self):
+ self.assertTrue(get_ssh_key_glob(
+ self.conf).startswith("/notareal/path"))
+
+ def test_get_ssh_key_private_path(self):
+ self.assertTrue(get_ssh_key_private_path(
+ self.conf).startswith("/notareal/path"))
+
+ def test_get_ssh_key_public_path(self):
+ self.assertTrue(get_ssh_key_public_path(
+ self.conf).startswith("/notareal/path"))
+
+ def test_get_fips_enabled(self):
+ self.assertTrue(get_fips_enabled(self.conf))
+
+ def test_get_provision_cloudinit(self):
+ self.assertTrue(get_provision_cloudinit(self.conf))
diff --git a/tests/daemon/test_daemon.py b/tests/daemon/test_daemon.py
index dd31fd7..5694dc9 100644
--- a/tests/daemon/test_daemon.py
+++ b/tests/daemon/test_daemon.py
@@ -14,7 +14,9 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-from azurelinuxagent.daemon import get_daemon_handler
+
+from azurelinuxagent.daemon import *
+from azurelinuxagent.daemon.main import OPENSSL_FIPS_ENVIRONMENT
from tests.tools import *
@@ -30,8 +32,9 @@ class MockDaemonCall(object):
self.daemon_handler.running = False
raise Exception("Mock unhandled exception")
-@patch("time.sleep")
class TestDaemon(AgentTestCase):
+
+ @patch("time.sleep")
def test_daemon_restart(self, mock_sleep):
#Mock daemon function
daemon_handler = get_daemon_handler()
@@ -45,6 +48,7 @@ class TestDaemon(AgentTestCase):
mock_sleep.assert_any_call(15)
self.assertEquals(2, daemon_handler.daemon.call_count)
+ @patch("time.sleep")
@patch("azurelinuxagent.daemon.main.conf")
@patch("azurelinuxagent.daemon.main.sys.exit")
def test_check_pid(self, mock_exit, mock_conf, mock_sleep):
@@ -58,6 +62,25 @@ class TestDaemon(AgentTestCase):
daemon_handler.check_pid()
mock_exit.assert_any_call(0)
+
+ @patch("azurelinuxagent.daemon.main.DaemonHandler.check_pid")
+ @patch("azurelinuxagent.common.conf.get_fips_enabled", return_value=True)
+ def test_set_openssl_fips(self, mock_conf, mock_daemon):
+ daemon_handler = get_daemon_handler()
+ daemon_handler.running = False
+ with patch.dict("os.environ"):
+ daemon_handler.run()
+ self.assertTrue(OPENSSL_FIPS_ENVIRONMENT in os.environ)
+ self.assertEqual('1', os.environ[OPENSSL_FIPS_ENVIRONMENT])
+
+ @patch("azurelinuxagent.daemon.main.DaemonHandler.check_pid")
+ @patch("azurelinuxagent.common.conf.get_fips_enabled", return_value=False)
+ def test_does_not_set_openssl_fips(self, mock_conf, mock_daemon):
+ daemon_handler = get_daemon_handler()
+ daemon_handler.running = False
+ with patch.dict("os.environ"):
+ daemon_handler.run()
+ self.assertFalse(OPENSSL_FIPS_ENVIRONMENT in os.environ)
if __name__ == '__main__':
unittest.main()
diff --git a/tests/data/events/1478123456789000.tld b/tests/data/events/1478123456789000.tld
new file mode 100644
index 0000000..a689f4c
--- /dev/null
+++ b/tests/data/events/1478123456789000.tld
@@ -0,0 +1 @@
+{"eventId": 1, "providerId": "69B669B9-4AF8-4C50-BDC4-6006FA76E975", "parameters": [{"name": "Name", "value": "Test Event"}, {"name": "Version", "value": "2.2.0"}, {"name": "IsInternal", "value": false}, {"name": "Operation", "value": "Some Operation"}, {"name": "OperationSuccess", "value": true}, {"name": "Message", "value": ""}, {"name": "Duration", "value": 0}, {"name": "ExtensionType", "value": ""}]} \ No newline at end of file
diff --git a/tests/data/events/1478123456789001.tld b/tests/data/events/1478123456789001.tld
new file mode 100644
index 0000000..95460e3
--- /dev/null
+++ b/tests/data/events/1478123456789001.tld
@@ -0,0 +1 @@
+{"eventId": 1, "providerId": "69B669B9-4AF8-4C50-BDC4-6006FA76E975", "parameters": [{"name": "Name", "value": "Linux Event"}, {"name": "Version", "value": "2.2.0"}, {"name": "IsInternal", "value": false}, {"name": "Operation", "value": "Linux Operation"}, {"name": "OperationSuccess", "value": false}, {"name": "Message", "value": "Linux Message"}, {"name": "Duration", "value": 42}, {"name": "ExtensionType", "value": "Linux Event Type"}]} \ No newline at end of file
diff --git a/tests/data/events/1479766858966718.tld b/tests/data/events/1479766858966718.tld
new file mode 100644
index 0000000..cc7ac67
--- /dev/null
+++ b/tests/data/events/1479766858966718.tld
@@ -0,0 +1 @@
+{"eventId": 1, "providerId": "69B669B9-4AF8-4C50-BDC4-6006FA76E975", "parameters": [{"name": "Name", "value": "WALinuxAgent"}, {"name": "Version", "value": "2.3.0.1"}, {"name": "IsInternal", "value": false}, {"name": "Operation", "value": "Enable"}, {"name": "OperationSuccess", "value": true}, {"name": "Message", "value": "Agent WALinuxAgent-2.3.0.1 launched with command 'python install.py' is successfully running"}, {"name": "Duration", "value": 0}, {"name": "ExtensionType", "value": ""}]} \ No newline at end of file
diff --git a/tests/data/ext/sample_ext.zip b/tests/data/ext/sample_ext-1.2.0.zip
index 08cfaf7..08cfaf7 100644
--- a/tests/data/ext/sample_ext.zip
+++ b/tests/data/ext/sample_ext-1.2.0.zip
Binary files differ
diff --git a/tests/data/ext/sample_ext/HandlerManifest.json b/tests/data/ext/sample_ext-1.2.0/HandlerManifest.json
index 9890d0c..9890d0c 100644
--- a/tests/data/ext/sample_ext/HandlerManifest.json
+++ b/tests/data/ext/sample_ext-1.2.0/HandlerManifest.json
diff --git a/tests/data/ext/sample_ext/sample.py b/tests/data/ext/sample_ext-1.2.0/sample.py
index 74bd839..74bd839 100755
--- a/tests/data/ext/sample_ext/sample.py
+++ b/tests/data/ext/sample_ext-1.2.0/sample.py
diff --git a/tests/data/ga/WALinuxAgent-2.2.11.zip b/tests/data/ga/WALinuxAgent-2.2.11.zip
new file mode 100644
index 0000000..f018116
--- /dev/null
+++ b/tests/data/ga/WALinuxAgent-2.2.11.zip
Binary files differ
diff --git a/tests/data/ga/WALinuxAgent-2.2.8.zip b/tests/data/ga/WALinuxAgent-2.2.8.zip
deleted file mode 100644
index 04c60a8..0000000
--- a/tests/data/ga/WALinuxAgent-2.2.8.zip
+++ /dev/null
Binary files differ
diff --git a/tests/data/ga/supported.json b/tests/data/ga/supported.json
new file mode 100644
index 0000000..2ae3753
--- /dev/null
+++ b/tests/data/ga/supported.json
@@ -0,0 +1,8 @@
+{
+ "ubuntu.16.10-x64": {
+ "versions": [
+ "^Ubuntu,16.10,yakkety$"
+ ],
+ "slice": 10
+ }
+}
diff --git a/tests/data/metadata/vmagent_manifest1.json b/tests/data/metadata/vmagent_manifest1.json
new file mode 100644
index 0000000..544a708
--- /dev/null
+++ b/tests/data/metadata/vmagent_manifest1.json
@@ -0,0 +1,20 @@
+{
+ "versions": [
+ {
+ "version": "2.2.8",
+ "uris": [
+ {
+ "uri": "https: //notused.com/ga/WALinuxAgent-2.2.8.zip"
+ }
+ ]
+ },
+ {
+ "version": "2.2.9",
+ "uris": [
+ {
+ "uri": "https: //notused.com/ga/WALinuxAgent-2.2.9.zip"
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/tests/data/metadata/vmagent_manifest2.json b/tests/data/metadata/vmagent_manifest2.json
new file mode 100644
index 0000000..544a708
--- /dev/null
+++ b/tests/data/metadata/vmagent_manifest2.json
@@ -0,0 +1,20 @@
+{
+ "versions": [
+ {
+ "version": "2.2.8",
+ "uris": [
+ {
+ "uri": "https: //notused.com/ga/WALinuxAgent-2.2.8.zip"
+ }
+ ]
+ },
+ {
+ "version": "2.2.9",
+ "uris": [
+ {
+ "uri": "https: //notused.com/ga/WALinuxAgent-2.2.9.zip"
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/tests/data/metadata/vmagent_manifests.json b/tests/data/metadata/vmagent_manifests.json
new file mode 100644
index 0000000..2628f89
--- /dev/null
+++ b/tests/data/metadata/vmagent_manifests.json
@@ -0,0 +1,7 @@
+{
+ "versionsManifestUris" :
+ [
+ { "uri" : "https://notused.com/vmagent_manifest1.json" },
+ { "uri" : "https://notused.com/vmagent_manifest2.json" }
+ ]
+}
diff --git a/tests/data/metadata/vmagent_manifests_invalid1.json b/tests/data/metadata/vmagent_manifests_invalid1.json
new file mode 100644
index 0000000..55b08d1
--- /dev/null
+++ b/tests/data/metadata/vmagent_manifests_invalid1.json
@@ -0,0 +1,10 @@
+{
+ "notTheRightKey": [
+ {
+ "uri": "https://notused.com/vmagent_manifest1.json"
+ },
+ {
+ "uri": "https://notused.com/vmagent_manifest2.json"
+ }
+ ]
+} \ No newline at end of file
diff --git a/tests/data/metadata/vmagent_manifests_invalid2.json b/tests/data/metadata/vmagent_manifests_invalid2.json
new file mode 100644
index 0000000..5df4252
--- /dev/null
+++ b/tests/data/metadata/vmagent_manifests_invalid2.json
@@ -0,0 +1,10 @@
+{
+ "notTheRightKey": [
+ {
+ "foo": "https://notused.com/vmagent_manifest1.json"
+ },
+ {
+ "bar": "https://notused.com/vmagent_manifest2.json"
+ }
+ ]
+} \ No newline at end of file
diff --git a/tests/data/test_waagent.conf b/tests/data/test_waagent.conf
new file mode 100644
index 0000000..6368c39
--- /dev/null
+++ b/tests/data/test_waagent.conf
@@ -0,0 +1,111 @@
+#
+# Microsoft Azure Linux Agent Configuration
+#
+
+# Key / value handling test entries
+=Value0
+FauxKey1= Value1
+FauxKey2=Value2 Value2
+
+# Enable instance creation
+Provisioning.Enabled=y
+
+# Rely on cloud-init to provision
+Provisioning.UseCloudInit=y
+
+# Password authentication for root account will be unavailable.
+Provisioning.DeleteRootPassword=y
+
+# Generate fresh host key pair.
+Provisioning.RegenerateSshHostKeyPair=y
+
+# Supported values are "rsa", "dsa" and "ecdsa".
+Provisioning.SshHostKeyPairType=rsa
+
+# Monitor host name changes and publish changes via DHCP requests.
+Provisioning.MonitorHostName=y
+
+# Decode CustomData from Base64.
+Provisioning.DecodeCustomData=n
+
+# Execute CustomData after provisioning.
+Provisioning.ExecuteCustomData=n
+
+# Algorithm used by crypt when generating password hash.
+#Provisioning.PasswordCryptId=6
+
+# Length of random salt used when generating password hash.
+#Provisioning.PasswordCryptSaltLength=10
+
+# Allow reset password of sys user
+Provisioning.AllowResetSysUser=n
+
+# Format if unformatted. If 'n', resource disk will not be mounted.
+ResourceDisk.Format=y
+
+# File system on the resource disk
+# Typically ext3 or ext4. FreeBSD images should use 'ufs2' here.
+ResourceDisk.Filesystem=ext4
+
+# Mount point for the resource disk
+ResourceDisk.MountPoint=/mnt/resource
+
+# Create and use swapfile on resource disk.
+ResourceDisk.EnableSwap=n
+
+# Size of the swapfile.
+ResourceDisk.SwapSizeMB=0
+
+# Comma-seperated list of mount options. See man(8) for valid options.
+ResourceDisk.MountOptions=None
+
+# Enable verbose logging (y|n)
+Logs.Verbose=n
+
+# Is FIPS enabled
+OS.EnableFIPS=y
+
+# Root device timeout in seconds.
+OS.RootDeviceScsiTimeout=300
+
+# If "None", the system default version is used.
+OS.OpensslPath=None
+
+# Set the path to SSH keys and configuration files
+OS.SshDir=/notareal/path
+
+# If set, agent will use proxy server to access internet
+#HttpProxy.Host=None
+#HttpProxy.Port=None
+
+# Detect Scvmm environment, default is n
+# DetectScvmmEnv=n
+
+#
+# Lib.Dir=/var/lib/waagent
+
+#
+# DVD.MountPoint=/mnt/cdrom/secure
+
+#
+# Pid.File=/var/run/waagent.pid
+
+#
+# Extension.LogDir=/var/log/azure
+
+#
+# Home.Dir=/home
+
+# Enable RDMA management and set up, should only be used in HPC images
+# OS.EnableRDMA=y
+
+# Enable or disable goal state processing auto-update, default is enabled
+# AutoUpdate.Enabled=y
+
+# Determine the update family, this should not be changed
+# AutoUpdate.GAFamily=Prod
+
+# Determine if the overprovisioning feature is enabled. If yes, hold extension
+# handling until inVMArtifactsProfile.OnHold is false.
+# Default is disabled
+# EnableOverProvisioning=n
diff --git a/tests/ga/test_extension.py b/tests/ga/test_extension.py
index 1df0a04..2a60ea3 100644
--- a/tests/ga/test_extension.py
+++ b/tests/ga/test_extension.py
@@ -15,6 +15,14 @@
# Requires Python 2.4+ and Openssl 1.0+
#
+import glob
+import os
+import os.path
+import shutil
+import tempfile
+import zipfile
+
+import azurelinuxagent.common.conf as conf
import azurelinuxagent.common.utils.fileutil as fileutil
from tests.protocol.mockwiredata import *
@@ -30,6 +38,103 @@ from azurelinuxagent.common.protocol.restapi import ExtHandlerStatus, \
from azurelinuxagent.ga.exthandlers import *
from azurelinuxagent.common.protocol.wire import WireProtocol
+class TestExtensionCleanup(AgentTestCase):
+ def setUp(self):
+ AgentTestCase.setUp(self)
+ self.ext_handlers = ExtHandlersHandler()
+ self.lib_dir = tempfile.mkdtemp()
+
+ def _install_handlers(self, start=0, count=1,
+ handler_state=ExtHandlerState.Installed):
+ src = os.path.join(data_dir, "ext", "sample_ext-1.2.0.zip")
+ version = FlexibleVersion("1.2.0")
+ version += start - version.patch
+
+ for i in range(start, start+count):
+ eh = ExtHandler()
+ eh.name = "sample_ext"
+ eh.properties.version = str(version)
+ handler = ExtHandlerInstance(eh, "unused")
+
+ dst = os.path.join(self.lib_dir,
+ handler.get_full_name()+HANDLER_PKG_EXT)
+ shutil.copy(src, dst)
+
+ if not handler_state is None:
+ zipfile.ZipFile(dst).extractall(handler.get_base_dir())
+ handler.set_handler_state(handler_state)
+
+ version += 1
+
+ def _count_packages(self):
+ return len(glob.glob(os.path.join(self.lib_dir, "*.zip")))
+
+ def _count_installed(self):
+ paths = os.listdir(self.lib_dir)
+ paths = [os.path.join(self.lib_dir, p) for p in paths]
+ return len([p for p in paths
+ if os.path.isdir(p) and self._is_installed(p)])
+
+ def _count_uninstalled(self):
+ paths = os.listdir(self.lib_dir)
+ paths = [os.path.join(self.lib_dir, p) for p in paths]
+ return len([p for p in paths
+ if os.path.isdir(p) and not self._is_installed(p)])
+
+ def _is_installed(self, path):
+ path = os.path.join(path, 'config', 'HandlerState')
+ return fileutil.read_file(path) != "NotInstalled"
+
+ @patch("azurelinuxagent.common.conf.get_lib_dir")
+ def test_cleanup_leaves_installed_extensions(self, mock_conf):
+ mock_conf.return_value = self.lib_dir
+
+ self._install_handlers(start=0, count=5, handler_state=ExtHandlerState.Installed)
+ self._install_handlers(start=5, count=5, handler_state=ExtHandlerState.Enabled)
+
+ self.assertEqual(self._count_packages(), 10)
+ self.assertEqual(self._count_installed(), 10)
+
+ self.ext_handlers.cleanup_outdated_handlers()
+
+ self.assertEqual(self._count_packages(), 10)
+ self.assertEqual(self._count_installed(), 10)
+ self.assertEqual(self._count_uninstalled(), 0)
+
+ @patch("azurelinuxagent.common.conf.get_lib_dir")
+ def test_cleanup_removes_uninstalled_extensions(self, mock_conf):
+ mock_conf.return_value = self.lib_dir
+
+ self._install_handlers(start=0, count=5, handler_state=ExtHandlerState.Installed)
+ self._install_handlers(start=5, count=5, handler_state=ExtHandlerState.NotInstalled)
+
+ self.assertEqual(self._count_packages(), 10)
+ self.assertEqual(self._count_installed(), 5)
+ self.assertEqual(self._count_uninstalled(), 5)
+
+ self.ext_handlers.cleanup_outdated_handlers()
+
+ self.assertEqual(self._count_packages(), 5)
+ self.assertEqual(self._count_installed(), 5)
+ self.assertEqual(self._count_uninstalled(), 0)
+
+ @patch("azurelinuxagent.common.conf.get_lib_dir")
+ def test_cleanup_removes_orphaned_packages(self, mock_conf):
+ mock_conf.return_value = self.lib_dir
+
+ self._install_handlers(start=0, count=5, handler_state=ExtHandlerState.Installed)
+ self._install_handlers(start=5, count=5, handler_state=None)
+
+ self.assertEqual(self._count_packages(), 10)
+ self.assertEqual(self._count_installed(), 5)
+ self.assertEqual(self._count_uninstalled(), 0)
+
+ self.ext_handlers.cleanup_outdated_handlers()
+
+ self.assertEqual(self._count_packages(), 5)
+ self.assertEqual(self._count_installed(), 5)
+ self.assertEqual(self._count_uninstalled(), 0)
+
class TestHandlerStateMigration(AgentTestCase):
def setUp(self):
AgentTestCase.setUp(self)
diff --git a/tests/ga/test_update.py b/tests/ga/test_update.py
index e7a7af4..a83db95 100644
--- a/tests/ga/test_update.py
+++ b/tests/ga/test_update.py
@@ -17,9 +17,16 @@
from __future__ import print_function
+from datetime import datetime
+
+import json
+import shutil
+
from azurelinuxagent.common.protocol.hostplugin import *
from azurelinuxagent.common.protocol.wire import *
+from azurelinuxagent.common.utils.fileutil import *
from azurelinuxagent.ga.update import *
+
from tests.tools import *
NO_ERROR = {
@@ -28,6 +35,18 @@ NO_ERROR = {
"was_fatal" : False
}
+FATAL_ERROR = {
+ "last_failure" : 42.42,
+ "failure_count" : 2,
+ "was_fatal" : True
+}
+
+SENTINEL_ERROR = {
+ "last_failure" : 0.0,
+ "failure_count" : 0,
+ "was_fatal" : True
+}
+
WITH_ERROR = {
"last_failure" : 42.42,
"failure_count" : 2,
@@ -137,19 +156,25 @@ class UpdateTestCase(AgentTestCase):
fileutil.copy_file(agent, to_dir=self.tmp_dir)
return
- def expand_agents(self):
+ def expand_agents(self, mark_test=False):
for agent in self.agent_pkgs():
- zipfile.ZipFile(agent).extractall(os.path.join(
- self.tmp_dir,
- fileutil.trim_ext(agent, "zip")))
+ path = os.path.join(self.tmp_dir, fileutil.trim_ext(agent, "zip"))
+ zipfile.ZipFile(agent).extractall(path)
+ if mark_test:
+ src = os.path.join(data_dir, 'ga', 'supported.json')
+ dst = os.path.join(path, 'supported.json')
+ shutil.copy(src, dst)
+
+ dst = os.path.join(path, 'error.json')
+ fileutil.write_file(dst, json.dumps(SENTINEL_ERROR))
return
- def prepare_agent(self, version):
+ def prepare_agent(self, version, mark_test=False):
"""
Create a download for the current agent version, copied from test data
"""
self.copy_agents(get_agent_pkgs()[0])
- self.expand_agents()
+ self.expand_agents(mark_test=mark_test)
versions = self.agent_versions()
src_v = FlexibleVersion(str(versions[0]))
@@ -214,6 +239,64 @@ class UpdateTestCase(AgentTestCase):
return dst_v
+class TestSupportedDistribution(UpdateTestCase):
+ def setUp(self):
+ UpdateTestCase.setUp(self)
+ self.sd = SupportedDistribution({
+ 'slice':10,
+ 'versions': ['^Ubuntu,16.10,yakkety$']})
+
+
+ def test_creation(self):
+ self.assertRaises(TypeError, SupportedDistribution)
+ self.assertRaises(UpdateError, SupportedDistribution, None)
+
+ self.assertEqual(self.sd.slice, 10)
+ self.assertEqual(self.sd.versions, ['^Ubuntu,16.10,yakkety$'])
+
+ @patch('platform.linux_distribution')
+ def test_is_supported(self, mock_dist):
+ mock_dist.return_value = ['Ubuntu', '16.10', 'yakkety']
+ self.assertTrue(self.sd.is_supported)
+
+ mock_dist.return_value = ['something', 'else', 'entirely']
+ self.assertFalse(self.sd.is_supported)
+
+ @patch('azurelinuxagent.ga.update.datetime')
+ def test_in_slice(self, mock_dt):
+ mock_dt.utcnow = Mock(return_value=datetime(2017, 1, 1, 0, 0, 5))
+ self.assertTrue(self.sd.in_slice)
+
+ mock_dt.utcnow = Mock(return_value=datetime(2017, 1, 1, 0, 0, 42))
+ self.assertFalse(self.sd.in_slice)
+
+
+class TestSupported(UpdateTestCase):
+ def setUp(self):
+ UpdateTestCase.setUp(self)
+ self.sp = Supported(os.path.join(data_dir, 'ga', 'supported.json'))
+
+ def test_creation(self):
+ self.assertRaises(TypeError, Supported)
+ self.assertRaises(UpdateError, Supported, None)
+
+ @patch('platform.linux_distribution')
+ def test_is_supported(self, mock_dist):
+ mock_dist.return_value = ['Ubuntu', '16.10', 'yakkety']
+ self.assertTrue(self.sp.is_supported)
+
+ mock_dist.return_value = ['something', 'else', 'entirely']
+ self.assertFalse(self.sp.is_supported)
+
+ @patch('platform.linux_distribution', return_value=['Ubuntu', '16.10', 'yakkety'])
+ @patch('azurelinuxagent.ga.update.datetime')
+ def test_in_slice(self, mock_dt, mock_dist):
+ mock_dt.utcnow = Mock(return_value=datetime(2017, 1, 1, 0, 0, 5))
+ self.assertTrue(self.sp.in_slice)
+
+ mock_dt.utcnow = Mock(return_value=datetime(2017, 1, 1, 0, 0, 42))
+ self.assertFalse(self.sp.in_slice)
+
class TestGuestAgentError(UpdateTestCase):
def test_creation(self):
self.assertRaises(TypeError, GuestAgentError)
@@ -241,6 +324,17 @@ class TestGuestAgentError(UpdateTestCase):
self.assertEqual(NO_ERROR["was_fatal"], err.was_fatal)
return
+ def test_is_sentinel(self):
+ with self.get_error_file(error_data=SENTINEL_ERROR) as path:
+ err = GuestAgentError(path.name)
+ self.assertTrue(err.is_blacklisted)
+ self.assertTrue(err.is_sentinel)
+
+ with self.get_error_file(error_data=FATAL_ERROR) as path:
+ err = GuestAgentError(path.name)
+ self.assertTrue(err.is_blacklisted)
+ self.assertFalse(err.is_sentinel)
+
def test_load_preserves_error_state(self):
with self.get_error_file(error_data=WITH_ERROR) as path:
err = GuestAgentError(path.name)
@@ -274,15 +368,6 @@ class TestGuestAgentError(UpdateTestCase):
# Agent failed >= MAX_FAILURE, it should be blacklisted
self.assertTrue(err.is_blacklisted)
self.assertEqual(MAX_FAILURE, err.failure_count)
-
- # Clear old failure does not clear recent failure
- err.clear_old_failure()
- self.assertTrue(err.is_blacklisted)
-
- # Clear does remove old, outdated failures
- err.last_failure -= RETAIN_INTERVAL * 2
- err.clear_old_failure()
- self.assertFalse(err.is_blacklisted)
return
def test_mark_failure_permanent(self):
@@ -334,6 +419,9 @@ class TestGuestAgent(UpdateTestCase):
self.assertEqual(get_agent_name(), agent.name)
self.assertEqual(get_agent_version(), agent.version)
+ self.assertFalse(agent.is_test)
+ self.assertFalse(agent.in_slice)
+
self.assertEqual(self.agent_path, agent.get_agent_dir())
path = os.path.join(self.agent_path, AGENT_MANIFEST_FILE)
@@ -403,6 +491,48 @@ class TestGuestAgent(UpdateTestCase):
self.assertTrue(agent.is_downloaded)
return
+ @patch('platform.linux_distribution', return_value=['Ubuntu', '16.10', 'yakkety'])
+ def test_is_test(self, mock_dist):
+ self.expand_agents(mark_test=True)
+ agent = GuestAgent(path=self.agent_path)
+
+ self.assertTrue(agent.is_blacklisted)
+ self.assertTrue(agent.is_test)
+
+ @patch('platform.linux_distribution', return_value=['Ubuntu', '16.10', 'yakkety'])
+ @patch('azurelinuxagent.ga.update.datetime')
+ def test_in_slice(self, mock_dt, mock_dist):
+ self.expand_agents(mark_test=True)
+ agent = GuestAgent(path=self.agent_path)
+
+ mock_dt.utcnow = Mock(return_value=datetime(2017, 1, 1, 0, 0, 5))
+ self.assertTrue(agent.in_slice)
+
+ mock_dt.utcnow = Mock(return_value=datetime(2017, 1, 1, 0, 0, 42))
+ self.assertFalse(agent.in_slice)
+
+ @patch('platform.linux_distribution', return_value=['Ubuntu', '16.10', 'yakkety'])
+ @patch('azurelinuxagent.ga.update.datetime')
+ def test_enable(self, mock_dt, mock_dist):
+ mock_dt.utcnow = Mock(return_value=datetime(2017, 1, 1, 0, 0, 5))
+
+ self.expand_agents(mark_test=True)
+ agent = GuestAgent(path=self.agent_path)
+
+ self.assertTrue(agent.is_blacklisted)
+ self.assertTrue(agent.is_test)
+ self.assertTrue(agent.in_slice)
+
+ agent.enable()
+
+ self.assertFalse(agent.is_blacklisted)
+ self.assertFalse(agent.is_test)
+
+ # Ensure the new state is preserved to disk
+ agent = GuestAgent(path=self.agent_path)
+ self.assertFalse(agent.is_blacklisted)
+ self.assertFalse(agent.is_test)
+
@patch("azurelinuxagent.ga.update.GuestAgent._ensure_downloaded")
def test_mark_failure(self, mock_ensure):
agent = GuestAgent(path=self.agent_path)
@@ -933,6 +1063,14 @@ class TestUpdate(UpdateTestCase):
self.assertEqual("1250_waagent.pid", os.path.basename(pid_file))
return
+ @patch('platform.linux_distribution', return_value=['Ubuntu', '16.10', 'yakkety'])
+ @patch('azurelinuxagent.ga.update.datetime')
+ def test_get_test_agent(self, mock_dt, mock_dist):
+ mock_dt.utcnow = Mock(return_value=datetime(2017, 1, 1, 0, 0, 5))
+ self.prepare_agent(AGENT_VERSION, mark_test=True)
+
+ self.assertNotEqual(None, self.update_handler.get_test_agent())
+
def test_is_clean_start_returns_true_when_no_sentinal(self):
self.assertFalse(os.path.isfile(self.update_handler._sentinal_file_path()))
self.assertTrue(self.update_handler._is_clean_start)
@@ -972,27 +1110,27 @@ class TestUpdate(UpdateTestCase):
self.assertTrue(self.update_handler._is_orphaned)
return
- def test_load_agents(self):
+ def test_find_agents(self):
self.prepare_agents()
self.assertTrue(0 <= len(self.update_handler.agents))
- self.update_handler._load_agents()
+ self.update_handler._find_agents()
self.assertEqual(len(get_agents(self.tmp_dir)), len(self.update_handler.agents))
return
- def test_load_agents_does_reload(self):
+ def test_find_agents_does_reload(self):
self.prepare_agents()
- self.update_handler._load_agents()
+ self.update_handler._find_agents()
agents = self.update_handler.agents
- self.update_handler._load_agents()
+ self.update_handler._find_agents()
self.assertNotEqual(agents, self.update_handler.agents)
return
- def test_load_agents_sorts(self):
+ def test_find_agents_sorts(self):
self.prepare_agents()
- self.update_handler._load_agents()
+ self.update_handler._find_agents()
v = FlexibleVersion("100000")
for a in self.update_handler.agents:
@@ -1002,7 +1140,7 @@ class TestUpdate(UpdateTestCase):
def test_purge_agents(self):
self.prepare_agents()
- self.update_handler._load_agents()
+ self.update_handler._find_agents()
# Ensure at least three agents initially exist
self.assertTrue(2 < len(self.update_handler.agents))
@@ -1014,7 +1152,7 @@ class TestUpdate(UpdateTestCase):
# Reload and assert only the kept agents remain on disk
self.update_handler.agents = kept_agents
self.update_handler._purge_agents()
- self.update_handler._load_agents()
+ self.update_handler._find_agents()
self.assertEqual(
[agent.version for agent in kept_agents],
[agent.version for agent in self.update_handler.agents])
@@ -1032,7 +1170,7 @@ class TestUpdate(UpdateTestCase):
self.assertTrue(os.path.exists(agent_path + ".zip"))
return
- def _test_run_latest(self, mock_child=None, mock_time=None):
+ def _test_run_latest(self, mock_child=None, mock_time=None, child_args=None):
if mock_child is None:
mock_child = ChildMock()
if mock_time is None:
@@ -1041,7 +1179,7 @@ class TestUpdate(UpdateTestCase):
with patch('subprocess.Popen', return_value=mock_child) as mock_popen:
with patch('time.time', side_effect=mock_time.time):
with patch('time.sleep', side_effect=mock_time.sleep):
- self.update_handler.run_latest()
+ self.update_handler.run_latest(child_args=child_args)
self.assertEqual(1, mock_popen.call_count)
return mock_popen.call_args
@@ -1051,16 +1189,32 @@ class TestUpdate(UpdateTestCase):
agent = self.update_handler.get_latest_agent()
args, kwargs = self._test_run_latest()
+ args = args[0]
cmds = textutil.safe_shlex_split(agent.get_agent_cmd())
if cmds[0].lower() == "python":
cmds[0] = get_python_cmd()
- self.assertEqual(args[0], cmds)
+ self.assertEqual(args, cmds)
+ self.assertTrue(len(args) > 1)
+ self.assertTrue(args[0].startswith("python"))
+ self.assertEqual("-run-exthandlers", args[len(args)-1])
self.assertEqual(True, 'cwd' in kwargs)
self.assertEqual(agent.get_agent_dir(), kwargs['cwd'])
self.assertEqual(False, '\x00' in cmds[0])
return
+ def test_run_latest_passes_child_args(self):
+ self.prepare_agents()
+
+ agent = self.update_handler.get_latest_agent()
+ args, kwargs = self._test_run_latest(child_args="AnArgument")
+ args = args[0]
+
+ self.assertTrue(len(args) > 1)
+ self.assertTrue(args[0].startswith("python"))
+ self.assertEqual("AnArgument", args[len(args)-1])
+ return
+
def test_run_latest_polls_and_waits_for_success(self):
mock_child = ChildMock(return_value=None)
mock_time = TimeMock(time_increment=CHILD_HEALTH_INTERVAL/3)
@@ -1147,7 +1301,8 @@ class TestUpdate(UpdateTestCase):
with patch('azurelinuxagent.ga.update.UpdateHandler.get_latest_agent', return_value=latest_agent):
self._test_run_latest(mock_child=ChildMock(return_value=1))
- self.assertTrue(latest_agent.is_available)
+ self.assertTrue(latest_agent.is_blacklisted)
+ self.assertFalse(latest_agent.is_available)
self.assertNotEqual(0.0, latest_agent.error.last_failure)
self.assertEqual(1, latest_agent.error.failure_count)
return
@@ -1198,8 +1353,6 @@ class TestUpdate(UpdateTestCase):
self.update_handler.running = False
return
- calls = calls * invocations
-
fileutil.write_file(conf.get_agent_pid_file_path(), ustr(42))
with patch('azurelinuxagent.ga.exthandlers.get_exthandlers_handler') as mock_handler:
@@ -1227,13 +1380,30 @@ class TestUpdate(UpdateTestCase):
return
def test_run_keeps_running(self):
- self._test_run(invocations=15)
+ self._test_run(invocations=15, calls=[call.run()]*15)
return
def test_run_stops_if_update_available(self):
self.update_handler._upgrade_available = Mock(return_value=True)
self._test_run(invocations=0, calls=[], enable_updates=True)
return
+
+ @patch('platform.linux_distribution', return_value=['Ubuntu', '16.10', 'yakkety'])
+ @patch('azurelinuxagent.ga.update.datetime')
+ def test_run_stops_if_test_agent_available(self, mock_dt, mock_dist):
+ mock_dt.utcnow = Mock(return_value=datetime(2017, 1, 1, 0, 0, 5))
+ self.prepare_agent(AGENT_VERSION, mark_test=True)
+
+ agent = GuestAgent(path=self.agent_dir(AGENT_VERSION))
+ agent.enable = Mock()
+ self.assertTrue(agent.is_test)
+ self.assertTrue(agent.in_slice)
+
+ with patch('azurelinuxagent.ga.update.UpdateHandler.get_test_agent',
+ return_value=agent) as mock_test:
+ self._test_run(invocations=0)
+ self.assertEqual(mock_test.call_count, 1)
+ self.assertEqual(agent.enable.call_count, 1)
def test_run_stops_if_orphaned(self):
with patch('os.getppid', return_value=1):
@@ -1417,6 +1587,5 @@ class TimeMock(Mock):
self.next_time += self.time_increment
return current_time
-
if __name__ == '__main__':
unittest.main()
diff --git a/tests/pa/test_deprovision.py b/tests/pa/test_deprovision.py
index be34915..c4cd9b4 100644
--- a/tests/pa/test_deprovision.py
+++ b/tests/pa/test_deprovision.py
@@ -15,11 +15,117 @@
# Requires Python 2.4+ and Openssl 1.0+
#
-from tests.tools import *
+import tempfile
+
+import azurelinuxagent.common.utils.fileutil as fileutil
+
from azurelinuxagent.pa.deprovision import get_deprovision_handler
+from azurelinuxagent.pa.deprovision.default import DeprovisionHandler
+from tests.tools import *
class TestDeprovision(AgentTestCase):
+ @patch("azurelinuxagent.pa.deprovision.default.DeprovisionHandler.cloud_init_dirs")
+ @patch("azurelinuxagent.pa.deprovision.default.DeprovisionHandler.cloud_init_files")
+ def test_del_cloud_init_without_once(self,
+ mock_files,
+ mock_dirs):
+ deprovision_handler = get_deprovision_handler("","","")
+ deprovision_handler.del_cloud_init([], [], include_once=False)
+
+ mock_dirs.assert_called_with(include_once=False)
+ mock_files.assert_called_with(include_once=False)
+
+ @patch("signal.signal")
+ @patch("azurelinuxagent.common.protocol.get_protocol_util")
+ @patch("azurelinuxagent.common.osutil.get_osutil")
+ @patch("azurelinuxagent.pa.deprovision.default.DeprovisionHandler.cloud_init_dirs")
+ @patch("azurelinuxagent.pa.deprovision.default.DeprovisionHandler.cloud_init_files")
+ def test_del_cloud_init(self,
+ mock_files,
+ mock_dirs,
+ mock_osutil,
+ mock_util,
+ mock_signal):
+ try:
+ with tempfile.NamedTemporaryFile() as f:
+ warnings = []
+ actions = []
+
+ dirs = [tempfile.mkdtemp()]
+ mock_dirs.return_value = dirs
+
+ files = [f.name]
+ mock_files.return_value = files
+
+ deprovision_handler = get_deprovision_handler("","","")
+ deprovision_handler.del_cloud_init(warnings, actions)
+
+ mock_dirs.assert_called_with(include_once=True)
+ mock_files.assert_called_with(include_once=True)
+
+ self.assertEqual(len(warnings), 0)
+ self.assertEqual(len(actions), 2)
+ for da in actions:
+ if da.func == fileutil.rm_dirs:
+ self.assertEqual(da.args, dirs)
+ elif da.func == fileutil.rm_files:
+ self.assertEqual(da.args, files)
+ else:
+ self.assertTrue(False)
+
+ try:
+ for da in actions:
+ da.invoke()
+ self.assertEqual(len([d for d in dirs if os.path.isdir(d)]), 0)
+ self.assertEqual(len([f for f in files if os.path.isfile(f)]), 0)
+ except Exception as e:
+ self.assertTrue(False, "Exception {0}".format(e))
+ except OSError:
+ # Ignore the error caused by removing the file within the "with"
+ pass
+
+ @distros("ubuntu")
+ @patch('azurelinuxagent.common.conf.get_lib_dir')
+ def test_del_lib_dir_files(self,
+ distro_name,
+ distro_version,
+ distro_full_name,
+ mock_conf):
+ files = [
+ 'HostingEnvironmentConfig.xml',
+ 'Incarnation',
+ 'Protocol',
+ 'SharedConfig.xml',
+ 'WireServerEndpoint',
+ 'Extensions.1.xml',
+ 'ExtensionsConfig.1.xml',
+ 'GoalState.1.xml',
+ 'Extensions.2.xml',
+ 'ExtensionsConfig.2.xml',
+ 'GoalState.2.xml'
+ ]
+
+ tmp = tempfile.mkdtemp()
+ mock_conf.return_value = tmp
+ for f in files:
+ fileutil.write_file(os.path.join(tmp, f), "Value")
+
+ deprovision_handler = get_deprovision_handler(distro_name,
+ distro_version,
+ distro_full_name)
+ warnings = []
+ actions = []
+ deprovision_handler.del_lib_dir_files(warnings, actions)
+
+ self.assertTrue(len(warnings) == 0)
+ self.assertTrue(len(actions) == 1)
+ self.assertEqual(fileutil.rm_files, actions[0].func)
+ self.assertTrue(len(actions[0].args) > 0)
+ for f in actions[0].args:
+ self.assertTrue(os.path.basename(f) in files)
+
+
@distros("redhat")
def test_deprovision(self,
distro_name,
diff --git a/tests/pa/test_provision.py b/tests/pa/test_provision.py
index a98eacd..0446442 100644
--- a/tests/pa/test_provision.py
+++ b/tests/pa/test_provision.py
@@ -16,17 +16,22 @@
#
import azurelinuxagent.common.utils.fileutil as fileutil
+
+from azurelinuxagent.common.exception import ProtocolError
from azurelinuxagent.common.osutil.default import DefaultOSUtil
from azurelinuxagent.common.protocol import OVF_FILE_NAME
from azurelinuxagent.pa.provision import get_provision_handler
+from azurelinuxagent.pa.provision.default import ProvisionHandler
from tests.tools import *
class TestProvision(AgentTestCase):
@distros("redhat")
- def test_provision(self, distro_name, distro_version, distro_full_name):
- provision_handler = get_provision_handler(distro_name, distro_version,
+ @patch('azurelinuxagent.common.osutil.default.DefaultOSUtil.get_instance_id',
+ return_value='B9F3C233-9913-9F42-8EB3-BA656DF32502')
+ def test_provision(self, mock_util, distro_name, distro_version, distro_full_name):
+ provision_handler = get_provision_handler(distro_name, distro_version,
distro_full_name)
mock_osutil = MagicMock()
mock_osutil.decode_customdata = Mock(return_value="")
@@ -48,6 +53,45 @@ class TestProvision(AgentTestCase):
data = DefaultOSUtil().decode_customdata(base64data)
fileutil.write_file(tempfile.mktemp(), data)
+ @patch('os.path.isfile', return_value=False)
+ def test_is_provisioned_not_provisioned(self, mock_isfile):
+ ph = ProvisionHandler()
+ self.assertFalse(ph.is_provisioned())
+
+ @patch('os.path.isfile', return_value=True)
+ @patch('azurelinuxagent.common.utils.fileutil.read_file',
+ return_value="B9F3C233-9913-9F42-8EB3-BA656DF32502")
+ @patch('azurelinuxagent.pa.deprovision.get_deprovision_handler')
+ def test_is_provisioned_is_provisioned(self,
+ mock_deprovision, mock_read, mock_isfile):
+ ph = ProvisionHandler()
+ ph.osutil = Mock()
+ ph.osutil.get_instance_id = \
+ Mock(return_value="B9F3C233-9913-9F42-8EB3-BA656DF32502")
+ ph.write_provisioned = Mock()
+
+ deprovision_handler = Mock()
+ mock_deprovision.return_value = deprovision_handler
+
+ self.assertTrue(ph.is_provisioned())
+ deprovision_handler.run_changed_unique_id.assert_not_called()
+
+ @patch('os.path.isfile', return_value=True)
+ @patch('azurelinuxagent.common.utils.fileutil.read_file',
+ side_effect=["Value"])
+ @patch('azurelinuxagent.pa.deprovision.get_deprovision_handler')
+ def test_is_provisioned_not_deprovisioned(self,
+ mock_deprovision, mock_read, mock_isfile):
+
+ ph = ProvisionHandler()
+ ph.osutil = Mock()
+ ph.write_provisioned = Mock()
+
+ deprovision_handler = Mock()
+ mock_deprovision.return_value = deprovision_handler
+
+ self.assertTrue(ph.is_provisioned())
+ deprovision_handler.run_changed_unique_id.assert_called_once()
if __name__ == '__main__':
unittest.main()
diff --git a/tests/protocol/mockwiredata.py b/tests/protocol/mockwiredata.py
index c789de5..4e45623 100644
--- a/tests/protocol/mockwiredata.py
+++ b/tests/protocol/mockwiredata.py
@@ -30,7 +30,7 @@ DATA_FILE = {
"ga_manifest" : "wire/ga_manifest.xml",
"trans_prv": "wire/trans_prv",
"trans_cert": "wire/trans_cert",
- "test_ext": "ext/sample_ext.zip"
+ "test_ext": "ext/sample_ext-1.2.0.zip"
}
DATA_FILE_NO_EXT = DATA_FILE.copy()
diff --git a/tests/protocol/test_hostplugin.py b/tests/protocol/test_hostplugin.py
index ef91998..e203615 100644
--- a/tests/protocol/test_hostplugin.py
+++ b/tests/protocol/test_hostplugin.py
@@ -33,6 +33,7 @@ import azurelinuxagent.common.protocol.wire as wire
import azurelinuxagent.common.protocol.hostplugin as hostplugin
from azurelinuxagent.common import event
+from azurelinuxagent.common.exception import ProtocolError, HttpError
from azurelinuxagent.common.protocol.hostplugin import API_VERSION
from azurelinuxagent.common.utils import restutil
@@ -128,8 +129,10 @@ class TestHostPlugin(AgentTestCase):
wire_protocol_client.get_goal_state = Mock(return_value=test_goal_state)
wire_protocol_client.ext_conf = wire.ExtensionsConfig(None)
wire_protocol_client.ext_conf.status_upload_blob = sas_url
+ wire_protocol_client.ext_conf.status_upload_blob_type = page_blob_type
wire_protocol_client.status_blob.set_vm_status(status)
wire_protocol_client.upload_status_blob()
+ self.assertEqual(patch_upload.call_count, 1)
self.assertTrue(patch_put.call_count == 1,
"Fallback was not engaged")
self.assertTrue(patch_put.call_args[0][0] == sas_url)
@@ -156,6 +159,7 @@ class TestHostPlugin(AgentTestCase):
client.get_goal_state = Mock(return_value=test_goal_state)
client.ext_conf = wire.ExtensionsConfig(None)
client.ext_conf.status_upload_blob = sas_url
+ client.ext_conf.status_upload_blob_type = page_blob_type
client.status_blob.set_vm_status(status)
client.upload_status_blob()
self.assertTrue(patch_put.call_count == 1,
diff --git a/tests/protocol/test_metadata.py b/tests/protocol/test_metadata.py
index f390f7a..ee4ba3e 100644
--- a/tests/protocol/test_metadata.py
+++ b/tests/protocol/test_metadata.py
@@ -15,14 +15,23 @@
# Requires Python 2.4+ and Openssl 1.0+
#
-from tests.tools import *
-from tests.protocol.mockmetadata import *
+import json
+
+from azurelinuxagent.common.future import ustr
+
from azurelinuxagent.common.utils.restutil import httpclient
-from azurelinuxagent.common.protocol.metadata import MetadataProtocol
+from azurelinuxagent.common.protocol.metadata import *
+from azurelinuxagent.common.protocol.restapi import *
+
+from tests.protocol.mockmetadata import *
+from tests.tools import *
-@patch("time.sleep")
-@patch("azurelinuxagent.common.protocol.metadata.restutil")
class TestMetadataProtocolGetters(AgentTestCase):
+ def load_json(self, path):
+ return json.loads(ustr(load_data(path)), encoding="utf-8")
+
+ @patch("time.sleep")
+ @patch("azurelinuxagent.common.protocol.metadata.restutil")
def _test_getters(self, test_data, mock_restutil ,_):
mock_restutil.http_get.side_effect = test_data.mock_http_get
@@ -43,3 +52,108 @@ class TestMetadataProtocolGetters(AgentTestCase):
self._test_getters(test_data, *args)
+ @patch("azurelinuxagent.common.protocol.metadata.MetadataProtocol.update_goal_state")
+ @patch("azurelinuxagent.common.protocol.metadata.MetadataProtocol._get_data")
+ def test_get_vmagents_manifests(self, mock_get, mock_update):
+ data = self.load_json("metadata/vmagent_manifests.json")
+ mock_get.return_value = data, 42
+
+ protocol = MetadataProtocol()
+ manifests, etag = protocol.get_vmagent_manifests()
+
+ self.assertEqual(mock_update.call_count, 1)
+ self.assertEqual(mock_get.call_count, 1)
+
+ manifests_uri = BASE_URI.format(
+ METADATA_ENDPOINT,
+ "vmAgentVersions",
+ APIVERSION)
+ self.assertEqual(mock_get.call_args[0][0], manifests_uri)
+
+ self.assertEqual(etag, 42)
+ self.assertNotEqual(None, manifests)
+ self.assertEqual(len(manifests.vmAgentManifests), 1)
+
+ manifest = manifests.vmAgentManifests[0]
+ self.assertEqual(manifest.family, conf.get_autoupdate_gafamily())
+ self.assertEqual(len(manifest.versionsManifestUris), 2)
+
+ # Same etag returns the same data
+ data = self.load_json("metadata/vmagent_manifests_invalid1.json")
+ mock_get.return_value = data, 42
+ next_manifests, etag = protocol.get_vmagent_manifests()
+
+ self.assertEqual(etag, 42)
+ self.assertEqual(manifests, next_manifests)
+
+ # New etag returns new data
+ mock_get.return_value = data, 43
+ self.assertRaises(ProtocolError, protocol.get_vmagent_manifests)
+
+ @patch("azurelinuxagent.common.protocol.metadata.MetadataProtocol.update_goal_state")
+ @patch("azurelinuxagent.common.protocol.metadata.MetadataProtocol._get_data")
+ def test_get_vmagents_manifests_raises(self, mock_get, mock_update):
+ data = self.load_json("metadata/vmagent_manifests_invalid1.json")
+ mock_get.return_value = data, 42
+
+ protocol = MetadataProtocol()
+ self.assertRaises(ProtocolError, protocol.get_vmagent_manifests)
+
+ data = self.load_json("metadata/vmagent_manifests_invalid2.json")
+ mock_get.return_value = data, 43
+ self.assertRaises(ProtocolError, protocol.get_vmagent_manifests)
+
+ @patch("azurelinuxagent.common.protocol.metadata.MetadataProtocol.update_goal_state")
+ @patch("azurelinuxagent.common.protocol.metadata.MetadataProtocol._get_data")
+ def test_get_vmagent_pkgs(self, mock_get, mock_update):
+ data = self.load_json("metadata/vmagent_manifests.json")
+ mock_get.return_value = data, 42
+
+ protocol = MetadataProtocol()
+ manifests, etag = protocol.get_vmagent_manifests()
+ manifest = manifests.vmAgentManifests[0]
+
+ data = self.load_json("metadata/vmagent_manifest1.json")
+ mock_get.return_value = data, 42
+ pkgs = protocol.get_vmagent_pkgs(manifest)
+
+ self.assertNotEqual(None, pkgs)
+ self.assertEqual(len(pkgs.versions), 2)
+
+ for pkg in pkgs.versions:
+ self.assertNotEqual(None, pkg.version)
+ self.assertTrue(len(pkg.uris) > 0)
+
+ for uri in pkg.uris:
+ self.assertTrue(uri.uri.endswith("zip"))
+
+ @patch("azurelinuxagent.common.protocol.metadata.MetadataProtocol._post_data")
+ def test_report_event(self, mock_post):
+ events = TelemetryEventList()
+
+ data = self.load_json("events/1478123456789000.tld")
+ event = TelemetryEvent()
+ set_properties("event", event, data)
+ events.events.append(event)
+
+ data = self.load_json("events/1478123456789001.tld")
+ event = TelemetryEvent()
+ set_properties("event", event, data)
+ events.events.append(event)
+
+ data = self.load_json("events/1479766858966718.tld")
+ event = TelemetryEvent()
+ set_properties("event", event, data)
+ events.events.append(event)
+
+ protocol = MetadataProtocol()
+ protocol.report_event(events)
+
+ events_uri = BASE_URI.format(
+ METADATA_ENDPOINT,
+ "status/telemetry",
+ APIVERSION)
+
+ self.assertEqual(mock_post.call_count, 1)
+ self.assertEqual(mock_post.call_args[0][0], events_uri)
+ self.assertEqual(mock_post.call_args[0][1], get_properties(events))
diff --git a/tests/protocol/test_wire.py b/tests/protocol/test_wire.py
index dda7a2b..ba9fc7d 100644
--- a/tests/protocol/test_wire.py
+++ b/tests/protocol/test_wire.py
@@ -152,11 +152,12 @@ class TestWireProtocolGetters(AgentTestCase):
wire_protocol_client = WireProtocol(wireserver_url).client
wire_protocol_client.ext_conf = ExtensionsConfig(None)
wire_protocol_client.ext_conf.status_upload_blob = testurl
+ wire_protocol_client.ext_conf.status_upload_blob_type = testtype
wire_protocol_client.status_blob.vm_status = vmstatus
with patch.object(WireClient, "get_goal_state") as patch_get_goal_state:
with patch.object(HostPluginProtocol, "put_vm_status") as patch_host_ga_plugin_upload:
- with patch.object(StatusBlob, "upload", return_value=True) as patch_default_upload:
+ with patch.object(StatusBlob, "upload") as patch_default_upload:
HostPluginProtocol.set_default_channel(False)
wire_protocol_client.upload_status_blob()
@@ -190,7 +191,25 @@ class TestWireProtocolGetters(AgentTestCase):
self.assertTrue(HostPluginProtocol.is_default_channel())
HostPluginProtocol.set_default_channel(False)
- def test_upload_status_blob_error_reporting(self, *args):
+ def test_upload_status_blob_unknown_type_assumes_block(self, *args):
+ vmstatus = VMStatus(message="Ready", status="Ready")
+ wire_protocol_client = WireProtocol(wireserver_url).client
+ wire_protocol_client.ext_conf = ExtensionsConfig(None)
+ wire_protocol_client.ext_conf.status_upload_blob = testurl
+ wire_protocol_client.ext_conf.status_upload_blob_type = "NotALegalType"
+ wire_protocol_client.status_blob.vm_status = vmstatus
+
+ with patch.object(WireClient, "get_goal_state") as patch_get_goal_state:
+ with patch.object(StatusBlob, "prepare") as patch_prepare:
+ with patch.object(StatusBlob, "upload") as patch_default_upload:
+ HostPluginProtocol.set_default_channel(False)
+ wire_protocol_client.upload_status_blob()
+
+ patch_prepare.assert_called_once_with("BlockBlob")
+ patch_default_upload.assert_called_once_with(testurl)
+ patch_get_goal_state.assert_not_called()
+
+ def test_upload_status_blob_reports_prepare_error(self, *args):
vmstatus = VMStatus(message="Ready", status="Ready")
wire_protocol_client = WireProtocol(wireserver_url).client
wire_protocol_client.ext_conf = ExtensionsConfig(None)
@@ -199,29 +218,13 @@ class TestWireProtocolGetters(AgentTestCase):
wire_protocol_client.status_blob.vm_status = vmstatus
goal_state = GoalState(WireProtocolData(DATA_FILE).goal_state)
- with patch.object(HostPluginProtocol,
- "ensure_initialized",
- return_value=True):
- with patch.object(StatusBlob,
- "put_block_blob",
- side_effect=HttpError("error")):
- with patch.object(StatusBlob,
- "get_blob_type",
- return_value='BlockBlob'):
- with patch.object(HostPluginProtocol,
- "put_vm_status"):
- with patch.object(WireClient,
- "report_blob_type",
- side_effect=MagicMock()):
- with patch.object(event,
- "add_event") as patch_add_event:
- HostPluginProtocol.set_default_channel(False)
- wire_protocol_client.get_goal_state = Mock(return_value=goal_state)
- wire_protocol_client.upload_status_blob()
- wire_protocol_client.get_goal_state.assert_called_once()
- self.assertTrue(patch_add_event.call_count == 1)
- self.assertTrue(patch_add_event.call_args_list[0][1]['op'] == 'ReportStatus')
- self.assertFalse(HostPluginProtocol.is_default_channel())
+ with patch.object(StatusBlob, "prepare",
+ side_effect=Exception) as mock_prepare:
+ with patch.object(WireClient, "report_status_event") as mock_event:
+ wire_protocol_client.upload_status_blob()
+
+ mock_prepare.assert_called_once()
+ mock_event.assert_called_once()
def test_get_in_vm_artifacts_profile_blob_not_available(self, *args):
wire_protocol_client = WireProtocol(wireserver_url).client
diff --git a/tests/test_agent.py b/tests/test_agent.py
new file mode 100644
index 0000000..1b35933
--- /dev/null
+++ b/tests/test_agent.py
@@ -0,0 +1,92 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+
+import mock
+import os.path
+
+from azurelinuxagent.agent import *
+from azurelinuxagent.common.conf import *
+
+from tests.tools import *
+
+
+class TestAgent(AgentTestCase):
+
+ def test_accepts_configuration_path(self):
+ conf_path = os.path.join(data_dir, "test_waagent.conf")
+ c, f, v, cfp = parse_args(["-configuration-path:" + conf_path])
+ self.assertEqual(cfp, conf_path)
+
+ @patch("os.path.exists", return_value=True)
+ def test_checks_configuration_path(self, mock_exists):
+ conf_path = "/foo/bar-baz/something.conf"
+ c, f, v, cfp = parse_args(["-configuration-path:"+conf_path])
+ self.assertEqual(cfp, conf_path)
+ self.assertEqual(mock_exists.call_count, 1)
+
+ @patch("sys.stderr")
+ @patch("os.path.exists", return_value=False)
+ @patch("sys.exit", side_effect=Exception)
+ def test_rejects_missing_configuration_path(self, mock_exit, mock_exists, mock_stderr):
+ try:
+ c, f, v, cfp = parse_args(["-configuration-path:/foo/bar.conf"])
+ self.assertTrue(False)
+ except Exception:
+ self.assertEqual(mock_exit.call_count, 1)
+
+ def test_configuration_path_defaults_to_none(self):
+ c, f, v, cfp = parse_args([])
+ self.assertEqual(cfp, None)
+
+ def test_agent_accepts_configuration_path(self):
+ Agent(False,
+ conf_file_path=os.path.join(data_dir, "test_waagent.conf"))
+ self.assertTrue(conf.get_fips_enabled())
+
+ @patch("azurelinuxagent.common.conf.load_conf_from_file")
+ def test_agent_uses_default_configuration_path(self, mock_load):
+ Agent(False)
+ mock_load.assert_called_once_with("/etc/waagent.conf")
+
+ @patch("azurelinuxagent.daemon.get_daemon_handler")
+ @patch("azurelinuxagent.common.conf.load_conf_from_file")
+ def test_agent_does_not_pass_configuration_path(self,
+ mock_load, mock_handler):
+
+ mock_daemon = Mock()
+ mock_daemon.run = Mock()
+ mock_handler.return_value = mock_daemon
+
+ agent = Agent(False)
+ agent.daemon()
+
+ mock_daemon.run.assert_called_once_with(child_args=None)
+ mock_load.assert_called_once()
+
+ @patch("azurelinuxagent.daemon.get_daemon_handler")
+ @patch("azurelinuxagent.common.conf.load_conf_from_file")
+ def test_agent_passes_configuration_path(self, mock_load, mock_handler):
+
+ mock_daemon = Mock()
+ mock_daemon.run = Mock()
+ mock_handler.return_value = mock_daemon
+
+ agent = Agent(False, conf_file_path="/foo/bar.conf")
+ agent.daemon()
+
+ mock_daemon.run.assert_called_once_with(child_args="-configuration-path:/foo/bar.conf")
+ mock_load.assert_called_once()
diff --git a/tests/utils/test_file_util.py b/tests/utils/test_file_util.py
index 76fb15b..0b92513 100644
--- a/tests/utils/test_file_util.py
+++ b/tests/utils/test_file_util.py
@@ -15,9 +15,14 @@
# Requires Python 2.4+ and Openssl 1.0+
#
+import glob
+import random
+import string
+import tempfile
import uuid
import azurelinuxagent.common.utils.fileutil as fileutil
+
from azurelinuxagent.common.future import ustr
from tests.tools import *
@@ -69,9 +74,6 @@ class TestFileOperations(AgentTestCase):
self.assertEquals('abc', filename)
def test_remove_files(self):
- import random
- import string
- import glob
random_word = lambda : ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(5))
#Create 10 test files
@@ -90,9 +92,27 @@ class TestFileOperations(AgentTestCase):
self.assertEqual(0, len(glob.glob(os.path.join(self.tmp_dir, test_file_pattern))))
self.assertEqual(0, len(glob.glob(os.path.join(self.tmp_dir, test_file_pattern2))))
+ def test_remove_dirs(self):
+ dirs = []
+ for n in range(0,5):
+ dirs.append(tempfile.mkdtemp())
+ for d in dirs:
+ for n in range(0, random.choice(range(0,10))):
+ fileutil.write_file(os.path.join(d, "test"+str(n)), "content")
+ for n in range(0, random.choice(range(0,10))):
+ dd = os.path.join(d, "testd"+str(n))
+ os.mkdir(dd)
+ for nn in range(0, random.choice(range(0,10))):
+ os.symlink(dd, os.path.join(dd, "sym"+str(nn)))
+ for n in range(0, random.choice(range(0,10))):
+ os.symlink(d, os.path.join(d, "sym"+str(n)))
+
+ fileutil.rm_dirs(*dirs)
+
+ for d in dirs:
+ self.assertEqual(len(os.listdir(d)), 0)
+
def test_get_all_files(self):
- import random
- import string
random_word = lambda: ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(5))
# Create 10 test files at the root dir and 10 other in the sub dir