def mock_cumin(mocked_transports, retcode, retvals=None):
    """Given a mocked cumin.transports, add the necessary mocks for these tests and set the retcode."""
    if retvals is None:
        retvals = [[("host1", b"output1")]]

    results = []
    for retval in retvals:
        result = []
        for host, message in retval:
            result.append((NodeSet(host), MsgTreeElem(message, parent=MsgTreeElem())))

        results.append(result)

    mocked_transports.clustershell = clustershell
    mocked_execute = mock.Mock()
    mocked_execute.return_value = retcode
    mocked_get_results = mock.Mock()
    if results:
        mocked_get_results.side_effect = results
    else:
        mocked_get_results.return_value = iter(())

    mocked_transports.clustershell.ClusterShellWorker.execute = mocked_execute
    mocked_transports.clustershell.ClusterShellWorker.get_results = mocked_get_results
    mocked_transports.Target = Target
 def test_results_to_list_callback_raise(self):
     """It should raise RemoteError if the callback call raises any exception."""
     results = (item for item in [(self.hosts, MsgTreeElem(b"test", parent=MsgTreeElem()))])
     with pytest.raises(
         remote.RemoteError,
         match=r"Unable to extract data with <lambda> for host\[1-9\] from: test",
     ):
         remote.RemoteHosts.results_to_list(results, callback=lambda x: 1 / 0)
def set_mocked_icinga_host_outputs(mocked_icinga_host, outputs):
    """Setup the mocked icinga_host side effect to return the given outputs, one after another."""
    outs = [
        MsgTreeElem(output.encode(), parent=MsgTreeElem())
        for output in outputs
    ]
    mocked_icinga_host.run_sync.side_effect = [
        iter([(NodeSet("icinga-host"), out)]) for out in outs
    ]
Ejemplo n.º 4
0
 def test_check_disabled_ok(self):
     """It should check that all hosts have Puppet disabled."""
     host1 = NodeSet("test1.example.com")
     host2 = NodeSet("test2.example.com")
     results = [
         (host1, MsgTreeElem(b"1", parent=MsgTreeElem())),
         (host2, MsgTreeElem(b"1", parent=MsgTreeElem())),
     ]
     self.mocked_remote_hosts.run_sync.return_value = iter(results)
     self.puppet_hosts.check_disabled()
Ejemplo n.º 5
0
    def test_get_certificate_metadata_raises(self, json_output,
                                             exception_message):
        """It should raise PuppetMasterError if the Puppet CA returns multiple certificates metadata."""
        results = [(
            NodeSet("puppetmaster.example.com"),
            MsgTreeElem(json_output, parent=MsgTreeElem()),
        )]
        self.mocked_master_host.run_sync.return_value = iter(results)

        with pytest.raises(puppet.PuppetMasterError, match=exception_message):
            self.puppet_master.get_certificate_metadata("test.example.com")
def _get_mock_run_sync(
        return_value: Optional[bytes] = None,
        side_effect: Optional[List[bytes]] = None) -> mock.MagicMock:
    if side_effect is not None:
        return mock.MagicMock(side_effect=[(iter([
            ("test0.local.host",
             MsgTreeElem(return_value, parent=MsgTreeElem())),
        ])) for return_value in side_effect])

    return mock.MagicMock(
        return_value=iter([("test0.local.host",
                            MsgTreeElem(return_value, parent=MsgTreeElem()))]))
Ejemplo n.º 7
0
    def test_wait_for_csr_fail(self):
        """It should raise PuppetMasterError if the certificate is in a wrong state."""
        results = [(
            NodeSet("puppetmaster.example.com"),
            MsgTreeElem(PUPPET_CA_CERT_METADATA_SIGNED, parent=MsgTreeElem()),
        )]
        self.mocked_master_host.run_sync.return_value = iter(results)

        with pytest.raises(
                puppet.PuppetMasterError,
                match="Expected certificate in requested state, got: signed",
        ):
            self.puppet_master.wait_for_csr("test.example.com")
Ejemplo n.º 8
0
    def test_sign_wrong_state(self):
        """It should raise PuppetMasterError if the certificate is not in the requested state."""
        results = [(
            NodeSet("puppetmaster.example.com"),
            MsgTreeElem(PUPPET_CA_CERT_METADATA_SIGNED, parent=MsgTreeElem()),
        )]
        self.mocked_master_host.run_sync.return_value = iter(results)

        with pytest.raises(
                puppet.PuppetMasterError,
                match=
                "Certificate for test.example.com not in requested state, got: signed",
        ):
            self.puppet_master.sign("test.example.com", "00:AA")
Ejemplo n.º 9
0
 def test_check_enabled_raise(self):
     """It should raise PuppetHostsCheckError if Puppet is disabled on some hosts."""
     host1 = NodeSet("test1.example.com")
     host2 = NodeSet("test2.example.com")
     results = [
         (host1, MsgTreeElem(b"0", parent=MsgTreeElem())),
         (host2, MsgTreeElem(b"1", parent=MsgTreeElem())),
     ]
     self.mocked_remote_hosts.run_sync.return_value = iter(results)
     with pytest.raises(
             puppet.PuppetHostsCheckError,
             match="Puppet is not enabled on those hosts: test2.example.com",
     ):
         self.puppet_hosts.check_enabled()
Ejemplo n.º 10
0
    def test_sign_wrong_fingerprint(self):
        """It should raise PuppetMasterError if the fingerprint doesn't match the one in the CSR."""
        results = [(
            NodeSet("puppetmaster.example.com"),
            MsgTreeElem(PUPPET_CA_CERT_METADATA_REQUESTED,
                        parent=MsgTreeElem()),
        )]
        self.mocked_master_host.run_sync.return_value = iter(results)

        with pytest.raises(
                puppet.PuppetMasterError,
                match=
                "CSR fingerprint 00:AA for test.example.com does not match provided fingerprint FF:FF",
        ):
            self.puppet_master.sign("test.example.com", "FF:FF")
Ejemplo n.º 11
0
    def test_regenerate_certificate_raise(self):
        """It should raise PuppetHostsError if unable to find any of the fingerprint."""
        message = PUPPET_GENERATE_CERTIFICATE_SUCCESS.decode().replace(
            ": 00:FF", "").encode()
        results = [(NodeSet("test.example.com"),
                    MsgTreeElem(message, parent=MsgTreeElem()))]
        self.mocked_remote_hosts.run_sync.side_effect = [
            iter(()), iter(results)
        ]

        with pytest.raises(
                puppet.PuppetHostsError,
                match="Unable to find CSR fingerprints for all hosts",
        ):
            self.puppet_hosts.regenerate_certificate()
Ejemplo n.º 12
0
    def test_verify_ok(self):
        """It should verify that the host has a signed certificate in the Puppet CA."""
        json_output = b'{"host":"test.example.com","valid":true}'
        results = [(
            NodeSet("puppetmaster.example.com"),
            MsgTreeElem(json_output, parent=MsgTreeElem()),
        )]
        self.mocked_master_host.run_sync.return_value = iter(results)

        self.puppet_master.verify("test.example.com")
        self.mocked_master_host.run_sync.assert_called_once_with(
            "puppet ca --disable_warnings deprecations --render-as json verify test.example.com",
            is_safe=True,
            print_output=False,
            print_progress_bars=False,
        )
Ejemplo n.º 13
0
    def test_verify_invalid_json(self):
        """It should raise PuppetMasterError if there output of the executed command is invalid JSON."""
        json_output = b'{"host":"test.example.com",,}'
        results = [(
            NodeSet("puppetmaster.example.com"),
            MsgTreeElem(json_output, parent=MsgTreeElem()),
        )]
        self.mocked_master_host.run_sync.return_value = iter(results)

        with pytest.raises(
                puppet.PuppetMasterError,
                match=
            ("Unable to parse Puppet master response for command "
             '"puppet ca --disable_warnings deprecations --render-as json verify test.example.com"'
             ),
        ):
            self.puppet_master.verify("test.example.com")
Ejemplo n.º 14
0
    def test_instance_add_ok(self, requests_mock):
        """It should issue the remove command on the master host."""
        self._set_requests_mock_for_instance(requests_mock)
        requests_mock.get(self.base_url + "/info", text=self.info)
        instance = self.ganeti.instance(self.instance)
        results = [(
            NodeSet("ganeti-master.example.com"),
            MsgTreeElem(b"creation logs", parent=MsgTreeElem()),
        )]
        self.remote.query.return_value.run_sync.return_value = iter(results)

        instance.add(row="A", vcpus=2, memory=3, disk=4, link="private")

        self.remote.query.return_value.run_sync.assert_called_once_with(
            "gnt-instance add -t drbd -I hail --net 0:link=private --hypervisor-parameters=kvm:boot_order=network "
            "-o debootstrap+default --no-install -g row_A -B vcpus=2,memory=3g --disk 0:size=4g test.example.com"
        )
Ejemplo n.º 15
0
    def test_wait_for_csr_timeout(self, mocked_sleep):
        """It should raise PuppetMasterCheckError if the certificate request doesn't appear."""
        results = [(
            NodeSet("puppetmaster.example.com"),
            MsgTreeElem(b"[]", parent=MsgTreeElem()),
        )]
        self.mocked_master_host.run_sync.side_effect = [
            iter(results) for _ in range(10)
        ]

        with pytest.raises(
                puppet.PuppetMasterCheckError,
                match="No certificate found for hostname: test.example.com",
        ):
            self.puppet_master.wait_for_csr("test.example.com")

        assert mocked_sleep.called
Ejemplo n.º 16
0
    def test_regenerate_certificate_errors(self):
        """It should raise PuppetHostsError and print the Puppet errors if unable to find any of the fingerprint."""
        results = [(
            NodeSet("test.example.com"),
            MsgTreeElem(PUPPET_GENERATE_CERTIFICATE_FAILED,
                        parent=MsgTreeElem()),
        )]
        self.mocked_remote_hosts.run_sync.side_effect = [
            iter(()), iter(results)
        ]

        with pytest.raises(
                puppet.PuppetHostsError,
                match=
            ("test.example.com: Error: Could not request certificate: The certificate retrieved "
             "from the master does not match the agent's private key."),
        ):
            self.puppet_hosts.regenerate_certificate()
Ejemplo n.º 17
0
    def test_wait_for_csr_already_ok(self):
        """It should return immediately if the certificate is already requested."""
        results = [(
            NodeSet("puppetmaster.example.com"),
            MsgTreeElem(PUPPET_CA_CERT_METADATA_REQUESTED,
                        parent=MsgTreeElem()),
        )]
        self.mocked_master_host.run_sync.return_value = iter(results)

        self.puppet_master.wait_for_csr("test.example.com")

        self.mocked_master_host.run_sync.assert_called_once_with(
            "puppet ca --disable_warnings deprecations --render-as json "
            r'list --all --subject "^test\.example\.com$"',
            is_safe=True,
            print_output=False,
            print_progress_bars=False,
        )
Ejemplo n.º 18
0
    def test_get_ca_servers_handles_multiple_lines_in_command_output(self):
        """Test test get ca servers handles multiple results."""
        self.mocked_remote_hosts.run_sync.return_value = [
            (
                NodeSet("test0.example.com"),
                MsgTreeElem(
                    b"test0.puppetmast.er",
                    parent=MsgTreeElem(b"some message that should be ignored",
                                       parent=MsgTreeElem()),
                ),
            ),
        ]

        result = self.puppet_hosts.get_ca_servers()

        self.mocked_remote_hosts.run_sync.assert_called_once()
        assert "test0.example.com" in result
        assert result["test0.example.com"] == "test0.puppetmast.er"
Ejemplo n.º 19
0
    def test_get_ca_servers_explodes_multihost_nodeset_into_single_hosts(self):
        """Test that get ca servers explodes multihost nodeset into single hosts."""
        expected_puppetmaster = "dummy.puppetmast.er"
        self.mocked_remote_hosts.run_sync.return_value = [
            (
                NodeSet("test[0-1].example.com"),
                MsgTreeElem(expected_puppetmaster.encode(),
                            parent=MsgTreeElem()),
            ),
        ]

        result = self.puppet_hosts.get_ca_servers()

        self.mocked_remote_hosts.run_sync.assert_called_once()
        assert "test0.example.com" in result
        assert result["test0.example.com"] == expected_puppetmaster
        assert "test1.example.com" in result
        assert result["test1.example.com"] == expected_puppetmaster
Ejemplo n.º 20
0
    def test_sign_alt_dns(self):
        """It should pass the --allow-dns-alt-names option while signing the certificate."""
        requested_results = [(
            NodeSet("puppetmaster.example.com"),
            MsgTreeElem(PUPPET_CA_CERT_METADATA_REQUESTED,
                        parent=MsgTreeElem()),
        )]
        signed_results = [(
            NodeSet("puppetmaster.example.com"),
            MsgTreeElem(PUPPET_CA_CERT_METADATA_SIGNED, parent=MsgTreeElem()),
        )]
        self.mocked_master_host.run_sync.side_effect = [
            iter(requested_results),
            iter(()),
            iter(signed_results),
        ]

        self.puppet_master.sign("test.example.com",
                                "00:AA",
                                allow_alt_names=True)

        self.mocked_master_host.run_sync.assert_has_calls([
            mock.call(
                "puppet ca --disable_warnings deprecations --render-as json "
                r'list --all --subject "^test\.example\.com$"',
                is_safe=True,
                print_output=False,
                print_progress_bars=False,
            ),
            mock.call(
                "puppet cert --disable_warnings deprecations sign --allow-dns-alt-names test.example.com",
                print_output=False,
                print_progress_bars=False,
            ),
            mock.call(
                "puppet ca --disable_warnings deprecations --render-as json "
                r'list --all --subject "^test\.example\.com$"',
                is_safe=True,
                print_output=False,
                print_progress_bars=False,
            ),
        ])
Ejemplo n.º 21
0
    def test_get_ca_servers_handles_multiple_results(self):
        """Test test get ca servers handles multiple results."""
        self.mocked_remote_hosts.run_sync.return_value = [
            (
                NodeSet("test0.example.com"),
                MsgTreeElem(b"test0.puppetmast.er", parent=MsgTreeElem()),
            ),
            (
                NodeSet("test1.example.com"),
                MsgTreeElem(b"test1.puppetmast.er", parent=MsgTreeElem()),
            ),
        ]

        result = self.puppet_hosts.get_ca_servers()

        self.mocked_remote_hosts.run_sync.assert_called_once()
        assert "test0.example.com" in result
        assert result["test0.example.com"] == "test0.puppetmast.er"
        assert "test1.example.com" in result
        assert result["test1.example.com"] == "test1.puppetmast.er"
Ejemplo n.º 22
0
    def test_wait_since_timeout(self, mocked_sleep):
        """It should raise PuppetHostsCheckError if the successful Puppet run is too old within the timeout."""
        last_run = datetime.utcnow()
        # timestamp() consider naive datetime objects as local time.
        last_run_string = str(
            int(last_run.replace(tzinfo=timezone.utc).timestamp()))
        start = last_run + timedelta(seconds=1)

        nodes = NodeSet("test.example.com")
        results = [(nodes,
                    MsgTreeElem(last_run_string.encode(),
                                parent=MsgTreeElem()))]
        self.mocked_remote_hosts.run_sync.side_effect = [results] * 60
        self.mocked_remote_hosts.hosts = nodes

        with pytest.raises(puppet.PuppetHostsCheckError,
                           match="Successful Puppet run too old"):
            self.puppet_hosts.wait_since(start)

        assert mocked_sleep.called
Ejemplo n.º 23
0
    def test_get_certificate_metadata_ok(self):
        """It should return the metadata of the certificate for the host in the Puppet CA."""
        results = [(
            NodeSet("puppetmaster.example.com"),
            MsgTreeElem(PUPPET_CA_CERT_METADATA_SIGNED, parent=MsgTreeElem()),
        )]
        self.mocked_master_host.run_sync.return_value = iter(results)

        metadata = self.puppet_master.get_certificate_metadata(
            "test.example.com")

        assert metadata == json.loads(
            PUPPET_CA_CERT_METADATA_SIGNED.decode())[0]
        self.mocked_master_host.run_sync.assert_called_once_with(
            "puppet ca --disable_warnings deprecations --render-as json list "
            r'--all --subject "^test\.example\.com$"',
            is_safe=True,
            print_output=False,
            print_progress_bars=False,
        )
Ejemplo n.º 24
0
    def test_regenerate_certificate_ok(self):
        """It should delete and regenerate the Puppet certificate."""
        results = [(
            NodeSet("test.example.com"),
            MsgTreeElem(PUPPET_GENERATE_CERTIFICATE_SUCCESS,
                        parent=MsgTreeElem()),
        )]
        self.mocked_remote_hosts.run_sync.side_effect = [
            iter(()), iter(results)
        ]

        fingerprints = self.puppet_hosts.regenerate_certificate()

        self.mocked_remote_hosts.run_sync.assert_has_calls([
            mock.call("rm -rfv /var/lib/puppet/ssl"),
            mock.call(puppet.Command("puppet agent --test --color=false",
                                     ok_codes=[]),
                      print_output=False),
        ])
        assert fingerprints == {"test.example.com": "00:FF"}
Ejemplo n.º 25
0
    def test_verify_raise(self):
        """It should raise PuppetMasterError if the certificate is not valid on the Puppet CA."""
        json_output = b'{"host":"test.example.com","valid":false,"error":"Error message"}'
        results = [(
            NodeSet("puppetmaster.example.com"),
            MsgTreeElem(json_output, parent=MsgTreeElem()),
        )]
        self.mocked_master_host.run_sync.return_value = iter(results)

        with pytest.raises(
                puppet.PuppetMasterError,
                match="Invalid certificate for test.example.com: Error message",
        ):
            self.puppet_master.verify("test.example.com")

        self.mocked_master_host.run_sync.assert_called_once_with(
            "puppet ca --disable_warnings deprecations --render-as json verify test.example.com",
            is_safe=True,
            print_output=False,
            print_progress_bars=False,
        )
Ejemplo n.º 26
0
    def test_sign_fail(self):
        """It should raise PuppetMasterError if the sign operation fails."""
        requested_results = [(
            NodeSet("puppetmaster.example.com"),
            MsgTreeElem(PUPPET_CA_CERT_METADATA_REQUESTED,
                        parent=MsgTreeElem()),
        )]
        sign_results = [(
            NodeSet("puppetmaster.example.com"),
            MsgTreeElem(b"sign error", parent=MsgTreeElem()),
        )]
        signed_results = [(
            NodeSet("puppetmaster.example.com"),
            MsgTreeElem(PUPPET_CA_CERT_METADATA_REQUESTED,
                        parent=MsgTreeElem()),
        )]
        self.mocked_master_host.run_sync.side_effect = [
            iter(requested_results),
            iter(sign_results),
            iter(signed_results),
        ]

        with pytest.raises(
                puppet.PuppetMasterError,
                match=
                "Expected certificate for test.example.com to be signed, got: requested",
        ):
            self.puppet_master.sign("test.example.com", "00:AA")
Ejemplo n.º 27
0
    def test_wait_ok(self):
        """It should return immediately if there is already successful Puppet run since now."""
        last_run = datetime.utcnow() + timedelta(seconds=1)
        # timestamp() consider naive datetime objects as local time.
        last_run_string = str(
            int(last_run.replace(tzinfo=timezone.utc).timestamp()))

        nodes = NodeSet("test.example.com")
        results = [(nodes,
                    MsgTreeElem(last_run_string.encode(),
                                parent=MsgTreeElem()))]
        self.mocked_remote_hosts.run_sync.return_value = iter(results)
        self.mocked_remote_hosts.hosts = nodes

        self.puppet_hosts.wait()

        self.mocked_remote_hosts.run_sync.assert_called_once_with(
            ("source /usr/local/share/bash/puppet-common.sh && last_run_success && awk /last_run/'{ print $2 }' "
             '"${PUPPET_SUMMARY}"'),
            is_safe=True,
            print_output=False,
            print_progress_bars=False,
        )
Ejemplo n.º 28
0
    def test_wait_since_missing_host(self, mocked_sleep):
        """It should raise PuppetHostsCheckError unable to get the result from some host."""
        last_run = datetime.utcnow()
        # timestamp() consider naive datetime objects as local time.
        last_run_string = str(
            int(last_run.replace(tzinfo=timezone.utc).timestamp()))
        start = last_run - timedelta(seconds=1)

        nodes = NodeSet("test[1-2].example.com")
        results = [(
            NodeSet("test1.example.com"),
            MsgTreeElem(last_run_string.encode(), parent=MsgTreeElem()),
        )]
        self.mocked_remote_hosts.run_sync.side_effect = [results] * 60
        self.mocked_remote_hosts.hosts = nodes

        with pytest.raises(
                puppet.PuppetHostsCheckError,
                match=
                "Unable to get successful Puppet run from: test2.example.com",
        ):
            self.puppet_hosts.wait_since(start)

        assert mocked_sleep.called
def set_mocked_icinga_host_output(mocked_icinga_host, output, n_hosts=1):
    """Setup the mocked icinga_host return value with the given output."""
    out = MsgTreeElem(output.encode(), parent=MsgTreeElem())
    mocked_icinga_host.run_sync.return_value = iter(
        n_hosts * [(NodeSet("icinga-host"), out)])
 def test_results_to_list_no_callback(self):
     """It should return the output string without any conversion."""
     results = (item for item in [(self.hosts, MsgTreeElem(b"test", parent=MsgTreeElem()))])
     extracted = remote.RemoteHosts.results_to_list(results)
     assert sorted(extracted) == sorted([(self.hosts, "test")])