From 3b8138b68f4685fc362d3d150f78eee248f6110a Mon Sep 17 00:00:00 2001
From: Maarten de Waard <maarten@greenhost.nl>
Date: Mon, 12 Apr 2021 12:33:58 +0200
Subject: [PATCH] use custom disk image for CI VPSs and document how to update
 it

---
 .gitlab-ci.yml                   |  3 ++-
 .gitlab/ci_scripts/create_vps.sh |  1 +
 CONTRIBUTING.md                  | 43 ++++++++++++++++++++++++++++++++
 openappstack/__main__.py         | 15 ++++++++---
 4 files changed, 57 insertions(+), 5 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 21784a30b..790abeef2 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -186,7 +186,8 @@ create-vps:
   stage: create-vps
   script:
     - *debug_information
-    # Creates the VPS only if an old VPS for this branch is not re-usable
+    # Creates a VPS based on a custom CI image for which --install-kubernetes
+    # has already run. See CONTRIBUTING.md#ci-pipeline-image for more info
     - sh .gitlab/ci_scripts/create_vps.sh
   artifacts:
     paths:
diff --git a/.gitlab/ci_scripts/create_vps.sh b/.gitlab/ci_scripts/create_vps.sh
index 55f058d18..123755568 100644
--- a/.gitlab/ci_scripts/create_vps.sh
+++ b/.gitlab/ci_scripts/create_vps.sh
@@ -7,6 +7,7 @@ set -ve
 echo "Deleting old machine"
 python3 -c "import greenhost_cloud; greenhost_cloud.terminate_droplets_by_name(\"^${HOSTNAME}$\")"
 echo "Creating new machine"
+# Uses a custom disk image. See CONTRIBUTING.md#ci-pipeline-image for more info.
 python3 -m openappstack $HOSTNAME create \
   --acme-staging \
   --local-flux \
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 0a8b888b9..bf7445e13 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -46,3 +46,46 @@ but also its dependencies.
 
 If the new package you are adding is only used by developers,
 please add it to the `requirements-dev.txt` file.
+
+## CI pipeline image
+
+We use a custom disk image for the VPSs used by the CI pipeline. On this image,
+the `install-kubernetes.yaml` playbook has already been applied, which usually
+saves a few minutes of pipeline running time.
+
+### What to do when I change a part of the `install-kubernetes.yaml` playbook?
+
+Don't worry, the playbook *runs* in the CI (just faster, because usually
+nothing needs to change). So if you make changes, you can test those in the CI
+without problems.
+
+If you want to start with a clean slate, however, you might want to change
+`.gitlab/ci_scripts/create_vps.sh` and temporarily remove the `--disk-image-id`
+argument.
+
+#### Before you merge, make sure your changes are applied to a new custom image:
+
+If you changed the `install-kubernetes.yaml` playbook, for example to upgrade
+the k3s version in use, you'll want to generate a new disk image template and
+use it. This is a manual process for now. Follow these steps:
+
+1. Create a new VPS
+2. Run the following to install *only kubernetes* on the VPS:
+   ```
+   $ python3 -m openappstack <cluster> install --install-kubernetes --no-install-openappstack
+   ```
+3. Log into Cosmos with the OpenAppStack account
+4. Go to VPS Cloud -> VPS and shut down your VPS
+5. Go to VPS Cloud -> Disk Images and click edit for your VPSs disk image
+   1. Change the Disk Label to something like `k3s-template`
+   2. Set VPS to `-- not assigned --`
+   3. Click 'make template'
+   4. Remember the disk image ID that you can see in the current URL as `id=...`
+   5. Click save
+6. Change the `--disk-image-id` argument in `.gitlab/ci_scripts/create_vps.sh`
+   to your current disk-image-id **with a minus in front of it**. This is
+   because custom images are negative integers, whereas Greenhost's disk images
+   are positive integers
+
+You are now ready to merge the changes you made to the `install-kubernetes`
+playbook
diff --git a/openappstack/__main__.py b/openappstack/__main__.py
index 70783f796..b8d0ed6c1 100755
--- a/openappstack/__main__.py
+++ b/openappstack/__main__.py
@@ -187,6 +187,12 @@ def main():  # pylint: disable=too-many-statements,too-many-branches,too-many-lo
         action='store_true',
         help="Installs k3s on your VPS before installing OpenAppStack")
 
+    install_parser.add_argument(
+        '--no-install-openappstack',
+        action='store_true',
+        help=("Skip openappstack installation. This is useful if you only "
+              "want a kubernetes cluster."))
+
     test_parser = subparsers.add_parser(
         'test',
         help=("Write test configuration and run tests on your cluster"))
@@ -368,10 +374,11 @@ def install(clus, args):
             os.path.join(ansible.ANSIBLE_PATH, 'install-kubernetes.yml'),
             args.ansible_param)
 
-    ansible.run_ansible(
-        clus,
-        os.path.join(ansible.ANSIBLE_PATH, 'install-openappstack.yml'),
-        args.ansible_param)
+    if not args.no_install_openappstack:
+        ansible.run_ansible(
+            clus,
+            os.path.join(ansible.ANSIBLE_PATH, 'install-openappstack.yml'),
+            args.ansible_param)
 
 
 def test(clus, args):
-- 
GitLab