diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..bec10c1 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +./.dapper +./.cache +./dist diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..a956791 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,179 @@ +--- +kind: pipeline +name: amd64 + +platform: + os: linux + arch: amd64 + +steps: +- name: build + image: rancher/dapper:v0.4.1 + commands: + - dapper ci + volumes: + - name: docker + path: /var/run/docker.sock + +- name: docker-publish + image: plugins/docker + settings: + dockerfile: package/Dockerfile + password: + from_secret: docker_password + repo: "rancher/shell" + tag: "${DRONE_TAG}-amd64" + username: + from_secret: docker_username + when: + instance: + - drone-publish.rancher.io + ref: + - refs/head/master + - refs/tags/* + event: + - tag + +volumes: +- name: docker + host: + path: /var/run/docker.sock + +--- +kind: pipeline +name: arm64 + +platform: + os: linux + arch: arm64 + +steps: +- name: build + image: rancher/dapper:v0.4.1 + commands: + - dapper ci + volumes: + - name: docker + path: /var/run/docker.sock + +- name: github_binary_release + image: plugins/github-release + settings: + api_key: + from_secret: github_token + prerelease: true + checksum: + - sha256 + checksum_file: CHECKSUMsum-arm64.txt + checksum_flatten: true + files: + - "dist/artifacts/*" + when: + instance: + - drone-publish.rancher.io + ref: + - refs/head/master + - refs/tags/* + event: + - tag + +- name: docker-publish + image: plugins/docker + settings: + dockerfile: package/Dockerfile + password: + from_secret: docker_password + repo: "rancher/shell" + tag: "${DRONE_TAG}-arm64" + username: + from_secret: docker_username + when: + instance: + - drone-publish.rancher.io + ref: + - refs/head/master + - refs/tags/* + event: + - tag + +volumes: +- name: docker + host: + path: /var/run/docker.sock + +--- +kind: pipeline +name: arm + +platform: + os: linux + arch: arm + +steps: +- name: build + image: rancher/dapper:v0.4.1 + commands: + - dapper ci + volumes: + - name: docker + path: /var/run/docker.sock + +- name: docker-publish + image: plugins/docker + settings: + dockerfile: package/Dockerfile + password: + from_secret: docker_password + repo: "rancher/shell" + tag: "${DRONE_TAG}-arm" + username: + from_secret: docker_username + when: + instance: + - drone-publish.rancher.io + ref: + - refs/head/master + - refs/tags/* + event: + - tag + +volumes: +- name: docker + host: + path: /var/run/docker.sock + +--- +kind: pipeline +name: manifest + +platform: + os: linux + arch: amd64 + +steps: +- name: manifest + image: plugins/manifest:1.0.2 + settings: + username: + from_secret: docker_username + password: + from_secret: docker_password + platforms: + - linux/amd64 + - linux/arm64 + - linux/arm + target: "rancher/shell:${DRONE_TAG}" + template: "rancher/shell:${DRONE_TAG}-ARCH" + when: + instance: + - drone-publish.rancher.io + ref: + - refs/head/master + - refs/tags/* + event: + - tag + +depends_on: +- amd64 +- arm64 +- arm diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4d32884 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +/.dapper +/.cache +/bin +/dist +*.swp +.idea diff --git a/Dockerfile.dapper b/Dockerfile.dapper new file mode 100644 index 0000000..88ddd07 --- /dev/null +++ b/Dockerfile.dapper @@ -0,0 +1,29 @@ +FROM golang:1.13.4-alpine3.10 + +ARG DAPPER_HOST_ARCH +ENV ARCH $DAPPER_HOST_ARCH + +RUN apk -U add bash git gcc musl-dev docker vim less file curl wget ca-certificates +RUN go get -d golang.org/x/lint/golint && \ + git -C /go/src/golang.org/x/lint/golint checkout -b current 06c8688daad7faa9da5a0c2f163a3d14aac986ca && \ + go install golang.org/x/lint/golint && \ + rm -rf /go/src /go/pkg +RUN mkdir -p /go/src/golang.org/x && \ + cd /go/src/golang.org/x && git clone https://github.com/golang/tools && \ + git -C /go/src/golang.org/x/tools checkout -b current aa82965741a9fecd12b026fbb3d3c6ed3231b8f8 && \ + go install golang.org/x/tools/cmd/goimports +RUN rm -rf /go/src /go/pkg +RUN if [ "${ARCH}" == "amd64" ]; then \ + curl -sL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s v1.15.0; \ + fi + +ENV GO111MODULE off +ENV DAPPER_ENV REPO TAG DRONE_TAG CROSS +ENV DAPPER_SOURCE /go/src/github.com/rancher/shell/ +ENV DAPPER_OUTPUT ./bin ./dist +ENV DAPPER_DOCKER_SOCKET true +ENV HOME ${DAPPER_SOURCE} +WORKDIR ${DAPPER_SOURCE} + +ENTRYPOINT ["./scripts/entry"] +CMD ["ci"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f433b1a --- /dev/null +++ b/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5d7b47e --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +TARGETS := $(shell ls scripts) + +.dapper: + @echo Downloading dapper + @curl -sL https://releases.rancher.com/dapper/latest/dapper-$$(uname -s)-$$(uname -m) > .dapper.tmp + @@chmod +x .dapper.tmp + @./.dapper.tmp -v + @mv .dapper.tmp .dapper + +$(TARGETS): .dapper + ./.dapper $@ + +.DEFAULT_GOAL := default + +.PHONY: $(TARGETS) diff --git a/package/Dockerfile b/package/Dockerfile new file mode 100644 index 0000000..14bc8a2 --- /dev/null +++ b/package/Dockerfile @@ -0,0 +1,31 @@ +FROM ubuntu:18.04 AS build +RUN apt update && \ + apt install -y curl xz-utils +RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.18.2/bin/linux/amd64/kubectl && \ + chmod +x kubectl +RUN curl -L https://github.com/scop/bash-completion/releases/download/2.10/bash-completion-2.10.tar.xz | tar xvJf - --strip-components=1 +RUN curl -L https://github.com/derailed/k9s/releases/download/v0.20.2/k9s_Linux_x86_64.tar.gz | tar xvzf - +RUN curl -L https://get.helm.sh/helm-v3.2.4-linux-amd64.tar.gz | tar xvzf - --strip-components=1 +RUN curl -L https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 > /jq && \ + chmod +x /jq + +FROM alpine:3.12 +RUN apk add -U --no-cache bash +RUN echo 'shell:x:1000:1000:shell,,,:/home/shell:/bin/bash' > /etc/passwd && \ + echo 'shell:x:1000:' > /etc/group && \ + mkdir /home/shell && \ + echo '. /etc/bash_completion' >> /home/shell/.bashrc && \ + echo 'alias k="kubectl"' >> /home/shell/.bashrc && \ + echo 'alias ks="kubectl -n kube-system"' >> /home/shell/.bashrc && \ + echo 'source <(kubectl completion bash)' >> /home/shell/.bashrc && \ + echo 'PS1="> "' >> /home/shell/.bashrc && \ + mkdir /home/shell/.kube && \ + chown -R shell /home/shell && \ + chmod 700 /run +COPY --from=build /bash_completion /etc/ +COPY --from=build /kubectl /k9s /jq /helm /usr/local/bin/ +COPY helm-cmd /usr/local/bin +COPY welcome /usr/local/bin +USER 1000 +WORKDIR /home/shell +CMD ["welcome"] diff --git a/package/helm-cmd b/package/helm-cmd new file mode 100755 index 0000000..858c856 --- /dev/null +++ b/package/helm-cmd @@ -0,0 +1,16 @@ +#!/bin/sh +set -e + +sleep 1 +while true; do + if kubectl version >/dev/null 2>&1; then + break + fi + echo Waiting for Kubernetes API to be available + sleep 1 +done + +for i in operation*; do + cat $i | xargs -0 -- echo helm + cat $i | xargs -0 -- helm +done diff --git a/package/welcome b/package/welcome new file mode 100755 index 0000000..154179f --- /dev/null +++ b/package/welcome @@ -0,0 +1,7 @@ +#!/bin/bash + +echo +echo "# Run kubectl commands inside here" +echo "# e.g. kubectl get all" +#export TERM=screen-256color +exec bash diff --git a/scripts/ci b/scripts/ci new file mode 100755 index 0000000..b0c677b --- /dev/null +++ b/scripts/ci @@ -0,0 +1,7 @@ +#!/bin/bash +set -e + +cd $(dirname $0) + +./validate-ci +./package diff --git a/scripts/default b/scripts/default new file mode 100755 index 0000000..84912d4 --- /dev/null +++ b/scripts/default @@ -0,0 +1,6 @@ +#!/bin/bash +set -e + +cd $(dirname $0) + +./package diff --git a/scripts/entry b/scripts/entry new file mode 100755 index 0000000..78fb567 --- /dev/null +++ b/scripts/entry @@ -0,0 +1,11 @@ +#!/bin/bash +set -e + +mkdir -p bin dist +if [ -e ./scripts/$1 ]; then + ./scripts/"$@" +else + exec "$@" +fi + +chown -R $DAPPER_UID:$DAPPER_GID . diff --git a/scripts/package b/scripts/package new file mode 100755 index 0000000..810f6b7 --- /dev/null +++ b/scripts/package @@ -0,0 +1,18 @@ +#!/bin/bash +set -e + +source $(dirname $0)/version + +cd $(dirname $0)/.. + +mkdir -p dist/artifacts +cp bin/shell dist/artifacts/shell${SUFFIX} + +IMAGE=${REPO}/shell:${TAG} +DOCKERFILE=package/Dockerfile +if [ -e ${DOCKERFILE}.${ARCH} ]; then + DOCKERFILE=${DOCKERFILE}.${ARCH} +fi + +docker build -f ${DOCKERFILE} -t ${IMAGE} . +echo Built ${IMAGE} diff --git a/scripts/release b/scripts/release new file mode 100755 index 0000000..7af0df3 --- /dev/null +++ b/scripts/release @@ -0,0 +1,3 @@ +#!/bin/bash + +exec $(dirname $0)/ci diff --git a/scripts/validate-ci b/scripts/validate-ci new file mode 100755 index 0000000..5a6c52a --- /dev/null +++ b/scripts/validate-ci @@ -0,0 +1,13 @@ +#!/bin/bash +set -e + +cd $(dirname $0)/.. + +source ./scripts/version + +if [ -n "$DIRTY" ]; then + echo Git is dirty + git status + git diff + exit 1 +fi diff --git a/scripts/version b/scripts/version new file mode 100755 index 0000000..1646092 --- /dev/null +++ b/scripts/version @@ -0,0 +1,27 @@ +#!/bin/bash + +if [ -n "$(git status --porcelain --untracked-files=no)" ]; then + DIRTY="-dirty" +fi + +COMMIT=$(git rev-parse --short HEAD) +GIT_TAG=${DRONE_TAG:-$(git tag -l --contains HEAD | head -n 1)} + +if [[ -z "$DIRTY" && -n "$GIT_TAG" ]]; then + VERSION=$GIT_TAG +else + VERSION="${COMMIT}${DIRTY}" +fi + +if [ -z "$ARCH" ]; then + ARCH=$(go env GOHOSTARCH) +fi + +SUFFIX="-${ARCH}" + +TAG=${TAG:-${VERSION}${SUFFIX}} +REPO=${REPO:-rancher} + +if echo $TAG | grep -q dirty; then + TAG=dev +fi