def test_mender_configure_successful_install_needs_reboot(
        setup_test_container, setup_tester_ssh_connection):
    # Install a configuration apply script which requires reboot
    make_configuration_apply_script(setup_tester_ssh_connection,
                                    "#/bin/sh\nexit 20\n")

    # Generate a simple configuration artifact
    configuration = {"key": "value"}
    configuration_artifact = tempfile.NamedTemporaryFile(suffix=".mender",
                                                         delete=False)
    configuration_artifact_name = configuration_artifact.name

    make_configuration_artifact(configuration, "configuration-artifact",
                                configuration_artifact_name)

    # Install the configuration artifact
    try:
        put(
            setup_tester_ssh_connection,
            configuration_artifact_name,
            key_filename=setup_test_container.key_filename,
            remote_path="/data/configuration-artifact.mender",
        )

        result = run(
            setup_tester_ssh_connection,
            "mender install /data/configuration-artifact.mender",
            warn=True,
        )
        logging.debug(result)
        assert result.exited == 0
        assert (
            "At least one payload requested a reboot of the device it updated."
            in result.stdout)
    finally:
        os.unlink(configuration_artifact_name)

    # Verify the content of the configuration
    result = run(
        setup_tester_ssh_connection,
        "cat /var/lib/mender-configure/device-config.json",
    )
    logging.debug(result)
    assert result.exited == 0

    assert "key" in result.stdout, result
    assert "value" in result.stdout, result

    device_config = json.loads(result.stdout)
    assert device_config == configuration

    # Verify the needs-reboot file
    result = run(
        setup_tester_ssh_connection,
        "ls /data/mender/modules/v3/payloads/0000/tree/tmp/needs-reboot",
        warn=True,
    )
    logging.debug(result)
    assert result.exited == 0
 def set_timezone(timezone):
     with tempfile.NamedTemporaryFile() as fd:
         fd.write(("""{"timezone":"%s"}""" % timezone).encode())
         fd.flush()
         put(
             setup_tester_ssh_connection,
             fd.name,
             key_filename=setup_test_container.key_filename,
             remote_path="/data/mender-configure/device-config.json",
         )
     run(
         setup_tester_ssh_connection,
         "/usr/lib/mender-configure/apply-device-config.d/timezone /data/mender-configure/device-config.json",
     )
def make_configuration_apply_script(setup_tester_ssh_connection, script):
    # Enable writes
    run(
        setup_tester_ssh_connection, "mount -o remount,rw /",
    )

    # Install the apply-device-config script
    tf = NamedTemporaryFile(delete=False)
    tf.write(script.encode("utf-8"))
    tf.close()

    try:
        run(
            setup_tester_ssh_connection,
            "mkdir -p /usr/lib/mender-configure/apply-device-config.d",
        )
        put(
            setup_tester_ssh_connection,
            tf.name,
            key_filename=tf.name,
            remote_path="/usr/lib/mender-configure/apply-device-config.d/integration-test",
        )
        run(
            setup_tester_ssh_connection,
            "chmod 755 /usr/lib/mender-configure/apply-device-config.d/integration-test",
        )
    finally:
        os.unlink(tf.name)
        # Disable writes
        run(
            setup_tester_ssh_connection, "mount -o remount,ro /",
        )
def test_mender_configure_successful_install(setup_test_container,
                                             setup_tester_ssh_connection):
    # Install a no-op configuration apply script
    make_configuration_apply_script(setup_tester_ssh_connection,
                                    "#/bin/sh\nexit 0\n")

    # Generate a simple configuration artifact
    configuration = {"key": "value"}
    configuration_artifact = tempfile.NamedTemporaryFile(suffix=".mender",
                                                         delete=False)
    configuration_artifact_name = configuration_artifact.name

    make_configuration_artifact(configuration, "configuration-artifact",
                                configuration_artifact_name)

    # Install the configuration artifact
    try:
        put(
            setup_tester_ssh_connection,
            configuration_artifact_name,
            key_filename=setup_test_container.key_filename,
            remote_path="/data/configuration-artifact.mender",
        )

        result = run(
            setup_tester_ssh_connection,
            "mender install /data/configuration-artifact.mender",
            warn=True,
        )
        logging.debug(result)
        assert result.exited == 0
    finally:
        os.unlink(configuration_artifact_name)

    # Verify the content of the configuration
    result = run(
        setup_tester_ssh_connection,
        "cat /var/lib/mender-configure/device-config.json",
    )
    logging.debug(result)

    assert "key" in result.stdout, result
    assert "value" in result.stdout, result

    device_config = json.loads(result.stdout)
    assert device_config == configuration

    # commit the installation
    result = run(
        setup_tester_ssh_connection,
        "mender commit",
        warn=True,
    )
    logging.debug(result)
    assert result.exited == 0

    # Generate a new configuration artifact
    configuration = {"new-key": "new-value"}
    configuration_artifact = tempfile.NamedTemporaryFile(suffix=".mender",
                                                         delete=False)
    configuration_artifact_name = configuration_artifact.name

    make_configuration_artifact(configuration, "new-configuration-artifact",
                                configuration_artifact_name)

    # Install the configuration artifact
    try:
        put(
            setup_tester_ssh_connection,
            configuration_artifact_name,
            key_filename=setup_test_container.key_filename,
            remote_path="/data/new-configuration-artifact.mender",
        )

        result = run(
            setup_tester_ssh_connection,
            "mender install /data/new-configuration-artifact.mender",
            warn=True,
        )
        logging.debug(result)
        assert result.exited == 0
    finally:
        os.unlink(configuration_artifact_name)

    # Verify the content of the configuration
    result = run(
        setup_tester_ssh_connection,
        "cat /var/lib/mender-configure/device-config.json",
    )
    logging.debug(result)

    assert "new-key" in result.stdout, result
    assert "new-value" in result.stdout, result

    device_config = json.loads(result.stdout)
    assert device_config == configuration
def test_mender_configure_failed_install_apply_fails(
        setup_test_container, setup_tester_ssh_connection):
    # Install a configuration apply script which fails in applying the new configuration
    make_configuration_apply_script(
        setup_tester_ssh_connection,
        """#/bin/sh
if grep -q new-key "$1"; then
    exit 2
fi
exit 0
""",
    )

    # Install a pre-existing configuration
    configuration = {"key": "value"}
    configuration_file = tempfile.NamedTemporaryFile(suffix=".json",
                                                     delete=False)
    configuration_file_name = configuration_file.name
    open(configuration_file_name, "w").write(json.dumps(configuration))
    put(
        setup_tester_ssh_connection,
        configuration_file_name,
        key_filename=setup_test_container.key_filename,
        remote_path="/var/lib/mender-configure/device-config.json",
    )
    os.unlink(configuration_file_name)

    # capture artifact and provides
    result = run(
        setup_tester_ssh_connection,
        "mender show-artifact 2>/dev/null",
    )
    artifact = result.stdout
    result = run(
        setup_tester_ssh_connection,
        "mender show-provides 2>/dev/null",
    )
    provides = result.stdout

    # Generate a simple configuration artifact
    new_configuration = {"new-key": "new-value"}
    configuration_artifact = tempfile.NamedTemporaryFile(suffix=".mender",
                                                         delete=False)
    configuration_artifact_name = configuration_artifact.name

    make_configuration_artifact(new_configuration, "configuration-artifact",
                                configuration_artifact_name)

    # Install the configuration artifact
    try:
        put(
            setup_tester_ssh_connection,
            configuration_artifact_name,
            key_filename=setup_test_container.key_filename,
            remote_path="/data/configuration-artifact.mender",
        )

        result = run(
            setup_tester_ssh_connection,
            "mender install /data/configuration-artifact.mender",
            warn=True,
        )
        logging.debug(result)
        assert result.exited != 0
        assert (
            "Installation failed: Update module terminated abnormally: exit status 2"
            in result.stderr)
    finally:
        os.unlink(configuration_artifact_name)

    # Verify the content of the configuration
    result = run(
        setup_tester_ssh_connection,
        "cat /var/lib/mender-configure/device-config.json",
        warn=True,
    )
    logging.debug(result)
    assert result.exited == 0

    assert "key" in result.stdout, result
    assert "value" in result.stdout, result

    device_config = json.loads(result.stdout)
    assert device_config == configuration

    # capture the new artifact and provides and verify they didn't change
    result = run(
        setup_tester_ssh_connection,
        "mender show-artifact 2>/dev/null",
    )
    new_artifact = result.stdout
    result = run(
        setup_tester_ssh_connection,
        "mender show-provides 2>/dev/null",
    )
    new_provides = result.stdout
    assert (new_artifact, new_provides) == (artifact, provides)
def test_mender_configure_failed_install_config_is_a_folder(
        setup_test_container, setup_tester_ssh_connection):
    # Install a no-op configuration apply script
    make_configuration_apply_script(setup_tester_ssh_connection,
                                    "#/bin/sh\nexit 0\n")

    # Lock the configuration file with a folder
    run(
        setup_tester_ssh_connection,
        "mkdir -p /var/lib/mender-configure/device-config.json",
    )

    # capture artifact and provides
    result = run(
        setup_tester_ssh_connection,
        "mender show-artifact 2>/dev/null",
    )
    artifact = result.stdout
    result = run(
        setup_tester_ssh_connection,
        "mender show-provides 2>/dev/null",
    )
    provides = result.stdout

    # Generate a simple configuration artifact
    new_configuration = {"new-key": "new-value"}
    configuration_artifact = tempfile.NamedTemporaryFile(suffix=".mender",
                                                         delete=False)
    configuration_artifact_name = configuration_artifact.name

    make_configuration_artifact(new_configuration, "configuration-artifact",
                                configuration_artifact_name)

    # Install the configuration artifact
    try:
        put(
            setup_tester_ssh_connection,
            configuration_artifact_name,
            key_filename=setup_test_container.key_filename,
            remote_path="/data/configuration-artifact.mender",
        )

        result = run(
            setup_tester_ssh_connection,
            "mender install /data/configuration-artifact.mender",
            warn=True,
        )
        logging.debug(result)
        assert result.exited != 0
        assert (
            "Installation failed: Update module terminated abnormally: exit status 1"
            in result.stderr)
    finally:
        os.unlink(configuration_artifact_name)

    # capture the new artifact and provides and verify they didn't change
    result = run(
        setup_tester_ssh_connection,
        "mender show-artifact 2>/dev/null",
    )
    new_artifact = result.stdout
    result = run(
        setup_tester_ssh_connection,
        "mender show-provides 2>/dev/null",
    )
    new_provides = result.stdout
    assert (new_artifact, new_provides) == (artifact, provides)
def test_timezone_script(setup_test_container, setup_tester_ssh_connection):
    run(setup_tester_ssh_connection, "mount / -o remount,rw")

    try:
        run(
            setup_tester_ssh_connection,
            "mkdir -p /usr/lib/mender-configure/apply-device-config.d",
        )
        put(
            setup_tester_ssh_connection,
            "../../scripts/timezone",
            key_filename=setup_test_container.key_filename,
            remote_path=
            "/usr/lib/mender-configure/apply-device-config.d/timezone",
        )
        run(setup_tester_ssh_connection, "mkdir -p /data/mender-configure")

        def set_timezone(timezone):
            with tempfile.NamedTemporaryFile() as fd:
                fd.write(("""{"timezone":"%s"}""" % timezone).encode())
                fd.flush()
                put(
                    setup_tester_ssh_connection,
                    fd.name,
                    key_filename=setup_test_container.key_filename,
                    remote_path="/data/mender-configure/device-config.json",
                )
            run(
                setup_tester_ssh_connection,
                "/usr/lib/mender-configure/apply-device-config.d/timezone /data/mender-configure/device-config.json",
            )

        set_timezone("UTC")
        res = run(setup_tester_ssh_connection, "timedatectl status")
        assert re.search("Time zone: *UTC", res.stdout) is not None

        old_hour = run(setup_tester_ssh_connection, "date +%H").stdout.strip()

        set_timezone("Asia/Tokyo")
        res = run(setup_tester_ssh_connection, "timedatectl status")
        assert re.search("Time zone: *Asia/Tokyo", res.stdout) is not None

        new_hour = run(setup_tester_ssh_connection, "date +%H").stdout.strip()
        assert abs(int(new_hour) - int(old_hour)) > 5

    finally:
        run(setup_tester_ssh_connection, "timedatectl set-timezone UTC")
        run(setup_tester_ssh_connection, "mount / -o remount,ro")