Skip to content

Commit

Permalink
Start in host CWD, autoconfigure ATMOS_BASE_PATH (cloudposse#756)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nuru authored Jan 23, 2022
1 parent 4e7a597 commit ac1d453
Show file tree
Hide file tree
Showing 9 changed files with 167 additions and 49 deletions.
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

<!-- markdownlint-disable -->
# Geodesic [![Build Status](https://github.com/cloudposse/geodesic/workflows/docker/badge.svg)](https://github.com/cloudposse/geodesic/actions?query=workflow%3Adocker) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcloudposse%2Fgeodesic.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcloudposse%2Fgeodesic?ref=badge_shield) [![Latest Release](https://img.shields.io/github/release/cloudposse/geodesic.svg)](https://github.com/cloudposse/geodesic/releases/latest) [![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com) [![Slack Archive](https://img.shields.io/badge/slack-archive-blue.svg)](https://archive.sweetops.com/geodesic)
<!-- markdownlint-restore -->
Expand Down Expand Up @@ -41,7 +42,6 @@ It provides a fully customizable framework for defining and building cloud infra

It's works natively with Mac OSX, Linux, and [Windows 10 (WSL)](https://docs.microsoft.com/en-us/windows/wsl/install-win10).


---

This project is part of our comprehensive ["SweetOps"](https://cpco.io/sweetops) approach towards DevOps.
Expand All @@ -66,7 +66,6 @@ It's 100% Open Source and licensed under the [APACHE2](LICENSE).




## Screenshots


Expand Down Expand Up @@ -108,6 +107,10 @@ chip takes several years to establish; we hope we will not have to wait that lon

Want to learn more? [Check out our getting started with Geodesic guide!](https://docs.cloudposse.com/tutorials/geodesic-getting-started/)





## Usage


Expand Down Expand Up @@ -195,6 +198,7 @@ Like this project? Please give it a ★ on [our GitHub](https://github.com/cloud
Are you using this project or any of our other projects? Consider [leaving a testimonial][testimonial]. =)



## Related Projects

Check out these related projects.
Expand All @@ -203,8 +207,6 @@ Check out these related projects.
- [Build Harness](https://github.com/cloudposse/dev) - Collection of Makefiles to facilitate building Golang projects, Dockerfiles, Helm charts, and more
- [terraform-aws-components](https://github.com/cloudposse/terraform-aws-components) - Catalog of reusable Terraform components and blueprints for provisioning reference architectures



## Help

**Got a question?** We got answers.
Expand Down Expand Up @@ -276,7 +278,7 @@ In general, PRs are welcome. We follow the typical "fork-and-pull" Git workflow.

## Copyright

Copyright © 2017-2021 [Cloud Posse, LLC](https://cpco.io/copyright)
Copyright © 2017-2022 [Cloud Posse, LLC](https://cpco.io/copyright)



Expand Down
8 changes: 5 additions & 3 deletions os/alpine/Dockerfile.alpine
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
ARG ALPINE_VERSION=3.13.5
ARG ALPINE_VERSION=3.13.7
# https://cloud.google.com/sdk/docs/release-notes
ARG GOOGLE_CLOUD_SDK_VERSION=352.0.0
ARG GOOGLE_CLOUD_SDK_VERSION=369.0.0
# https://github.com/ahmetb/kubectx/releases
ARG KUBECTX_COMPLETION_VERSION=0.9.4
# https://github.com/jonmosco/kube-ps1/releases
ARG KUBE_PS1_VERSION=0.7.0

#
# Python Dependencies
Expand Down Expand Up @@ -146,7 +148,7 @@ ADD https://raw.githubusercontent.com/ahmetb/kubectx/v${KUBECTX_COMPLETION_VERSI
#
# Install fancy Kube PS1 Prompt
#
ENV KUBE_PS1_VERSION 0.7.0
ARG KUBE_PS1_VERSION
ADD https://raw.githubusercontent.com/jonmosco/kube-ps1/v${KUBE_PS1_VERSION}/kube-ps1.sh /etc/profile.d/prompt:kube-ps1.sh


Expand Down
10 changes: 6 additions & 4 deletions os/debian/Dockerfile.debian
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
ARG DEBIAN_VERSION=10.10-slim
ARG DEBIAN_VERSION=10.11-slim
# https://cloud.google.com/sdk/docs/release-notes
ARG GOOGLE_CLOUD_SDK_VERSION=352.0.0-0
ARG GOOGLE_CLOUD_SDK_VERSION=369.0.0-0
# https://github.com/ahmetb/kubectx/releases
ARG KUBECTX_COMPLETION_VERSION=0.9.4
# https://github.com/jonmosco/kube-ps1/releases
ARG KUBE_PS1_VERSION=0.7.0

FROM debian:$DEBIAN_VERSION as python
# Find the current version of Python at https://www.python.org/downloads/source/
ARG PYTHON_VERSION=3.8.11
ARG PYTHON_VERSION=3.8.12

# Debian comes with minimal Locale support. See https://github.com/docker-library/docs/pull/703/files
# Recommended: LC_ALL=C.UTF-8
Expand Down Expand Up @@ -173,7 +175,7 @@ ADD https://raw.githubusercontent.com/ahmetb/kubectx/v${KUBECTX_COMPLETION_VERSI
#
# Install fancy Kube PS1 Prompt
# https://github.com/jonmosco/kube-ps1/releases
ENV KUBE_PS1_VERSION 0.7.0
ARG KUBE_PS1_VERSION
ADD https://raw.githubusercontent.com/jonmosco/kube-ps1/v${KUBE_PS1_VERSION}/kube-ps1.sh /etc/profile.d/prompt:kube-ps1.sh


Expand Down
8 changes: 5 additions & 3 deletions packages.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ helm3@cloudposse
helmfile@cloudposse
jq
kops@cloudposse
# The latest version of kubectl is wrong for all of our customers, so do not install it.
# Instead, install a compatible version. For now, track the latest AWS EKS version.
kubectl-1.16@cloudposse
# The latest version of kubectl is wrong for most of our customers, so do not install it.
# Instead, install a compatible version. For now, track the latest AWS EKS version,
# which will support the previous and current EKS versions, and support the newly
# released next version until we later update this to follow.
kubectl-1.21@cloudposse
kubectx@cloudposse
kubens@cloudposse
less
Expand Down
7 changes: 0 additions & 7 deletions rootfs/etc/init.d/atmos.sh

This file was deleted.

60 changes: 60 additions & 0 deletions rootfs/etc/profile.d/_workdir.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Files in the profile.d directory are executed by the lexicographical order of their file names.
# This file sets the working directory inside Geodesic to match the host directory Geodesic
# was launched from, if possible. If the host directory is not accessible, it sets the working directory to `/`.
#
# This file is named _workdir.sh. The leading underscore is needed to ensure this file executes before
# other files that may depend on it. The "w" is needed to ensure it is loaded *after* _preferences.sh
#

function _file_device() {
df --output=source "$1" | tail -1
}

# file_on_host is true when the argument is a file or directory that appears to be on the Host file system.
# Intended to support files on user-defined bind mounts in addition to `/localhost`.
# This function is run by the command line prompt setup, so it should be very fast.
# Therefore we cache some info in the environment.
if df -a | grep -q /localhost; then
export GEODESIC_LOCALHOST_DEVICE=$(_file_device /localhost)
else
export GEODESIC_LOCALHOST_MISSING=true
fi

function file_on_host() {
[[ $GEODESIC_LOCALHOST_MISSING != "true" ]] && [[ $(_file_device "$1") == ${GEODESIC_LOCALHOST_DEVICE} ]]
}

function _default_initial_wd() {
if [[ -d /stacks ]]; then
# Newer default using `atmos` and stacks
export GEODESIC_WORKDIR="/"
else
# Older default working directory
export GEODESIC_WORKDIR="/conf"
fi
red "# Defaulting initial working directory to \"${GEODESIC_WORKDIR}\""
}

# You can set GEODESIC_WORKDIR in your Geodesic preferences to have full control of your starting working directory
if [[ -d $GEODESIC_WORKDIR ]]; then
[[ $SHLVL == 1 ]] && green "# Initial working directory configured as ${GEODESIC_WORKDIR}"
else
if [[ -d $GEODESIC_HOST_CWD ]]; then
if [[ -n $LOCAL_HOME ]] && $(file_on_host "$GEODESIC_HOST_CWD"); then
export GEODESIC_WORKDIR=$(readlink -e "${GEODESIC_HOST_CWD}")
green "# Initial working directory set from host CWD to ${GEODESIC_WORKDIR}"
else
red "# Host CWD \"${GEODESIC_HOST_CWD}\" does not appear to be accessible from this container"
_default_initial_wd
fi
else
red "# No configured working directory is accessible:"
red "# GEODESIC_WORKDIR is \"$GEODESIC_WORKDIR\""
red "# GEODESIC_HOST_CWD is \"$GEODESIC_HOST_CWD\""
_default_initial_wd
fi
fi

[[ $SHLVL == 1 ]] && cd "${GEODESIC_WORKDIR}"

unset -f _default_initial_wd
38 changes: 38 additions & 0 deletions rootfs/etc/profile.d/atmos.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/bin/bash

function _configure_atmos_base_path() {
# Leave $ATMOS_BASE_PATH alone if it is already set
if [[ -n $ATMOS_BASE_PATH ]]; then
if [[ $SHLVL == 1 ]]; then
green "# Using configured $ATMOS_BASE_PATH of \"$ATMOS_BASE_PATH\""
fi
return
fi

# If $GEODESIC_WORKDIR contains both a "stacks" and "components" directory,
# use it as the $ATMOS_BASE_PATH
if [[ -d "${GEODESIC_WORKDIR}/stacks" ]] && [[ -d "${GEODESIC_WORKDIR}/components" ]]; then
export ATMOS_BASE_PATH="${GEODESIC_WORKDIR}"
green "# Setting ATMOS_BASE_PATH to \"$ATMOS_BASE_PATH\" based on children of workdir"
return
fi

# If $GEODESIC_WORKDIR is a descendent of either a "stacks" or "components" directory,
# use the parent of that directory as ATMOS_BASE_PATH
if [[ "${GEODESIC_WORKDIR}" =~ /(stacks|components)/ ]]; then
if [[ "${GEODESIC_WORKDIR}" =~ /stacks/ ]]; then
export ATMOS_BASE_PATH="${GEODESIC_WORKDIR%/stacks/*}"
else
export ATMOS_BASE_PATH="${GEODESIC_WORKDIR%/components/*}"
fi
green "# Setting ATMOS_BASE_PATH to \"$ATMOS_BASE_PATH\" based on parent of workdir"
return
fi
yellow "# No candidate for ATMOS_BASE_PATH found, leaving it unset"
}

# Only configure ATMOS_BASE_PATH if we find an `atmos` executable,
# but otherwise leave the function available for the user to call explicitly.
# NOTE: If we start shipping `atmos` with Geodesic by default, change this to
# [[ -f /usr/local/etc/atmos/atmos.yaml ]] && _configure_atmos_base_path
command -v atmos >/dev/null && _configure_atmos_base_path && unset -f _configure_atmos_base_path
54 changes: 35 additions & 19 deletions rootfs/etc/profile.d/prompt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,37 +61,52 @@ function geodesic_prompt() {
plain)
# 8859-1 codepoints:
# '\[' and '\]' are bash prompt delimiters around non-printing characters
ASSUME_ROLE_ACTIVE_MARK="\["$(tput bold)$(tput setab 2)"\]»\["$(tput sgr0)"\] " # green
ASSUME_ROLE_INACTIVE_MARK=$'· '
BLACK_RIGHTWARDS_ARROWHEAD=$'=> '
BANNER_MARK=$'§ '
[[ -z $ASSUME_ROLE_ACTIVE_MARK ]] && ASSUME_ROLE_ACTIVE_MARK="\["$(tput bold)$(tput setab 2)"\]»\["$(tput sgr0)"\]" # green
[[ -z $ASSUME_ROLE_INACTIVE_MARK ]] && ASSUME_ROLE_INACTIVE_MARK=$'·'
[[ -z $BLACK_RIGHTWARDS_ARROWHEAD ]] && BLACK_RIGHTWARDS_ARROWHEAD=$'=>'
[[ -z $BANNER_MARK ]] && BANNER_MARK=$'§'
;;

unicode)
# unicode
ASSUME_ROLE_ACTIVE_MARK=$'\u2705 ' # '✅'
ASSUME_ROLE_INACTIVE_MARK=$'\u274C ' # '❌'
BLACK_RIGHTWARDS_ARROWHEAD=$'\u27A4 ' # '➤', suggest '▶' may be present in more fonts
BANNER_MARK=$'\u29C9 ' # '⧉'
[[ -z $ASSUME_ROLE_ACTIVE_MARK ]] && ASSUME_ROLE_ACTIVE_MARK=$'\u2705' # '✅'
[[ -z $ASSUME_ROLE_INACTIVE_MARK ]] && ASSUME_ROLE_INACTIVE_MARK=$'\u274C' # '❌'
[[ -z $BLACK_RIGHTWARDS_ARROWHEAD ]] && BLACK_RIGHTWARDS_ARROWHEAD=$'\u27A4' # '➤', suggest '▶' may be present in more fonts
[[ -z $BANNER_MARK ]] && BANNER_MARK=$'\u29C9' # '⧉'
;;

fancy)
# Same as default, except for BLACK_RIGHTWARDS_ARROWHEAD, because the character used in the
# default set, Z NOTATION SCHEMA PIPING, is from the "Supplemental Mathematical Operators" Unicode block
# which is not included by default in the Ubuntu terminal font.
# See https://github.com/cloudposse/geodesic/issues/417
[[ -z $ASSUME_ROLE_ACTIVE_MARK ]] && ASSUME_ROLE_ACTIVE_MARK=$'\x01'$(tput bold)$(tput setaf 2)$'\x02\u221a\x01'$(tput sgr0)$'\x02' # green bold '√'
[[ -z $ASSUME_ROLE_INACTIVE_MARK ]] && ASSUME_ROLE_INACTIVE_MARK=$'\x01'$(tput bold)$(tput setaf 1)$'\x02\u2717\x01'$(tput sgr0)$'\x02' # red bold '✗'
[[ -z $BLACK_RIGHTWARDS_ARROWHEAD ]] && BLACK_RIGHTWARDS_ARROWHEAD=$'\u27A4' # '➤'
[[ -z $BANNER_MARK ]] && BANNER_MARK='' # \u29c9 TWO JOINED SQUARES
;;

*)
# default
# ASSUME_ROLE_ACTIVE_MARK=$' \x01'$(tput bold)$(tput setaf 2)$'\x02\u2713 \x01'$(tput sgr0)$'\x02' # green bold '✓'
ASSUME_ROLE_ACTIVE_MARK=$' \x01'$(tput bold)$(tput setaf 2)$'\x02\u221a \x01'$(tput sgr0)$'\x02' # green bold '√'
ASSUME_ROLE_INACTIVE_MARK=$' \x01'$(tput bold)$(tput setaf 1)$'\x02\u2717 \x01'$(tput sgr0)$'\x02' # red bold '✗'
# ASSUME_ROLE_ACTIVE_MARK=$'\x01'$(tput bold)$(tput setaf 2)$'\x02\u2713\x01'$(tput sgr0)$'\x02' # green bold '✓'
[[ -z $ASSUME_ROLE_ACTIVE_MARK ]] && ASSUME_ROLE_ACTIVE_MARK=$'\x01'$(tput bold)$(tput setaf 2)$'\x02\u221a\x01'$(tput sgr0)$'\x02' # green bold '√'
[[ -z $ASSUME_ROLE_INACTIVE_MARK ]] && ASSUME_ROLE_INACTIVE_MARK=$'\x01'$(tput bold)$(tput setaf 1)$'\x02\u2717\x01'$(tput sgr0)$'\x02' # red bold '✗'
# Options for arrow per https://github.com/cloudposse/geodesic/issues/417#issuecomment-477836676
# '»' ($'\u00bb') RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK from the Latin-1 supplement Unicode block
# '≫' ($'\u226b') MUCH GREATER-THAN and
# '⋙' ($'\u22d9') VERY MUCH GREATER-THAN which are from the Mathematical Operators Unicode block
# '➤' ($'\u27a4') BLACK RIGHTWARDS ARROWHEAD from the Dingbats Unicode block
# '▶︎' ($'\u25b6\ufe0e') BLACK RIGHT-POINTING TRIANGLE which is sometimes presented as an emoji (as GitHub likes to) '▶️'
# '⏩︎' ($'\u23e9\ufe0e') BLACK RIGHT-POINTING DOUBLE TRIANGLE
BLACK_RIGHTWARDS_ARROWHEAD=$'\u2a20 ' # '⨠' Z NOTATION SCHEMA PIPING
BANNER_MARK=' '
[[ -z $BLACK_RIGHTWARDS_ARROWHEAD ]] && BLACK_RIGHTWARDS_ARROWHEAD=$'\u2a20' # '⨠' Z NOTATION SCHEMA PIPING
[[ -z $BANNER_MARK ]] && BANNER_MARK='' # \u29c9 TWO JOINED SQUARES
;;
esac

# "(HOST)" with "HOST" in bold red. Only test for unset ("-") instead of unset or null (":-") so that
# the feature can be suppressed by setting PROMPT_HOST_MARK to null.
[[ -z $PROMPT_HOST_MARK ]] && PROMPT_HOST_MARK="${PROMPT_HOST_MARK-$'(\x01'$(tput bold)$(tput setaf 1)$'\x02HOST\x01'$(tput sgr0)$'\x02)'}"

local level_prompt
case $SHLVL in
1) level_prompt='.' ;;
Expand Down Expand Up @@ -123,13 +138,13 @@ function geodesic_prompt() {
done

local dir_prompt
dir_prompt="${STATUS}${level_prompt} "
if [[ $(pwd -P) =~ ^/localhost/ ]]; then
dir_prompt+="${ROLE_PROMPT} ("$'\x01'$(tput bold)$(tput setaf 1)$'\x02HOST\x01'$(tput sgr0)$'\x02'") \W "
dir_prompt=" ${STATUS} ${level_prompt} "
if [[ -n $PROMPT_HOST_MARK ]] && file_on_host "$(pwd -P)"; then
dir_prompt+="${ROLE_PROMPT} ${PROMPT_HOST_MARK} \W "
else
dir_prompt+="${ROLE_PROMPT} \W "
fi
dir_prompt+=$'${GEODISIC_PROMPT_GLYPHS-$BLACK_RIGHTWARDS_ARROWHEAD}'
dir_prompt+=$'${GEODESIC_PROMPT_GLYPHS-${BLACK_RIGHTWARDS_ARROWHEAD} }'

update_terraform_prompt
local old_kube_ps1_prefix="$KUBE_PS1_PREFIX"
Expand All @@ -143,7 +158,7 @@ function geodesic_prompt() {
tf_mark="${ASSUME_ROLE_ACTIVE_MARK}"
fi
if [[ -n ${GEODESIC_TF_PROMPT_LINE} ]]; then
tf_prompt="${tf_mark}${GEODESIC_TF_PROMPT_LINE}\n"
tf_prompt=" ${tf_mark} ${GEODESIC_TF_PROMPT_LINE}\n"
fi
if [[ $GEODESIC_TERRAFORM_WORKSPACE_PROMPT_ENABLED == "true" ]]; then
KUBE_PS1_PREFIX="$(yellow "cluster:")("
Expand All @@ -154,7 +169,8 @@ function geodesic_prompt() {
fi

if [ -n "${BANNER}" ]; then
PS1=$' ${BANNER_MARK}'" ${BANNER} $(kube_ps1)${secrets_active}\n${tf_prompt}${dir_prompt}"
# Intentional 2 spaces between banner mark and banner in order to offset it from level prompt
PS1=$' ${BANNER_MARK}'" ${BANNER} $(kube_ps1)${secrets_active}\n${tf_prompt}${dir_prompt}"
else
PS1="${tf_prompt}${dir_prompt}"
fi
Expand Down
19 changes: 11 additions & 8 deletions rootfs/templates/wrapper
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ set -o pipefail
# Geodesic Settings
export GEODESIC_PORT=${GEODESIC_PORT:-$((30000 + $$ % 30000))}

# If this env var is unset, set it to the current directory without the home dir
export GEODESIC_WORKDIR=${GEODESIC_WORKDIR:-/localhost/${PWD#$HOME/}}
export GEODESIC_HOST_CWD=$(pwd -P 2>/dev/null || pwd)

readonly OS=$(uname -s)

Expand Down Expand Up @@ -156,20 +155,24 @@ function use() {
if [ "${local_home}" == "/localhost" ]; then
echo "WARNING: not mounting ${local_home} because it conflicts with geodesic"
else
echo "# Mounting ${local_home} into container"
DOCKER_ARGS+=(--volume=${local_home}:/localhost)
DOCKER_ARGS+=(--env LOCAL_HOME=${local_home})
echo "# Mounting ${local_home} into container with workdir ${GEODESIC_HOST_CWD}"
DOCKER_ARGS+=(
--volume="${local_home}:/localhost"
--env LOCAL_HOME="${local_home}"
)
fi

DOCKER_ARGS+=(--privileged
DOCKER_ARGS+=(
--privileged
--publish ${GEODESIC_PORT}:${GEODESIC_PORT}
--name "${DOCKER_NAME}"
--rm
--env GEODESIC_PORT=${GEODESIC_PORT}
--env DOCKER_IMAGE="${DOCKER_IMAGE%:*}"
--env DOCKER_NAME="${DOCKER_NAME}"
--env DOCKER_TAG="${DOCKER_TAG}"
--workdir "${GEODESIC_WORKDIR}")
--env GEODESIC_HOST_CWD="${GEODESIC_HOST_CWD}"
)

trap run_exit_hooks EXIT
# the extra curly braces around .ID are because this file goes through go template substitution local before being installed as a shell script
Expand All @@ -179,7 +182,7 @@ function use() {
if [ $# -eq 0 ]; then
set -- "/bin/bash" "-l" "$@"
fi
docker exec -it "${DOCKER_NAME}" $*
docker exec -it --env GEODESIC_HOST_CWD="${GEODESIC_HOST_CWD}" "${DOCKER_NAME}" $*
else
echo "# Starting new ${DOCKER_NAME} session from ${DOCKER_IMAGE}"
echo "# Exposing port ${GEODESIC_PORT}"
Expand Down

0 comments on commit ac1d453

Please sign in to comment.