def init(ctx, kube_context, submodules, repopath):
    """Init the platform by doing submodule init and checkout
    all submodules on master"""

    # Get the repo from arguments defaults to cwd
    repo = get_repo(repopath)
    submodules = get_submodules(repo, submodules)

    with click_spinner.spinner():
        repo.submodule_update()
    logger.info('Platform initialized.')
Exemple #2
0
def status(ctx, kube_context):
    """Check the status of the k3d cluster"""
    # Check if the cluster exists
    kube_context = ctx.kube_context
    if k3d.k3d_get(kube_context):
        if kube.kubectl_info(kube_context):
            logger.info('K3D cluster \'' + kube_context + '\' is running')
        else:
            logger.error('Cluster not running. Please start the cluster')
            raise click.Abort()
    else:
        logger.error('K3D cluster \'' + kube_context + '\' does not exist.')
def info(ctx, kube_context):
    """Get info on accessing the platform"""
    kube_context = ctx.kube_context

    try:
        k1s_host = s.run([
            'kubectl', '--context', 'k3d-' + kube_context, '-n', 'k1s', 'get',
            'ingressroute', 'ui', '-o', 'jsonpath={.spec.routes[0].match}'
        ],
                         capture_output=True,
                         check=True)
        k1s_host = k1s_host.stdout.decode('utf-8')
        k1s_host = k1s_host.split('`')
        k1s_url = k1s_host[1]
        logger.info('K1S can be accessed through the URL:')
        logger.info('https://' + k1s_url + '/')
    except s.CalledProcessError as error:
        logger.debug(error.stderr.decode('utf-8'))
        raise click.Abort()
def token(ctx, kube_context):
    """Get the platform token required by Kubernetes Dashboard"""
    kube_context = ctx.kube_context

    try:
        proc1 = s.Popen([
            'kubectl', '--context', 'k3d-' + kube_context, '-n', 'monitoring',
            'describe', 'secret', 'k1s-admin'
        ],
                        stdout=s.PIPE)
        proc2 = s.Popen(['grep', 'token:'],
                        stdin=proc1.stdout,
                        stdout=s.PIPE,
                        universal_newlines=True)
        proc1.stdout.close()
        out = proc2.communicate()[0]
        logger.info('The platform token is:\n')
        logger.info(out)
    except s.CalledProcessError as error:
        logger.debug(error.stderr.decode('utf-8'))
        raise click.Abort()
Exemple #5
0
def stop(ctx, kube_context):
    """Stop k3d cluster"""
    # Check the cluster status
    kube_context = ctx.kube_context
    if k3d.k3d_get(kube_context):
        if not kube.kubectl_info(kube_context):
            logger.info('K3D cluster \'' + kube_context +
                        '\' is already stopped')
            raise click.Abort()
    elif not k3d.k3d_get(kube_context):
        logger.error('K3D cluster \'' + kube_context + '\' doesn\'t exist')
        raise click.Abort()

    # Stop the k3d cluster
    try:
        logger.debug('Running: `k3d cluster stop`')
        _stop_cluster = s.run(['k3d',
                                'cluster',
                                'stop',
                                kube_context],
                               capture_output=False, check=True)
    except s.CalledProcessError as error:
        logger.critical('Could not stop k3d cluster' +
                        error.stderr.decode('utf-8'))
Exemple #6
0
def ns(ctx, kube_context, name):
    """Create a namespace"""
    kube_context = ctx.kube_context

    # Create a namespace in kubernetes
    ns_exists = s.run(
        ['kubectl', 'get', 'ns', name, '--context', 'k3d-' + kube_context],
        capture_output=True)
    if ns_exists.returncode != 0:
        try:
            _app_ns = s.run([
                'kubectl', 'create', 'ns', name, '--context',
                'k3d-' + kube_context
            ],
                            capture_output=True,
                            check=True)
            logger.info('Created a namespace for ' + name)
        except s.CalledProcessError as error:
            logger.error('Something went wrong with namespace: ' +
                         error.stderr.decode('utf-8'))
            raise click.Abort()
    else:
        logger.info('Skipping creation of ' + name + ' namespace '
                    'since it already exists.')
Exemple #7
0
def init(ctx, kube_context):
    """Download binaries for all dependencies"""

    # Figure out what kind of OS we are on
    ostype = os.uname().sysname.lower()

    # Kubectl parameters
    kubectl_stable = s.check_output([
        'curl', '-s',
        'https://storage.googleapis.com/kubernetes-release/release/stable.txt'
    ]).decode('utf-8')
    kubectl_url = 'https://storage.googleapis.com/kubernetes-release/release/{}/bin/linux/arm/kubectl'.format(
        kubectl_stable.split('\n')[0])

    # Helm parameters
    helm_url = 'https://get.helm.sh/helm-v3.4.2-{}-arm.tar.gz'.format(ostype)

    # K3D parameters
    k3d_url = 'https://github.com/rancher/k3d/releases/download/v3.4.0/k3d-{}-arm'.format(
        ostype)

    # Skaffold parameters
    skaffold_url = 'https://github.com/nushkovg/skaffold/releases/download/v1.17.2-arm/skaffold-{}-arm'.format(
        ostype)

    with click_spinner.spinner():
        # Download kubectl
        logger.info('Downloading kubectl...')
        urllib.request.urlretrieve(kubectl_url, 'bin/kubectl')
        st = os.stat('bin/kubectl')
        os.chmod('bin/kubectl', st.st_mode | stat.S_IEXEC)
        logger.info('kubectl downloaded')

        # Download helm
        logger.info('Downloading helm...')
        urllib.request.urlretrieve(helm_url, 'bin/helm.tar.gz')
        tar = tarfile.open('bin/helm.tar.gz', 'r:gz')
        helm_file = '{}-arm/helm'.format(ostype)
        for member in tar.getmembers():
            if member.name == helm_file:
                tar.extract(helm_file, 'bin')
                os.rename('bin/' + helm_file, 'bin/helm')
        tar.close()
        os.remove('bin/helm.tar.gz')
        os.removedirs('bin/{}-arm'.format(ostype))
        logger.info('helm downloaded!')

        # Download k3d
        logger.info('Downloading k3d...')
        urllib.request.urlretrieve(k3d_url, 'bin/k3d')
        st = os.stat('bin/k3d')
        os.chmod('bin/k3d', st.st_mode | stat.S_IEXEC)
        logger.info('k3d downloaded')

        # Download skaffold
        logger.info('Downloading skaffold...')
        urllib.request.urlretrieve(skaffold_url, 'bin/skaffold')
        st = os.stat('bin/skaffold')
        os.chmod('bin/skaffold', st.st_mode | stat.S_IEXEC)
        logger.info('skaffold downloaded')

    logger.info('All dependencies downloaded to bin/')
    logger.info('IMPORTANT: Please add the path to your user profile to ' +
                os.getcwd() + '/bin directory at the beginning of your PATH')
    logger.info('$ echo export PATH=' + os.getcwd() +
                '/bin:$PATH >> ~/.profile')
    logger.info('$ source ~/.profile')
def cli(ctx, kube_context):
    """Preflight checks to ensure all tools and versions are present"""
    # Check go
    try:
        go_ver = s.run(['go', 'version'], capture_output=True, check=True)
        logger.info('Found go.')
        logger.debug(go_ver.stdout.decode('utf-8'))
    except FileNotFoundError:
        logger.critical('go not found in PATH.')
    except s.CalledProcessError as error:
        logger.critical('go version returned something unexpected: ' +
                        error.stderr.decode('utf-8'))

    # Check docker
    try:
        docker_ps = s.run(['docker', 'ps'], capture_output=True, check=True)
        logger.info('Found docker.')
        logger.debug(docker_ps.stdout.decode('utf-8'))
    except FileNotFoundError:
        logger.critical('docker not found in PATH.')
    except s.CalledProcessError as error:
        logger.critical('`docker ps` returned something unexpected: ' +
                        error.stderr.decode('utf-8'))
        logger.critical('Please ensure the docker daemon is running and that '
                        'your user is part of the docker group. See README')

    # Check helm 3
    try:
        helm_ver = s.run(['helm', 'version', '--short'],
                         capture_output=True,
                         check=True)
        # Check that we have helm 3
        if helm_ver.stdout.decode('utf-8')[1] != "3":
            logger.error(
                'Old version of helm detected when running "helm" from PATH.')
        else:
            logger.info('Found helm.')
            logger.debug(helm_ver.stdout.decode('utf-8'))
    except FileNotFoundError:
        logger.critical('helm not found in PATH.')
    except s.CalledProcessError as error:
        logger.critical('helm version returned something unexpected: ' +
                        error.stderr.decode('utf-8'))

    # Check k3d
    try:
        k3d_ver = s.run(['k3d', 'version'], capture_output=True, check=True)
        logger.info('Found k3d.')
        logger.debug(k3d_ver.stdout.decode('utf-8'))
    except FileNotFoundError:
        logger.critical('k3d not found in PATH.')
    except s.CalledProcessError as error:
        logger.critical('k3d version returned something unexpected: ' +
                        error.stderr.decode('utf-8'))

    # Check skaffold
    try:
        skaffold_ver = s.run(['skaffold', 'version'],
                             capture_output=True,
                             check=True)
        logger.info('Found skaffold.')
        logger.debug(skaffold_ver.stdout.decode('utf-8'))
    except FileNotFoundError:
        logger.critical('skaffold not found in PATH.')
    except s.CalledProcessError as error:
        logger.critical('skaffold version returned something unexpected: ' +
                        error.stderr.decode('utf-8'))

    # Check kubectl
    try:
        kubectl_ver = s.run(['kubectl', 'version', '--client=true'],
                            capture_output=True,
                            check=True)
        logger.info('Found kubectl.')
        logger.debug(kubectl_ver.stdout.decode('utf-8'))
    except FileNotFoundError:
        logger.critical('kubectl not found in PATH.')
    except s.CalledProcessError as error:
        logger.critical('kubectl version returned something unexpected: ' +
                        error.stderr.decode('utf-8'))
def version(ctx, kube_context, submodules, repopath):
    """Check versions of services in git submodules
    You can provide a comma separated list of submodules
    or you can use 'all' for all submodules"""

    # Get the repo from arguments defaults to cwd
    repo = get_repo(repopath)
    submodules = get_submodules(repo, submodules)

    # Do something with the submodules
    all_sm_details = []
    with click_spinner.spinner():
        for submodule in submodules:
            logger.debug('Switched to submodule: ' + submodule)
            sm_details = {}
            sm_details['repo'] = submodule
            # Are we on an active branch? on a tag? if not then get sha?
            try:
                smrepo = git.Repo(submodule)
                sm_details['present'] = True
            except git.InvalidGitRepositoryError as error:
                logger.warning(submodule + ': not present')
                sm_details['present'] = False
                all_sm_details.append(sm_details)
                continue

            # Get branch
            try:
                branch = smrepo.active_branch.name
                sm_details['branch'] = branch

                # Check if remotes are ahead or behind
                origin = smrepo.remotes.origin
                origin.fetch()
                commits_behind = smrepo.iter_commits(branch + '..origin/' +
                                                     branch)
                commits_ahead = smrepo.iter_commits('origin/' + branch + '..' +
                                                    branch)
                sm_details['commits_ahead'] = sum(1 for c in commits_ahead)
                sm_details['commits_behind'] = sum(1 for c in commits_behind)
            except TypeError as error:
                sm_details['branch'] = ''
                logger.debug(error)

            # Check if we point to any tags
            points_at_tag = smrepo.git.tag('--points-at', 'HEAD')
            sm_details['tag'] = points_at_tag

            # Get sha of HEAD
            sha = smrepo.head.commit.hexsha
            sm_details['sha'] = sha

            # Add submodule details to the list
            all_sm_details.append(sm_details)

    logger.debug('Received following details about the platform submodules:')
    logger.debug(all_sm_details)
    for sm_details in all_sm_details:
        logger.info(sm_details['repo'] + ':')
        logger.info('Branch: ' + sm_details['branch'])
        logger.info('SHA: ' + sm_details['sha'])
        if sm_details['tag']:
            logger.info('Tag: ' + sm_details['tag'])
        if sm_details['commits_ahead'] > 0:
            logger.info('Ahead by: ' + str(sm_details['commits_ahead']) +
                        ' commits')
        if sm_details['commits_behind'] > 0:
            logger.info('Behind by: ' + str(sm_details['commits_behind']) +
                        ' commits')
Exemple #10
0
def create(ctx, kube_context):
    """Create a k3d cluster"""
    # Check if k3d cluster is already created
    kube_context = ctx.kube_context
    if k3d.k3d_get(kube_context):
        logger.error('K3D cluster \'' + kube_context + '\' already exists')
        raise click.Abort()

    # Create the k3d cluster
    try:
        logger.debug('Running: `k3d cluster create`')
        _create_cluster = s.run(['k3d',
                                'cluster',
                                'create',
                                '--k3s-server-arg',
                                '--no-deploy=traefik',
                                '--port',
                                '80:80@loadbalancer',
                                '--port',
                                '443:443@loadbalancer',
                                '--port',
                                '8080:8080@loadbalancer',
                                kube_context],
                               capture_output=False, check=True)
    except s.CalledProcessError as error:
        logger.critical('Could not create k3d cluster' +
                        error.stderr.decode('utf-8'))

    # Create required namespaces
    namespaces = [kube_context, 'traefik', 'monitoring']

    for ns in namespaces:
        ns_exists = s.run(['kubectl',
                        'get',
                        'ns',
                        ns,
                        '--context',
                        'k3d-' + kube_context],
                        capture_output=True)
        if ns_exists.returncode != 0:
            try:
                _app_ns = s.run(['kubectl',
                                'create',
                                'ns',
                                ns,
                                '--context',
                                'k3d-' + kube_context],
                            check=True, stdout=s.DEVNULL)
            except s.CalledProcessError as error:
                logger.error('Something went wrong with namespace: ' +
                            error.stderr.decode('utf-8'))
                raise click.Abort()
        else:
            logger.info('Skipping creation of ' + ns + ' namespace '
                        'since it already exists.')

    # Apply traefik CRD definitions
    try:
        crd_path = 'infrastructure/k1s-traefik/manifests/001-crds.yaml'
        logger.debug('Running: `kubectl apply -f {}`'.format(crd_path))
        _apply_crds = s.run(['kubectl',
                                'apply',
                                '-f',
                                crd_path],
                               check=True, stdout=s.DEVNULL)
    except s.CalledProcessError as error:
        logger.critical('Could not apply traefik CRDs' +
                        error.stderr.decode('utf-8'))