예제 #1
0
def test_downgrade_then_upgrade():
    """
    If the patch version is greater than zero,
    check that we can perform a version downgrade,
    followed by version upgrade back to the current version
    """
    helm_chart_path = os.environ.get("HELM_CHART_PATH")
    if not helm_chart_path:
        raise Exception(
            "This test only works with HELM_CHART_PATH set to the path of the chart to be tested"
        )
    with open(os.path.join(git_root_dir, "Chart.yaml"), "r") as f:
        astro_chart_dot_yaml = yaml.safe_load(f.read())
    major, minor, patch = semver(astro_chart_dot_yaml['version']).release
    if patch == 0:
        print("This test is not applicable to patch version 0")
        return

    namespace = os.environ.get('NAMESPACE')
    release_name = os.environ.get('RELEASE_NAME')
    if not namespace:
        print("NAMESPACE env var is not present, using 'astronomer' namespace")
        namespace = 'astronomer'
    if not release_name:
        print(
            "RELEASE_NAME env var is not present, assuming 'astronomer' is the release name"
        )
        release_name = 'astronomer'

    config_path = os.path.join(git_root_dir, "upgrade_test_config.yaml")
    # Get the existing values
    check_output(
        f"helm3 get values -n {namespace} {release_name} > {config_path}",
        shell=True)
    # attempt downgrade with the documented procedure
    print("Performing patch version downgrade...")
    command = \
        "helm3 upgrade --reset-values " + \
        f"-f {config_path} " + \
        f"-n {namespace} " + \
        f"--version={major}.{minor}.{patch - 1} " + \
        f"{release_name} " + \
        "astronomer-internal/astronomer"
    print(command)
    print(check_output(command, shell=True))
    print("The downgrade worked, upgrading!")
    command = \
        "helm3 upgrade --reset-values " + \
        f"-f {config_path} " + \
        f"-n {namespace} " + \
        f"--version={major}.{minor}.{patch} " + \
        f"{release_name} " + \
        helm_chart_path
    print(command)
    print(check_output(command, shell=True))
    print("The upgrade worked!")
예제 #2
0
def test_downgrade_then_upgrade():
    """
    If the patch version is greater than zero,
    check that we can perform a version downgrade,
    followed by version upgrade back to the current version
    """
    helm_chart_path = getenv("HELM_CHART_PATH")
    if not helm_chart_path:
        raise Exception(
            "This test only works with HELM_CHART_PATH set to the path of the chart to be tested"
        )
    with open(git_root_dir / "Chart.yaml") as f:
        astro_chart_dot_yaml = yaml.safe_load(f.read())
    major, minor, patch = semver(astro_chart_dot_yaml["version"]).release
    if patch == 0:
        print("This test is not applicable to patch version 0")
        return

    if not (namespace := getenv("NAMESPACE")):
        print("NAMESPACE env var is not present, using 'astronomer' namespace")
        namespace = "astronomer"
예제 #3
0
def test_chart_version_is_not_already_published():
    """
    Tests that Chart.yaml has been incremented
    """
    with open(os.path.join(git_root_dir, "Chart.yaml"), "r") as f:
        astro_chart_dot_yaml = yaml.safe_load(f.read())
    major, minor, patch = semver(astro_chart_dot_yaml['version']).release
    if patch == 0:
        print("This test does not apply to patch version zero")
        return
    repo_result = check_output(
        f"helm3 search repo --output=json --version=^{major}.{minor} astronomer-internal/astronomer",
        shell=True)
    # Example result:
    # [{"name":"astronomer-internal/astronomer","version":"0.19.3","app_version":"0.19.3","description":"Helm chart to deploy the Astronomer Platform"}]
    repo_result = json.loads(repo_result)
    for line in repo_result:
        assert line['version'] != astro_chart_dot_yaml['version'], \
            f"Version {astro_chart_dot_yaml['version']} is already released " + \
            "to https://internal-helm.astronomer.io/, please increment 'version' " + \
            "in both Chart.yaml and charts/astronomer/Chart.yaml"
예제 #4
0
from packaging.version import parse as semver


def eprint(*args, **kwargs):
    print(*args, file=sys.stderr, **kwargs)


def print_usage():
    eprint(f"Description: {__doc__}\n")
    eprint(f"Usage:       {sys.argv[0]} <dir_to_check>\n")


if len(sys.argv) != 2:
    print_usage()
    sys.exit(1)

directory = Path(sys.argv[1]).absolute()

try:
    with open(directory / "version.txt") as version_file:
        version = version_file.read().strip()
except FileNotFoundError:
    eprint(f"ERROR: version.txt not found in {directory}")
    sys.exit(1)

if not semver(version).release:
    eprint(f"ERROR: No valid semver found in {directory}/version.txt")
    exit(1)

print(version)
예제 #5
0
def test_upgrade():
    """
    Functional test for the LTS to LTS upgrade (0.16 to 0.23)
    """
    with open(os.path.join(git_root_dir, "Chart.yaml"), "r") as f:
        astro_chart_dot_yaml = yaml.safe_load(f.read())
    major, minor, patch = semver(astro_chart_dot_yaml['version']).release

    assert major == 0 and minor == 23, "This test is only applicable for 0.23"

    upgrade_manifest_path = os.path.join(
        git_root_dir,
        "bin/migration-scripts/lts-to-lts/0.16-to-0.23/manifests/upgrade-0.16-to-0.23.yaml"
    )
    rollback_manifest_path = os.path.join(
        git_root_dir,
        "bin/migration-scripts/lts-to-lts/0.16-to-0.23/manifests/rollback-0.16-to-0.23.yaml"
    )

    namespace = os.environ.get('NAMESPACE')
    release_name = os.environ.get('RELEASE_NAME')
    if not namespace:
        print("NAMESPACE env var is not present, using 'astronomer' namespace")
        namespace = 'astronomer'
    if not release_name:
        print(
            "RELEASE_NAME env var is not present, assuming 'astronomer' is the release name"
        )
        release_name = 'astronomer'

    config_path = os.path.join(git_root_dir, "upgrade_test_config.yaml")
    # Get the existing values
    result = check_output(
        f"helm3 history { release_name } -n { namespace } | tail -n 1",
        shell=True).decode('utf8')
    assert "0.16" in result
    # rewrite manifest to replace with CI image for Kind test
    with open(upgrade_manifest_path, "r") as f:
        upgrade_manifest_data = f.read()
    upgrade_manifest_data = upgrade_manifest_data.replace(
        "image: quay.io/astronomer/lts-016-023-upgrade:latest",
        "image: lts-016-023-upgrade:latest")
    upgrade_manifest_data = upgrade_manifest_data.replace(
        "imagePullPolicy: Always", "imagePullPolicy: Never")
    with open(f"{upgrade_manifest_path}.test.yaml", "w") as f:
        f.write(upgrade_manifest_data)
    check_output(f"kubectl apply -f {upgrade_manifest_path}.test.yaml",
                 shell=True)
    timeout = 800
    start_time = time()
    while True:
        sleep(5)
        result = check_output(
            f"kubectl get pods -n default | grep upgrade-astronomer",
            shell=True).decode('utf8')
        if "Completed" in result:
            print("Upgrade pod finished in success")
            break
        if "Error" in result:
            print("Upgrade pod finished in error")
            logs = check_output(
                f"kubectl logs $(kubectl get pods -n default | grep upgrade-astronomer | awk "
                + "'{ print $1 }')",
                shell=True).decode('utf8')
            print(logs)
            assert False, "Failed to perform upgrade, see logs"
        if time() - start_time > timeout:
            logs = check_output(
                f"kubectl logs $(kubectl get pods -n default | grep upgrade-astronomer | awk "
                + "'{ print $1 }')",
                shell=True).decode('utf8')
            print(logs)
            assert False, "Failed to perform upgrade (timeout!), see logs"
    result = check_output(
        f"helm3 history astronomer -n astronomer | tail -n 1",
        shell=True).decode('utf8')
    assert "0.23" in result and "deployed" in result, "Expected upgrade to be performed"
    with open(rollback_manifest_path, "r") as f:
        rollback_manifest_data = f.read()
    rollback_manifest_data = rollback_manifest_data.replace(
        "image: quay.io/astronomer/lts-016-023-upgrade:latest",
        "image: lts-016-023-upgrade:latest")
    rollback_manifest_data = rollback_manifest_data.replace(
        "imagePullPolicy: Always", "imagePullPolicy: Never")
    with open(f"{rollback_manifest_path}.test.yaml", "w") as f:
        f.write(rollback_manifest_data)
    check_output(f"kubectl apply -f {rollback_manifest_path}.test.yaml",
                 shell=True)
    timeout = 800
    start_time = time()
    while True:
        sleep(5)
        result = check_output(f"kubectl get pods -n default | grep rollback",
                              shell=True).decode('utf8')
        if "Completed" in result:
            print("Rollback pod finished in success")
            break
        if "Error" in result:
            print("Rollback pod finished in error")
            logs = check_output(
                f"kubectl logs $(kubectl get pods -n default | grep rollback | awk "
                + "'{ print $1 }')",
                shell=True).decode('utf8')
            print(logs)
            assert False, "Failed to perform rollback, see logs"
        if time() - start_time > timeout:
            logs = check_output(
                f"kubectl logs $(kubectl get pods -n default | grep rollback | awk "
                + "'{ print $1 }')",
                shell=True).decode('utf8')
            print(logs)
            assert False, "Failed to perform rollback (timeout!), see logs"
    result = check_output(
        f"helm3 history astronomer -n astronomer | tail -n 1",
        shell=True).decode('utf8')
    assert "0.16" in result and "deployed" in result, "Expected rollback to be performed"
예제 #6
0
org = os.environ['GIT_ORG']
repository = os.environ['CIRCLE_PROJECT_REPONAME']
github = Github()
repo = github.get_repo(f'{ org }/{ repository }')

release_regex = re.compile("release-(\d*\.\d*)")
major_minor_version = release_regex.findall(branch)
most_recent_tag = None

if not len(major_minor_version):
    raise Exception("ERROR: we are not on a release branch. Branch should be named release-X.Y where X and Y are positive integers")
major_minor_version = major_minor_version[0]
print(f"We are on a release branch: {branch}, detected major.minor version {major_minor_version}", file=sys.stderr)
print(f"We will find the most recent patch version of {major_minor_version} and return it incremented by one", file=sys.stderr)
for release in repo.get_releases():
    version = semver(release.tag_name).release
    this_major_minor = f"{version[0]}.{version[1]}"
    if this_major_minor == major_minor_version:
        most_recent_tag = release.tag_name
        print(f"The most recent tag matching this release is {most_recent_tag}", file=sys.stderr)
        break

if most_recent_tag:
    base_version = semver(most_recent_tag).base_version
    print(f"Parsed base version as {base_version}", file=sys.stderr)
    base_version = semver(base_version)
    major, minor, patch = base_version.release
    patch += 1
    new_version = ".".join(str(i) for i in [major, minor, patch])
else:
    print("Did not detect a most recent version. Setting patch number to zero.", file=sys.stderr)
예제 #7
0
def test_upgrade():
    """
    Functional test for the LTS to LTS upgrade (0.16 to 0.23)
    """
    with open(Path(git_root_dir / "Chart.yaml"), "r") as f:
        astro_chart_dot_yaml = yaml.safe_load(f.read())
    major, minor, patch = semver(astro_chart_dot_yaml["version"]).release

    assert major == 0 and minor == 23, "This test is only applicable for 0.23"

    upgrade_manifest_path = Path(
        git_root_dir /
        "bin/migration-scripts/lts-to-lts/0.16-to-0.23/manifests/upgrade-0.16-to-0.23.yaml"
    )
    rollback_manifest_path = Path(
        git_root_dir /
        "bin/migration-scripts/lts-to-lts/0.16-to-0.23/manifests/rollback-0.16-to-0.23.yaml"
    )

    namespace = environ.get("NAMESPACE")
    release_name = environ.get("RELEASE_NAME")
    if not namespace:
        print("NAMESPACE env var is not present, using 'astronomer' namespace")
        namespace = "astronomer"
    if not release_name:
        print(
            "RELEASE_NAME env var is not present, assuming 'astronomer' is the release name"
        )
        release_name = "astronomer"

    # Get the existing values
    result = check_output(
        f"helm3 history { release_name } -n { namespace } | tail -n 1",
        shell=True).decode("utf8")
    assert "0.16" in result

    # Rewrite some parts of the k8s manifest with testing-specific configs
    with open(upgrade_manifest_path, "r") as f:
        upgrade_manifest_data = f.read()
    upgrade_manifest_data = upgrade_manifest_data.replace(
        "image: quay.io/astronomer/lts-016-023-upgrade:latest",
        "image: lts-016-023-upgrade:latest",
    )
    upgrade_manifest_data = upgrade_manifest_data.replace(
        "imagePullPolicy: Always", "imagePullPolicy: Never")
    upgrade_manifest_yaml = [
        doc for doc in yaml.safe_load_all(upgrade_manifest_data)
    ]
    for i, doc in enumerate(upgrade_manifest_yaml):
        if doc.get("kind") == "Job":
            try:
                containers = doc["spec"]["template"]["spec"]["containers"]
                for container in containers:
                    if not container.get("env"):
                        container["env"] = []
                    container["env"].append({
                        "name": "USE_INTERNAL_HELM_REPO",
                        "value": "True"
                    })
                upgrade_manifest_yaml[i] = doc
            except KeyError:
                pass

    upgrade_manifest_data = yaml.safe_dump_all(upgrade_manifest_yaml)

    modified_upgrade_manifest_path = f"{upgrade_manifest_path}.test.yaml"
    with open(modified_upgrade_manifest_path, "w") as f:
        f.write(upgrade_manifest_data)
    check_output(f"kubectl apply -f {modified_upgrade_manifest_path}",
                 shell=True)
    timeout = 800
    start_time = time()
    while True:
        sleep(5)
        result = check_output(
            "kubectl get pods -n default | grep upgrade-astronomer",
            shell=True).decode("utf8")
        if "Completed" in result:
            print("Upgrade pod finished in success")
            break
        if "Error" in result:
            print("Upgrade pod finished in error")
            logs = check_output(
                "kubectl logs $(kubectl get pods -n default | grep upgrade-astronomer | awk "
                + "'{ print $1 }')",
                shell=True,
            ).decode("utf8")
            print(logs)
            assert False, "Failed to perform upgrade, see logs"
        if time() - start_time > timeout:
            logs = check_output(
                "kubectl logs $(kubectl get pods -n default | grep upgrade-astronomer | awk "
                + "'{ print $1 }')",
                shell=True,
            ).decode("utf8")
            print(logs)
            assert False, "Failed to perform upgrade (timeout!), see logs"
    result = check_output("helm3 history astronomer -n astronomer | tail -n 1",
                          shell=True).decode("utf8")
    assert "0.23" in result and "deployed" in result, "Expected upgrade to be performed"
    with open(rollback_manifest_path, "r") as f:
        rollback_manifest_data = f.read()
    rollback_manifest_data = rollback_manifest_data.replace(
        "image: quay.io/astronomer/lts-016-023-upgrade:latest",
        "image: lts-016-023-upgrade:latest",
    )
    rollback_manifest_data = rollback_manifest_data.replace(
        "imagePullPolicy: Always", "imagePullPolicy: Never")
    with open(f"{rollback_manifest_path}.test.yaml", "w") as f:
        f.write(rollback_manifest_data)
    check_output(f"kubectl apply -f {rollback_manifest_path}.test.yaml",
                 shell=True)
    timeout = 800
    start_time = time()
    while True:
        sleep(5)
        result = check_output("kubectl get pods -n default | grep rollback",
                              shell=True).decode("utf8")
        if "Completed" in result:
            print("Rollback pod finished in success")
            break
        if "Error" in result:
            print("Rollback pod finished in error")
            logs = check_output(
                "kubectl logs $(kubectl get pods -n default | grep rollback | awk "
                + "'{ print $1 }')",
                shell=True,
            ).decode("utf8")
            print(logs)
            assert False, "Failed to perform rollback, see logs"
        if time() - start_time > timeout:
            logs = check_output(
                "kubectl logs $(kubectl get pods -n default | grep rollback | awk "
                + "'{ print $1 }')",
                shell=True,
            ).decode("utf8")
            print(logs)
            assert False, "Failed to perform rollback (timeout!), see logs"
    result = check_output("helm3 history astronomer -n astronomer | tail -n 1",
                          shell=True).decode("utf8")
    assert ("0.16" in result
            and "deployed" in result), "Expected rollback to be performed"