diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..0daf12d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,8 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..eec5b84 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,5 @@ +# These owners will be the default owners for everything in +# the repo, unless a later match takes precedence: +# +# @bdsoha will be requested for review when someone opens a pull request. +* @bdsoha diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml new file mode 100644 index 0000000..1366a06 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -0,0 +1,55 @@ +--- +name: ๐Ÿ› Bug Report +description: Report an issue to help the project improve. +title: ๐Ÿ› +labels: + - "type: bug ๐Ÿ›" +body: + - type: checkboxes + attributes: + label: Is there an existing issue for this? + description: Please search to see if an issue already exists for the bug you encountered. + options: + - label: I have searched the existing issues + required: true + + - type: input + attributes: + label: Version + description: Docker image digest + placeholder: sha256:58025ebfabf03b54899829b7d20b1c9c3de3558f452edd033802e809a8c194b0 + validations: + required: true + + - type: textarea + attributes: + label: Current Behavior + description: A concise description of what you're experiencing. + validations: + required: true + + - type: textarea + attributes: + label: Expected Behavior + description: A concise description of what you expected to happen. + validations: + required: true + + - type: textarea + attributes: + label: Steps To Reproduce & Additional information + description: | + Steps to reproduce the behavior: + + - Links + - References + - More context about the issue you are encountering! + + Tip: You can attach images by dragging files into this area. + placeholder: | + 1. In this environment... + 1. With this config... + 1. Run '...' + 1. See error... + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/docs_request.yaml b/.github/ISSUE_TEMPLATE/docs_request.yaml new file mode 100644 index 0000000..cbf8f34 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/docs_request.yaml @@ -0,0 +1,26 @@ +--- +name: ๐Ÿ“š Documentation Change +description: Improvements or additions to documentation. +title: ๐Ÿ“š <title> +labels: + - "type: documentation ๐Ÿ“š" +body: + - type: checkboxes + attributes: + label: Is there an existing request for this change? + description: | + Please make sure a request does not already exists for the + documentation changes you're looking to implement. + options: + - label: I have searched the existing issues + required: true + - type: textarea + attributes: + label: Context for documentation change + description: Explain what led you to draft this issue. + placeholder: | + I noticed unclear explanation of build and install and encountered + a few issues while attempting it myself. + This could confuse other contributors. + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml new file mode 100644 index 0000000..8666182 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -0,0 +1,32 @@ +--- +name: ๐Ÿš€ Feature Request +description: Request a new feature. +title: ๐Ÿš€ <title> +labels: + - "type: feature request ๐Ÿš€" +body: + - type: textarea + id: summary + attributes: + label: Summary + description: A clear and concise description of the feature you're interested in. + placeholder: Describe in a few lines your feature request. + validations: + required: true + + - type: textarea + attributes: + label: Suggested Solution + description: | + Describe the solution you'd like. + A clear and concise description of what you want to happen. + validations: + required: true + + - type: textarea + attributes: + label: Additional Context + description: | + Add any other context about the problem here. + validations: + required: false diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..49ca16e --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,73 @@ +--- +name: ๐Ÿ‘ทโ€โ™‚๏ธ Build + +on: + push: + branches: + - main + + tags: + - v* + +jobs: + lint: + name: ๐Ÿงน Lint + runs-on: ubuntu-latest + if: github.actor != 'renovate[bot]' && github.actor != 'renovate[bot]' + steps: + - name: ๐Ÿ“ Checkout repository + uses: actions/checkout@v4 + + - name: ๐Ÿงน Lint + uses: pre-commit/action@v3.0.1 + + build: + name: ๐Ÿณ Docker Build + runs-on: ubuntu-latest + needs: + - lint + + permissions: + contents: read + packages: write + + steps: + - name: ๐Ÿ“ Checkout repository + uses: actions/checkout@v4 + + - uses: docker/setup-qemu-action@v3 + - uses: docker/setup-buildx-action@v3 + + - name: ๐Ÿ”‘ Login to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: ๐Ÿ“ƒ Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }} + flavor: | + latest=false + tags: | + type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} + type=ref,event=pr,prefix=pr- + type=semver,pattern=v{{version}} + type=semver,pattern=v{{major}}.{{minor}} + + - name: ๐Ÿณ Docker Build & Push + uses: docker/build-push-action@v6 + id: docker_build + env: + DOCKER_BUILD_NO_SUMMARY: true + with: + cache-from: type=gha + cache-to: type=gha,mode=max + context: . + labels: ${{ steps.meta.outputs.labels }} + push: true + provenance: false + tags: ${{ steps.meta.outputs.tags }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..8753d72 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,30 @@ +--- +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: check-added-large-files + args: + - --maxkb=300 + - id: check-json + - id: check-toml + - id: check-yaml + - id: end-of-file-fixer + - id: mixed-line-ending + - id: trailing-whitespace + + - repo: https://github.com/adrienverge/yamllint + rev: v1.35.1 + hooks: + - id: yamllint + args: + - --config-file + - src/home/.config/yamllint/config + + - repo: https://github.com/igorshubovych/markdownlint-cli + rev: v0.39.0 + hooks: + - id: markdownlint + args: + - --config + - src/home/.config/markdownlint/config diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c5548b0 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,93 @@ +ARG tag=12 + +################################## Temp Layer ################################## + +FROM debian:${tag} AS temp + +RUN mkdir -p /etc/apt/keyrings + +### Install helper requirements +RUN apt-get update \ + && apt-get satisfy -y --no-install-recommends \ + "ca-certificates (>=20230311)" \ + "curl (>=7.88)" \ + "gnupg (>=2.2)" \ + "unzip (>=6.0)" \ + && rm -rf /var/lib/apt/lists/* + +### Add non-standard repository keys +RUN --mount=src=src,dst=/build \ + /build/add-gpg-keyrings.sh /build/extra.gpg.txt \ + && chmod a+r /etc/apt/keyrings/*.gpg + +################################## Base Layer ################################## + +FROM debian:${tag} AS base +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +ENV LANG=en_US.UTF-8 + +COPY src/rootfs / +COPY --from=temp /etc/apt/keyrings /etc/apt/keyrings + +### Add application user +RUN adduser \ + --disabled-password \ + --gecos '' \ + --uid 1000 \ + kloud + +### Install packages +RUN --mount=src=src,dst=/build \ + apt-get update \ + && apt-get satisfy -y --no-install-recommends \ + "ca-certificates (>=20230311)" \ + && apt-get update \ + && apt-get satisfy -y --no-install-recommends $(cat /build/packages.apt) \ + && rm -rf \ + /var/lib/apt/lists/* \ + /usr/lib/python3.11/EXTERNALLY-MANAGED \ + && locale-gen \ + && ln -fs "$(which python3)" /usr/bin/python + +############################### Dependency Layer ############################### + +FROM temp AS deps +WORKDIR /usr/local/bin +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +ARG TARGETARCH + +# renovate: source=github-releases dep=google/go-containerregistry +ARG crane_version=0.20.0 + +RUN case ${TARGETARCH} in "arm64") amr64 ;; "amd64") file=x86_64 ;; esac \ + && curl -fsSL "https://github.com/google/go-containerregistry/releases/download/v${crane_version}/go-containerregistry_Linux_${file}.tar.gz" \ + | tar -xzf - \ + && curl -fsSL https://mirror.openshift.com/pub/openshift-v4/x86_64/clients/ocp/4.9.9/openshift-client-linux.tar.gz \ + | tar -xzf - -C /tmp \ + && cp /tmp/oc . + +RUN chown -R root:root /usr/local/bin \ + && chmod -R 755 /usr/local/bin + +############################### Application layer ############################## + +FROM base +USER kloud +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +WORKDIR /workspace + +ENV USER=kloud +ENV PATH=${PATH}:/home/kloud/.local/bin + +### Install user packages & extensions +RUN --mount=src=src,dst=/build \ + helm plugin install https://github.com/databus23/helm-diff \ + && pip install --no-cache-dir -r /build/requirements.txt \ + && pip cache purge \ + && ansible-galaxy install -r /build/requirements.yaml \ + && rm -rf \ + /home/kloud/.ansible/galaxy_cache \ + /home/kloud/.cache/helm + +ENTRYPOINT ["ansible-playbook"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7d1cfb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 KloudKIT + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..b4186aa --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +# Ansible Controller + +> ๐ŸŽฎ Ansible controller: your configurations can stay home + +[![License](https://img.shields.io/badge/License-MIT-blue?style=flat-square&link=https://github.com/kloudkit/ansible-controller?tab=MIT-1-ov-file#MIT-1-ov-file)](https://github.com/kloudkit/ansible-controller?tab=MIT-1-ov-file#MIT-1-ov-file) + +## Documentation + +TBD + +## License + +This project is licensed under the +[**MIT License**](https://github.com/kloudkit/ansible-controller?tab=MIT-1-ov-file#MIT-1-ov-file) diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..a7f8e49 --- /dev/null +++ b/renovate.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended", + ":disableRateLimiting" + ], + "assignees": [ "bdsoha" ], + "labels": [ "type: dependency ๐Ÿ”ผ" ], + "schedule": [ "every weekend" ], + "dependencyDashboard": true, + "dependencyDashboardTitle": "๐Ÿค– Renovate Dashboard", + "commitMessageAction": "๐Ÿ”ผ Bump", + "regexManagers": [ + { + "fileMatch": [ "^Dockerfile$" ], + "matchStrings": [ + "# renovate: source=(?<datasource>.*?) dep=(?<depName>.*?)( versioning=(?<versioning>.*?))?\\nARG.*=(?<currentValue>.*)\\n" + ], + "versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}semver{{/if}}" + } + ] +} diff --git a/src/add-gpg-keyrings.sh b/src/add-gpg-keyrings.sh new file mode 100755 index 0000000..54a7b77 --- /dev/null +++ b/src/add-gpg-keyrings.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +while IFS= read -r line; do + read -r name url <<< "${line}" + + curl -fsSL "https://${url}" \ + | gpg --dearmor -o "/etc/apt/keyrings/${name}.gpg" +done < "${1}" diff --git a/src/extra.gpg.txt b/src/extra.gpg.txt new file mode 100644 index 0000000..8473977 --- /dev/null +++ b/src/extra.gpg.txt @@ -0,0 +1,2 @@ +helm baltocdn.com/helm/signing.asc +kubernetes pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key diff --git a/src/packages.apt b/src/packages.apt new file mode 100644 index 0000000..84a60bd --- /dev/null +++ b/src/packages.apt @@ -0,0 +1,14 @@ +curl +dnsutils +git +helm +iputils-ping +jq +kubectl +locales +netcat-traditional +openssh-client +python3 +python3-apt +python3-pip +sshpass diff --git a/src/requirements.txt b/src/requirements.txt new file mode 100644 index 0000000..85e46f7 --- /dev/null +++ b/src/requirements.txt @@ -0,0 +1,6 @@ +ansible-core==2.17.1 +docker==7.1.0 +kubernetes==30.1.0 +netaddr==1.3.0 +passlib==1.7.4 +yq==3.4.3 diff --git a/src/requirements.yaml b/src/requirements.yaml new file mode 100644 index 0000000..61d7bea --- /dev/null +++ b/src/requirements.yaml @@ -0,0 +1,13 @@ +--- +collections: + - name: ansible.posix + version: 1.5.4 + + - name: community.crypto + version: 2.20.0 + + - name: community.general + version: 9.1.0 + + - name: kubernetes.core + version: 5.0.0 diff --git a/src/rootfs/etc/ansible/ansible.cfg b/src/rootfs/etc/ansible/ansible.cfg new file mode 100644 index 0000000..56aff87 --- /dev/null +++ b/src/rootfs/etc/ansible/ansible.cfg @@ -0,0 +1,9 @@ +[defaults] +callbacks_enabled = ansible.posix.timer, community.general.dense, community.general.yaml +callback_result_format = yaml +fact_caching = jsonfile +fact_caching_connection = /tmp +force_color = True +gathering = smart +interpreter_python = /usr/bin/python3 +stdout_callback = community.general.yaml diff --git a/src/rootfs/etc/ansible/hosts b/src/rootfs/etc/ansible/hosts new file mode 100644 index 0000000..a9976c7 --- /dev/null +++ b/src/rootfs/etc/ansible/hosts @@ -0,0 +1,7 @@ +--- +workspace: + hosts: + localhost: + vars: + ansible_connection: local + ansible_become: true diff --git a/src/rootfs/etc/apt/apt.conf.d/99controller b/src/rootfs/etc/apt/apt.conf.d/99controller new file mode 100644 index 0000000..6e124f0 --- /dev/null +++ b/src/rootfs/etc/apt/apt.conf.d/99controller @@ -0,0 +1,6 @@ +APT::Install-Recommends "false"; + +Dpkg::Options { + "--force-confdef"; + "--force-confold"; +} diff --git a/src/rootfs/etc/apt/sources.list.d/extra.sources b/src/rootfs/etc/apt/sources.list.d/extra.sources new file mode 100644 index 0000000..1b2e4d0 --- /dev/null +++ b/src/rootfs/etc/apt/sources.list.d/extra.sources @@ -0,0 +1,14 @@ +##################################### helm ##################################### + +Types: deb +URIs: https://baltocdn.com/helm/stable/debian +Suites: all +Components: main +Signed-By: /etc/apt/keyrings/helm.gpg + +##################################### k8s ###################################### + +Types: deb +URIs: https://pkgs.k8s.io/core:/stable:/v1.30/deb/ +Suites: / +Signed-By: /etc/apt/keyrings/kubernetes.gpg diff --git a/src/rootfs/etc/locale.gen b/src/rootfs/etc/locale.gen new file mode 100644 index 0000000..a66d814 --- /dev/null +++ b/src/rootfs/etc/locale.gen @@ -0,0 +1 @@ +en_US.UTF-8 UTF-8