Ejemplo n.º 1
0
def install(ctx, config):
    """
    Installs kubernetes deployment
    """
    settings_dict = get_settings()
    config_dict = settings_dict['configs'][config]
    set_context(ctx, config)

    helm_bin = get_helm_bin(config_dict)

    install_flag = ''

    if config_dict.get('helm_version') and version.parse(
            str(config_dict['helm_version'])) <= version.parse('3'):
        install_flag = " --name"

    ctx.run(
        '{helm_bin} repo add rehive https://rehive.github.io/charts'.format(
            helm_bin=helm_bin),
        echo=True)
    ctx.run('{helm_bin} install{helm_install_flag} {project_name} '
            '--values {helm_values_path} '
            '--version {helm_chart_version} {helm_chart}'.format(
                helm_bin=helm_bin,
                project_name=config_dict['project_name'],
                helm_install_flag=install_flag,
                helm_values_path=config_dict['helm_values_path'],
                helm_chart=config_dict['helm_chart'],
                helm_chart_version=config_dict['helm_chart_version']),
            echo=True)
Ejemplo n.º 2
0
def shell(ctx, config):
    """Exec into the management container"""
    set_context(ctx, config)
    settings_dict = get_settings()
    config_dict = settings_dict['configs'][config]
    management_cmd = build_management_cmd(config_dict, "/bin/bash")
    ctx.run(management_cmd, pty=True, warn=False, echo=True)
Ejemplo n.º 3
0
def template_install(ctx, config):
    """
    Installs kubernetes deployment from a helm template
    """

    settings_dict = get_settings()
    config_dict = settings_dict['configs'][config]
    set_context(ctx, config)

    repository = 'https://rehive.github.io/charts'
    chart_directory = "var/helm/chart/{config}".format(config=config)
    manifest_directory = "var/helm/manifests/{config}".format(config=config)
    log_directory = "var/helm/log/{config}".format(config=config)
    err_file = "{log_dir}/template_install.error.log".format(
        log_dir=log_directory)
    out_file = "{log_dir}/template_install.out.log".format(
        log_dir=log_directory)
    chart_name = config_dict["helm_chart"]

    if len(chart_name.split('/')) > 0:
        chart_name = chart_name.spliat('/')[1]

    ctx.run('mkdir -p {chart_dir} {manifest_dir} {log_dir}'.format(
        chart_dir=chart_directory,
        manifest_dir=manifest_directory,
        log_dir=log_directory),
            echo=False)

    ctx.run('helm fetch --repo {repository} --untar '
            '--untardir {chart_dir} '
            '--version {version} {chart_name}'.format(
                repository=repository,
                chart_dir=chart_directory,
                version=config_dict['helm_chart_version'],
                chart_name=chart_name),
            echo=True)

    ctx.run('helm template {chart_dir}/{chart_name} '
            '--values {values_file} '
            '--name {release_name} '
            '--namespace {namespace} '
            '--output-dir {manifest_dir} '.format(
                chart_dir=chart_directory,
                chart_name=chart_name,
                manifest_dir=manifest_directory,
                namespace=config_dict['namespace'],
                release_name=config_dict['project_name'],
                values_file=config_dict['helm_values_path']),
            err_stream=open(err_file, 'w'),
            out_stream=open(out_file, 'w'),
            echo=True)

    ctx.run('kubectl create namespace {namespace} || '
            'kubectl apply --recursive '
            '--filename {manifest_dir}/{chart_name} '
            '--namespace {namespace} '.format(
                chart_name=chart_name,
                manifest_dir=manifest_directory,
                namespace=config_dict['namespace']),
            echo=True)
Ejemplo n.º 4
0
def manage(ctx, config, cmd, tag=None):
    """Exec into the management container"""
    set_context(ctx, config)
    settings_dict = get_settings()
    config_dict = settings_dict['configs'][config]
    management_cmd = build_management_cmd(config_dict,
                                          f'python manage.py {cmd}', tag)
    ctx.run(management_cmd, pty=True, warn=False, echo=True)
Ejemplo n.º 5
0
def helm(ctx, config, command):
    settings_dict = get_settings()
    config_dict = settings_dict['configs'][config]
    set_context(ctx, config)

    helm_bin = get_helm_bin(config_dict)

    ctx.run('{helm_bin} {command}'.format(helm_bin=helm_bin, command=command),
            echo=True)
Ejemplo n.º 6
0
def activate(ctx, config):
    """Fetches and sets the project, cluster and namespace"""
    settings_dict = get_settings()
    config_dict = settings_dict['configs'][config]
    set_project(ctx, config)
    set_cluster(ctx, config)
    ctx.run(
        'kubectl config use-context $(kubectl config current-context)'
        ' --namespace={namespace}'.format(namespace=config_dict['namespace']),
        echo=True)
Ejemplo n.º 7
0
def create_namespace(ctx, config):
    """
    Updates kubernetes deployment to use specified version
    """
    settings_dict = get_settings()
    config_dict = settings_dict['configs'][config]
    set_context(ctx, config)

    ctx.run('kubectl create namespace {namespace}'.format(
        namespace=config_dict['namespace']),
            echo=True)
Ejemplo n.º 8
0
def build(ctx, config, tag):
    """
    Build project's docker image and pushes to remote repo
    """
    settings_dict = get_settings()
    config_dict = settings_dict['configs'][config]
    set_project(ctx, config)
    image_name = config_dict['docker_image'].split(':')[0]
    image = '{}:{}'.format(image_name, tag)
    ctx.run('docker build -t %s -f etc/docker/Dockerfile .' % image, echo=True)
    ctx.run('gcloud auth configure-docker', echo=True)
    ctx.run('docker push %s' % image, echo=True)
    return image
Ejemplo n.º 9
0
def live_image(ctx, config):
    """Displays the current docker image and version deployed"""
    settings_dict = get_settings()
    config_dict = settings_dict['configs'][config]
    set_context(ctx, config)

    result = ctx.run(
        'kubectl get deployment {project_name} --output=json'.format(
            project_name=config_dict['project_name']),
        echo=True,
        hide='stdout')
    server_config = json.loads(result.stdout)
    image = server_config['spec']['template']['spec']['containers'][0]['image']
    print(image)
Ejemplo n.º 10
0
def upload_secrets(ctx, config, env_file):
    """
    Updates kubernetes deployment to use specified version
    """
    settings_dict = get_settings()
    config_dict = settings_dict['configs'][config]
    set_context(ctx, config)

    ctx.run('kubectl delete secret {project_name}'\
            .format(project_name=config_dict['project_name'],
                    namespace=config_dict['namespace']),
            warn=True)

    ctx.run('kubectl create secret generic {project_name}'
            ' --from-env-file {env_file}'.format(
                project_name=config_dict['project_name'], env_file=env_file))
Ejemplo n.º 11
0
def helm_setup(ctx, config):
    settings_dict = get_settings()
    config_dict = settings_dict['configs'][config]

    helm_version = config_dict.get('helm_version')
    if not helm_version:
        print('Please add the helm_version config to rdeploy.yaml.')
        return

    if config_dict.get('use_system_helm', True):
        print('Please add the following config to rdeploy.yaml:\n'
              'use_system_helm: false')
        return

    if sys.platform == 'linux' or sys.platform == 'linux2':
        os_string = 'linux-amd64'
        archive_tool = tarfile
    elif sys.platform == 'darwin':
        os_string = 'darwin-amd64'
        archive_tool = tarfile
    elif sys.platform == 'win32':
        os_string = 'windows-amd64'
        archive_tool = zipfile

    url = 'https://get.helm.sh/helm-v{version}-{os_string}.tar.gz'.format(
        version=helm_version, os_string=os_string)
    file_tmp = urllib.request.urlretrieve(url, filename=None)[0]
    tar = archive_tool.open(file_tmp)
    tar.extractall('./opt/helm-v{version}'.format(version=helm_version))

    helm_bin = get_helm_bin(config_dict)
    ctx.run('{helm_bin} repo add stable https://charts.helm.sh/stable'.format(
        helm_bin=helm_bin),
            echo=True)
    ctx.run(
        '{helm_bin} repo add rehive https://rehive.github.io/charts'.format(
            helm_bin=helm_bin),
        echo=True)

    print(
        'Successfully installed helm to opt/helm-v{version}/{os_string}/ \n'
        'Please make sure this directory has been added to .gitignore.'.format(
            version=helm_version, os_string=os_string))
Ejemplo n.º 12
0
def set_project(ctx, config):
    """Sets the active gcloud project"""
    settings_dict = get_settings()
    config_dict = settings_dict['configs'][config]
    if settings_dict.get('version') and version.parse(
            str(settings_dict['version'])) > version.parse('1'):
        provider_data = config_dict.get('cloud_provider')
        if provider_data and provider_data['name'] == 'azure':
            ctx.run('az account set -s {subscription}'.format(
                subscription=provider_data['subscription_id']),
                    echo=True)
        elif provider_data and provider_data['name'] == 'gcp':
            ctx.run('gcloud config set project {project}'.format(
                project=provider_data['project']),
                    echo=True)
    else:
        ctx.run('gcloud config set project {project}'.format(
            project=config_dict['cloud_project']),
                echo=True)
Ejemplo n.º 13
0
def upgrade(ctx, config, version):
    """
    Upgrades kubernetes deployment
    """

    settings_dict = get_settings()
    config_dict = settings_dict['configs'][config]
    set_context(ctx, config)

    helm_bin = get_helm_bin(config_dict)

    ctx.run('{helm_bin} upgrade {project_name} '
            '--values {helm_values_path} '
            '--set image.tag={version} '
            '--version {helm_chart_version} {helm_chart}'.format(
                helm_bin=helm_bin,
                project_name=config_dict['project_name'],
                helm_chart=config_dict['helm_chart'],
                helm_values_path=config_dict['helm_values_path'],
                version=version,
                helm_chart_version=config_dict['helm_chart_version']),
            echo=True)
Ejemplo n.º 14
0
def cloudbuild(ctx, config, tag):
    """
    Build project's docker image using google cloud builder and pushes to remote repo
    """
    settings_dict = get_settings()
    config_dict = settings_dict['configs'][config]
    image_name = config_dict['docker_image'].split(':')[0]

    if config_dict.get('container_registry_provider') == 'google':
        project = config_dict['docker_image'].split('/')[1]
        ctx.run('gcloud config set project {project}'.format(project=project),
                echo=True)
    else:
        set_project(ctx, config)

    if settings_dict.get('version') and version.parse(
            str(settings_dict['version'])) > version.parse('1'):
        provider_data = config_dict.get('cloud_provider')

        def azure_image_build(container_registry, image_name, tag):
            ctx.run('az acr run'
                    ' -r {container_registry}'
                    ' -f ./etc/docker/acr.yaml'
                    ' --set IMAGE={image_name}'
                    ' --set TAG_NAME={tag_name}'
                    ' .'.format(container_registry=container_registry,
                                image_name=image_name,
                                tag_name=tag),
                    echo=True)

        def google_image_build(project, image_name, tag):
            log_dir = "gs://{project}-cloudbuild-logs/{image}/{tag_name}/".format(
                project=project, image=image_name, tag_name=tag)
            ctx.run('gcloud builds submit .'
                    ' --config etc/docker/cloudbuild.yaml'
                    ' --substitutions _IMAGE={image_name},TAG_NAME={tag_name}'
                    ' --gcs-log-dir {log_dir}'.format(image_name=image_name,
                                                      tag_name=tag,
                                                      log_dir=log_dir),
                    echo=True)

        if config_dict.get('container_registry_provider') == 'azure':
            azure_image_build(provider_data['container_registry'], image_name,
                              tag)

        elif config_dict.get('container_registry_provider') == 'google':
            project = config_dict['docker_image'].split('/')[1]
            google_image_build(project, image_name, tag)

        else:
            if provider_data and provider_data['name'] == 'azure':
                azure_image_build(provider_data['container_registry'],
                                  image_name, tag)
            else:
                google_image_build(provider_data['project'], image_name, tag)

    else:
        log_dir = "gs://{project}-cloudbuild-logs/{image}/{tag_name}/".format(
            project=config_dict['cloud_project'],
            image=image_name,
            tag_name=tag)
        ctx.run('gcloud builds submit .'
                ' --config etc/docker/cloudbuild-no-cache.yaml'
                ' --substitutions _IMAGE={image_name},TAG_NAME={tag_name}'
                ' --gcs-log-dir {log_dir}'.format(image_name=image_name,
                                                  tag_name=tag,
                                                  log_dir=log_dir),
                echo=True)
Ejemplo n.º 15
0
def set_cluster(ctx, config):
    """Sets the active cluster"""
    settings_dict = get_settings()
    config_dict = settings_dict['configs'][config]

    if settings_dict.get('version') and version.parse(
            str(settings_dict['version'])) > version.parse('1'):
        provider_data = config_dict.get('cloud_provider')
        if provider_data['name'] == 'azure':
            ctx.run(
                'az aks get-credentials -g {group} -n {cluster} --context aks-{region}-{cluster} --context {name}_{cluster}_{region}  --overwrite-existing'
                .format(group=provider_data['resource_group'],
                        cluster=provider_data['kube_cluster'],
                        region=provider_data['region'],
                        name=provider_data['name']),
                echo=True)
        elif provider_data['name'] == 'gcp':
            if provider_data.get('zone'):
                zone_or_region_param = '--zone {}'.format(
                    provider_data['zone'])
                zone = provider_data['zone']
            elif provider_data.get('region'):
                zone_or_region_param = '--region {}'.format(
                    provider_data['region'])
                zone = provider_data['region']

            ctx.run('gcloud container clusters get-credentials {cluster}'
                    ' --project {project} {zone_or_region_param}'.format(
                        cluster=provider_data['kube_cluster'],
                        project=provider_data['project'],
                        zone_or_region_param=zone_or_region_param),
                    echo=True)

            ctx.run(
                'kubectl config rename-context gke_{project}_{zone}_{cluster}'
                ' {name}_{project}_{cluster}_{zone}'.format(
                    cluster=provider_data['kube_cluster'],
                    project=provider_data['project'],
                    name=provider_data['name'],
                    zone=zone),
                echo=True)
        else:
            sys.exit(f"Unsupported provider: {provider_data['name']}")
    else:
        if config_dict.get('cloud_zone'):
            zone_or_region_param = '--zone {}'.format(
                config_dict['cloud_zone'])
            zone = config_dict['cloud_zone']
        elif config_dict.get('cloud_region'):
            zone_or_region_param = '--region {}'.format(
                config_dict['cloud_region'])
            zone = config_dict['cloud_region']
        else:
            zone_or_region_param = '--zone europe-west1-c'
            zone = 'europe-west1-c'

        ctx.run('gcloud container clusters get-credentials {cluster}'
                ' --project {project} {zone_or_region_param}'.format(
                    cluster=config_dict['cluster'],
                    project=config_dict['cloud_project'],
                    zone_or_region_param=zone_or_region_param),
                echo=True)

        ctx.run('kubectl config rename-context gke_{project}_{zone}_{cluster}'
                ' gcp_{project}_{cluster}_{zone}'.format(
                    cluster=config_dict['cluster'],
                    project=config_dict['cloud_project'],
                    zone=zone),
                echo=True)
Ejemplo n.º 16
0
def set_context(ctx, config):
    """Switch cluster and namespace"""
    settings_dict = get_settings()
    config_dict = settings_dict['configs'][config]
    provider_data = config_dict.get('cloud_provider')

    # Check for future versions
    if settings_dict.get('version') and version.parse(
            str(settings_dict['version'])) > version.parse('3'):
        sys.exit(
            f"Unsupported rdeploy.yaml version, please upgrade rdeploy or double check the version number."
        )

    # v3 of the config file uses the kube_context value to set the kubernetes cluster context
    # whereas previous versions used the GCP/AZ tools to set it and a naming convention
    elif str(settings_dict.get('version')) == '3' and config_dict.get(
            'kube_context'):
        ctx.run('kubectl config use-context {kube_context}'.format(
            kube_context=config_dict['kube_context']),
                echo=True)
        ctx.run('kubectl config set-context --current --namespace={namespace}'.
                format(namespace=config_dict['namespace']),
                echo=True)

    # v2 (or v3 when kube_context is not specified)
    elif version.parse(str(settings_dict['version'])) >= version.parse('2'):
        if provider_data.get('name') == 'gcp':
            if provider_data.get('zone') is not None:
                get_zone = provider_data['zone']
            elif provider_data.get('region') is not None:
                get_zone = provider_data['region']

            ctx.run(
                'kubectl config use-context {name}_{project}_{cluster}_{zone}'
                ' --namespace={namespace}'.format(
                    namespace=config_dict['namespace'],
                    project=provider_data['project'],
                    cluster=provider_data['kube_cluster'],
                    name=provider_data['name'],
                    zone=get_zone),
                echo=True)
            ctx.run('kubectl config set-context --current'
                    ' --namespace={namespace}'.format(
                        namespace=config_dict['namespace']),
                    echo=True)

        elif provider_data.get('name') == 'azure':
            ctx.run('kubectl config use-context {name}_{cluster}_{region}'
                    ' --namespace={namespace}'.format(
                        namespace=config_dict['namespace'],
                        cluster=provider_data['kube_cluster'],
                        name=provider_data['name'],
                        region=provider_data['region']),
                    echo=True)
            ctx.run('kubectl config set-context --current'
                    ' --namespace={namespace}'.format(
                        namespace=config_dict['namespace']),
                    echo=True)
        else:
            sys.exit(
                f"Invalid provider name in rdeploy file: {provider_data.get('name')}"
            )

    # Config file v1 or no version
    # Backwards compatible with initial version of rdeploy where config file was not yet versioned.
    else:
        ctx.run(
            'kubectl config use-context gcp_{cloud_project}_{cluster}_europe-west1-c'
            ' --namespace={namespace}'.format(
                namespace=config_dict['namespace'],
                cloud_project=config_dict['cloud_project'],
                cluster=config_dict['cluster']),
            echo=True)
        ctx.run('kubectl config set-context --current'
                ' --namespace={namespace}'.format(
                    namespace=config_dict['namespace']),
                echo=True)