Blame tests/unittests/test_datasource/test_hetzner.py

Packit Service a04d08
# Copyright (C) 2018 Jonas Keidel
Packit Service a04d08
#
Packit Service a04d08
# Author: Jonas Keidel <jonas.keidel@hetzner.com>
Packit Service a04d08
#
Packit Service a04d08
# This file is part of cloud-init. See LICENSE file for license information.
Packit Service a04d08
Packit Service a04d08
from cloudinit.sources import DataSourceHetzner
Packit Service 751c4a
import cloudinit.sources.helpers.hetzner as hc_helper
Packit Service a04d08
from cloudinit import util, settings, helpers
Packit Service a04d08
Packit Service a04d08
from cloudinit.tests.helpers import mock, CiTestCase
Packit Service a04d08
Packit Service 751c4a
import base64
Packit Service 751c4a
import pytest
Packit Service 751c4a
Packit Service a04d08
METADATA = util.load_yaml("""
Packit Service a04d08
hostname: cloudinit-test
Packit Service a04d08
instance-id: 123456
Packit Service a04d08
local-ipv4: ''
Packit Service a04d08
network-config:
Packit Service a04d08
  config:
Packit Service a04d08
  - mac_address: 96:00:00:08:19:da
Packit Service a04d08
    name: eth0
Packit Service a04d08
    subnets:
Packit Service a04d08
    - dns_nameservers:
Packit Service a04d08
      - 213.133.99.99
Packit Service a04d08
      - 213.133.100.100
Packit Service a04d08
      - 213.133.98.98
Packit Service a04d08
      ipv4: true
Packit Service a04d08
      type: dhcp
Packit Service a04d08
    type: physical
Packit Service a04d08
  - name: eth0:0
Packit Service a04d08
    subnets:
Packit Service a04d08
    - address: 2a01:4f8:beef:beef::1/64
Packit Service a04d08
      gateway: fe80::1
Packit Service a04d08
      ipv6: true
Packit Service a04d08
      routes:
Packit Service a04d08
      - gateway: fe80::1%eth0
Packit Service a04d08
        netmask: 0
Packit Service a04d08
        network: '::'
Packit Service a04d08
      type: static
Packit Service a04d08
    type: physical
Packit Service a04d08
  version: 1
Packit Service a04d08
network-sysconfig: "DEVICE='eth0'\nTYPE=Ethernet\nBOOTPROTO=dhcp\n\
Packit Service a04d08
  ONBOOT='yes'\nHWADDR=96:00:00:08:19:da\n\
Packit Service a04d08
  IPV6INIT=yes\nIPV6ADDR=2a01:4f8:beef:beef::1/64\n\
Packit Service a04d08
  IPV6_DEFAULTGW=fe80::1%eth0\nIPV6_AUTOCONF=no\n\
Packit Service a04d08
  DNS1=213.133.99.99\nDNS2=213.133.100.100\n"
Packit Service a04d08
public-ipv4: 192.168.0.1
Packit Service a04d08
public-keys:
Packit Service a04d08
- ssh-ed25519 \
Packit Service a04d08
  AAAAC3Nzac1lZdI1NTE5AaaAIaFrcac0yVITsmRrmueq6MD0qYNKlEvW8O1Ib4nkhmWh \
Packit Service a04d08
  test-key@workstation
Packit Service a04d08
vendor_data: "test"
Packit Service a04d08
""")
Packit Service a04d08
Packit Service a04d08
USERDATA = b"""#cloud-config
Packit Service a04d08
runcmd:
Packit Service a04d08
- [touch, /root/cloud-init-worked ]
Packit Service a04d08
"""
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
class TestDataSourceHetzner(CiTestCase):
Packit Service a04d08
    """
Packit Service a04d08
    Test reading the meta-data
Packit Service a04d08
    """
Packit Service a04d08
    def setUp(self):
Packit Service a04d08
        super(TestDataSourceHetzner, self).setUp()
Packit Service a04d08
        self.tmp = self.tmp_dir()
Packit Service a04d08
Packit Service a04d08
    def get_ds(self):
Packit Service a04d08
        ds = DataSourceHetzner.DataSourceHetzner(
Packit Service a04d08
            settings.CFG_BUILTIN, None, helpers.Paths({'run_dir': self.tmp}))
Packit Service a04d08
        return ds
Packit Service a04d08
Packit Service a04d08
    @mock.patch('cloudinit.net.EphemeralIPv4Network')
Packit Service a04d08
    @mock.patch('cloudinit.net.find_fallback_nic')
Packit Service a04d08
    @mock.patch('cloudinit.sources.helpers.hetzner.read_metadata')
Packit Service a04d08
    @mock.patch('cloudinit.sources.helpers.hetzner.read_userdata')
Packit Service a04d08
    @mock.patch('cloudinit.sources.DataSourceHetzner.on_hetzner')
Packit Service a04d08
    def test_read_data(self, m_on_hetzner, m_usermd, m_readmd, m_fallback_nic,
Packit Service a04d08
                       m_net):
Packit Service a04d08
        m_on_hetzner.return_value = True
Packit Service a04d08
        m_readmd.return_value = METADATA.copy()
Packit Service a04d08
        m_usermd.return_value = USERDATA
Packit Service a04d08
        m_fallback_nic.return_value = 'eth0'
Packit Service a04d08
Packit Service a04d08
        ds = self.get_ds()
Packit Service a04d08
        ret = ds.get_data()
Packit Service a04d08
        self.assertTrue(ret)
Packit Service a04d08
Packit Service a04d08
        m_net.assert_called_once_with(
Packit Service a04d08
            'eth0', '169.254.0.1',
Packit Service a04d08
            16, '169.254.255.255'
Packit Service a04d08
        )
Packit Service a04d08
Packit Service a04d08
        self.assertTrue(m_readmd.called)
Packit Service a04d08
Packit Service a04d08
        self.assertEqual(METADATA.get('hostname'), ds.get_hostname())
Packit Service a04d08
Packit Service a04d08
        self.assertEqual(METADATA.get('public-keys'),
Packit Service a04d08
                         ds.get_public_ssh_keys())
Packit Service a04d08
Packit Service a04d08
        self.assertIsInstance(ds.get_public_ssh_keys(), list)
Packit Service a04d08
        self.assertEqual(ds.get_userdata_raw(), USERDATA)
Packit Service a04d08
        self.assertEqual(ds.get_vendordata_raw(), METADATA.get('vendor_data'))
Packit Service a04d08
Packit Service a04d08
    @mock.patch('cloudinit.sources.helpers.hetzner.read_metadata')
Packit Service a04d08
    @mock.patch('cloudinit.net.find_fallback_nic')
Packit Service a04d08
    @mock.patch('cloudinit.sources.DataSourceHetzner.on_hetzner')
Packit Service a04d08
    def test_not_on_hetzner_returns_false(self, m_on_hetzner, m_find_fallback,
Packit Service a04d08
                                          m_read_md):
Packit Service a04d08
        """If helper 'on_hetzner' returns False, return False from get_data."""
Packit Service a04d08
        m_on_hetzner.return_value = False
Packit Service a04d08
        ds = self.get_ds()
Packit Service a04d08
        ret = ds.get_data()
Packit Service a04d08
Packit Service a04d08
        self.assertFalse(ret)
Packit Service a04d08
        # These are a white box attempt to ensure it did not search.
Packit Service a04d08
        m_find_fallback.assert_not_called()
Packit Service a04d08
        m_read_md.assert_not_called()
Packit Service 751c4a
Packit Service 751c4a
Packit Service 751c4a
class TestMaybeB64Decode:
Packit Service 751c4a
    """Test the maybe_b64decode helper function."""
Packit Service 751c4a
Packit Service 751c4a
    @pytest.mark.parametrize("invalid_input", (str("not bytes"), int(4)))
Packit Service 751c4a
    def test_raises_error_on_non_bytes(self, invalid_input):
Packit Service 751c4a
        """maybe_b64decode should raise error if data is not bytes."""
Packit Service 751c4a
        with pytest.raises(TypeError):
Packit Service 751c4a
            hc_helper.maybe_b64decode(invalid_input)
Packit Service 751c4a
Packit Service 751c4a
    @pytest.mark.parametrize("in_data,expected", [
Packit Service 751c4a
        # If data is not b64 encoded, then return value should be the same.
Packit Service 751c4a
        (b"this is my data", b"this is my data"),
Packit Service 751c4a
        # If data is b64 encoded, then return value should be decoded.
Packit Service 751c4a
        (base64.b64encode(b"data"), b"data"),
Packit Service 751c4a
    ])
Packit Service 751c4a
    def test_happy_path(self, in_data, expected):
Packit Service 751c4a
        assert expected == hc_helper.maybe_b64decode(in_data)