From 09ffccc2e87f22f5c42bfece4b325d599efb8bac Mon Sep 17 00:00:00 2001 From: balchua Date: Sun, 3 Sep 2023 11:19:27 +0800 Subject: [PATCH 01/16] initial work on launch config --- .github/workflows/e2e.yaml | 88 ++++++++++++++----------- action.yaml | 25 ++++--- lib/addon.js | 44 +++++++++++++ lib/index.js | 118 +++++---------------------------- lib/microk8s.js | 128 ++++++++++++++++++++++++++++++++++++ lib/status.js | 75 +++++++++++++++++++++ lib/util.js | 31 +++++++++ microk8s-config.yaml | 7 ++ src/addon.ts | 24 +++++++ src/index.ts | 130 ++++++------------------------------- src/microk8s.ts | 113 ++++++++++++++++++++++++++++++++ src/status.ts | 44 +++++++++++++ src/util.ts | 9 +++ 13 files changed, 576 insertions(+), 260 deletions(-) create mode 100644 lib/addon.js create mode 100644 lib/microk8s.js create mode 100644 lib/status.js create mode 100644 lib/util.js create mode 100644 microk8s-config.yaml create mode 100644 src/addon.ts create mode 100644 src/microk8s.ts create mode 100644 src/status.ts create mode 100644 src/util.ts diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index d0ad006..e509485 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -6,44 +6,56 @@ jobs: runs-on: ubuntu-latest name: A job to install MicroK8s steps: - - uses: balchua/microk8s-actions@master - with: - channel: '1.26/stable' - addons: '["rbac", "dns", "hostpath-storage", "registry"]' + - name: build-image + run: | + mkdir -p $HOME/sideload + docker pull alpine:edge + docker save alpine:edge > $HOME/sideload/alpine-edge.tar - - name: Check User - run: | - id - sg microk8s -c 'microk8s status' + - uses: balchua/microk8s-actions@feat/launch_config + with: + channel: "1.28/stable" + launch-configuration: "$HOME/microk8s-config.yaml" + sideload-image-path: "$HOME/sideload/" - - name: Check push to local registry - run: | - docker pull busybox:1 - echo $REGISTRY_IP - docker tag busybox:1 localhost:32000/my-repo/busybox:1 - docker push localhost:32000/my-repo/busybox:1 - curl http://localhost:32000/v2/_catalog - - - name: Test MicroK8s - id: microk8s - run: | - set -ex - kubectl get no - kubectl get pods -A -o wide - sleep 120 # Give it sometime before we start checking for pod readiness. - # wait for storage pod to be ready - kubectl -n kube-system wait --for=condition=ready pod -l k8s-app=hostpath-provisioner --timeout=60s - storage_ready=$? + - name: Check Side loaded images + run: | + sudo microk8s ctr images ls | grep alpine:edge + sudo microk8s status --wait-ready - if [ $storage_ready -ne 0 ]; then - echo "Error storage not ready." - exit $storage_ready - fi - - name: Test MicroK8s commands - id: microk8s-commands - run: | - set -ex - echo "Executing microk8s status using sg command." - sg microk8s -c 'microk8s status' - echo "Executing microk8s status using sudo command." - sudo microk8s status + - name: Check User + run: | + id + sg microk8s -c 'microk8s status' + + - name: Check push to local registry + run: | + docker pull busybox:1 + echo $REGISTRY_IP + docker tag busybox:1 localhost:32000/my-repo/busybox:1 + docker push localhost:32000/my-repo/busybox:1 + curl http://localhost:32000/v2/_catalog + + - name: Test MicroK8s + id: microk8s + run: | + set -ex + kubectl get no + kubectl get pods -A -o wide + sleep 120 # Give it sometime before we start checking for pod readiness. + # wait for storage pod to be ready + kubectl -n kube-system wait --for=condition=ready pod -l k8s-app=hostpath-provisioner --timeout=60s + storage_ready=$? + + if [ $storage_ready -ne 0 ]; then + echo "Error storage not ready." + exit $storage_ready + fi + - name: Test MicroK8s commands + id: microk8s-commands + run: | + set -ex + echo "Executing microk8s status using sg command." + sg microk8s -c 'microk8s status' + echo "Executing microk8s status using sudo command." + sudo microk8s status diff --git a/action.yaml b/action.yaml index b4fcf68..f389213 100644 --- a/action.yaml +++ b/action.yaml @@ -1,20 +1,27 @@ -name: 'MicroK8s Action' -description: 'Run a MicroK8s Kubernetes cluster in your GitHub Action' +name: "MicroK8s Action" +description: "Run a MicroK8s Kubernetes cluster in your GitHub Action" author: "balchua" inputs: - channel: # MicroK8s channel - description: 'The MicroK8s Channel to use. More information here https://microk8s.io/docs/setting-snap-channel' + channel: # MicroK8s channel + description: "The MicroK8s Channel to use. More information here https://microk8s.io/docs/setting-snap-channel" required: true - default: 'latest/stable' + default: "latest/stable" devMode: description: "Enable devmode, this is only applicable to strict confinement" required: false default: "false" addons: - description: "A JSON array of addons to enable" + description: "A JSON array of addons to enable" required: false default: "[]" - + launch-configuration: + description: "Fully qualified path where the custom MicroK8s launch configuration is located" + required: false + default: "" + sideload-images-path: + description: "Fully qualified path where the container image tarballs is located" + required: false + default: "" runs: - using: 'node16' - main: 'lib/index.js' \ No newline at end of file + using: "node16" + main: "lib/index.js" diff --git a/lib/addon.js b/lib/addon.js new file mode 100644 index 0000000..75d6435 --- /dev/null +++ b/lib/addon.js @@ -0,0 +1,44 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Addon = void 0; +const util = __importStar(require("./util")); +const status = __importStar(require("./status")); +const sh = __importStar(require("shelljs")); +class Addon { + constructor(addon) { + this.addon = addon; + } + enable() { + sh.echo('Start enabling ' + this.addon); + status.waitForReadyState(); + if (this.addon === "kubeflow") { + sh.echo('kubeflow is no longer supported as a addon'); + } + else { + util.executeCommand(false, 'sudo microk8s enable ' + this.addon); + status.silentWaitForStorageToBeReady(this.addon); + status.silentwaitForRegistryPvClaim(this.addon); + } + status.waitForReadyState(); + } +} +exports.Addon = Addon; diff --git a/lib/index.js b/lib/index.js index 17f44d7..6d9a5a9 100644 --- a/lib/index.js +++ b/lib/index.js @@ -29,120 +29,32 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", { value: true }); const core = __importStar(require("@actions/core")); +//import { exec } from '@actions/exec'; const sh = __importStar(require("shelljs")); +const mk8s = __importStar(require("./microk8s")); function run() { return __awaiter(this, void 0, void 0, function* () { - let channel = core.getInput("channel"); - let addons = core.getInput("addons"); + let addonConfig = core.getInput("addons"); let devMode = core.getInput("devMode"); + let channel = core.getInput("channel"); + let launchConfigPath = core.getInput("launch-configuration"); + let sideloadImagePath = core.getInput("sideload-images-path"); sh.config.fatal = true; sh.config.verbose = true; - let isStrict = isStrictMode(channel); try { - console.log(`'install microk8s [channel: ${channel}] [strict mode: ${isStrict}]'`); - sh.echo("install microk8s [channel: " + channel + "] [strict mode: " + isStrict + "]"); - let microK8scommand = "sudo snap install microk8s --channel=" + channel; - if (isStrict) { - if (devMode === "true") { - microK8scommand = microK8scommand + " --devmode "; - } - } - else { - microK8scommand = microK8scommand + " --classic "; - } - executeCommand(false, microK8scommand); - let startTimeInMillis = Date.now(); - prepareUserEnv(isStrict); - waitForReadyState(isStrict); - if (addons) { - enableAddons(JSON.parse(addons), isStrict); - } - waitTillApiServerIsReady(startTimeInMillis, isStrict); + let addons = JSON.parse(addonConfig); + let microk8s = new mk8s.MicroK8s(channel, addons, devMode, launchConfigPath, sideloadImagePath); + microk8s.install(); + microk8s.enableAddons(); } catch (error) { - core.setFailed(error.message); - } - }); -} -function waitForReadyState(isStrict) { - return __awaiter(this, void 0, void 0, function* () { - let ready = false; - while (!ready) { - yield delay(2000); - let code = executeCommand(true, "sudo microk8s status --wait-ready"); - if (code === 0) { - ready = true; - break; + if (error instanceof Error) { + core.setFailed(error.message); + } + else { + console.log('Unexpected error', error); } } }); } -function prepareUserEnv(isStrict) { - // Create microk8s group - sh.echo("creating microk8s group."); - if (!isStrict) { - executeCommand(false, "sudo usermod -a -G microk8s $USER"); - } - else { - executeCommand(false, "sudo usermod -a -G snap_microk8s $USER"); - } - sh.echo("creating default kubeconfig location."); - executeCommand(false, "mkdir -p '/home/runner/.kube/'"); - sh.echo("Generating kubeconfig file to default location."); - executeCommand(false, "sudo microk8s kubectl config view --raw > $HOME/.kube/config"); - sh.echo("Change default location ownership."); - executeCommand(false, "sudo chown -f -R $USER $HOME/.kube/"); - executeCommand(false, "sudo chmod go-rx $HOME/.kube/config"); -} -function enableAddon(addon, isStrict) { - if (addon) { - sh.echo('Start enabling ' + addon); - waitForReadyState(isStrict); - if (addon === "kubeflow") { - sh.echo('kubeflow is no longer supported as a addon'); - } - else { - executeCommand(false, 'sudo microk8s enable ' + addon); - waitForStorageToBeReady(isStrict, addon); - waitForRegistryPvClaim(isStrict, addon); - } - waitForReadyState(isStrict); - } -} -function delay(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); -} -function enableAddons(addons, isStrict) { - addons.forEach((addon) => { - enableAddon(addon, isStrict); - }); -} -function waitTillApiServerIsReady(startTimeInMillis, isStrict) { - return __awaiter(this, void 0, void 0, function* () { - let endTimeInMillis = startTimeInMillis + 80000; - let elapsed = Date.now(); - if (endTimeInMillis > elapsed) { - yield delay(endTimeInMillis - elapsed); - waitForReadyState(isStrict); - } - }); -} -function isStrictMode(channel) { - return channel.includes("-strict"); -} -function executeCommand(isSilent, command) { - return sh.exec(command, { silent: isSilent }).code; -} -function waitForStorageToBeReady(isSilent, addon) { - if (addon === "hostpath-storage") { - sh.echo('Waiting for hostpath-storage to be ready '); - executeCommand(isSilent, "sudo microk8s kubectl rollout status deployment/hostpath-provisioner -n kube-system --timeout=90s"); - } -} -function waitForRegistryPvClaim(isSilent, addon) { - if (addon === "registry") { - sh.echo('Waiting for registry volume to be bound'); - executeCommand(isSilent, "sudo microk8s kubectl wait --for=jsonpath='{.status.phase}'=Bound pvc/registry-claim -n container-registry --timeout=90s"); - } -} run(); diff --git a/lib/microk8s.js b/lib/microk8s.js new file mode 100644 index 0000000..6c4acac --- /dev/null +++ b/lib/microk8s.js @@ -0,0 +1,128 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MicroK8s = void 0; +const addon_1 = require("./addon"); +const sh = __importStar(require("shelljs")); +const util = __importStar(require("./util")); +const core = __importStar(require("@actions/core")); +const status = __importStar(require("./status")); +class MicroK8s { + constructor(channel, addons, devMode, launchConfigPath, sideloadImagePath) { + this.channel = channel; + this.addons = new Array(addons.length); + addons.forEach((addonString) => { + let addon = new addon_1.Addon(addonString); + this.addons.push(addon); + }); + this.isDevMode = devMode === "true"; + this.isStrictMode = this.channel.includes("-strict"); + this.command = "sudo snap install microk8s --channel=" + this.channel; + this.launchConfigPath = launchConfigPath; + this.sideloadImagePath = sideloadImagePath; + } + generateMicrok8sInstallCommand() { + if (this.isStrictMode) { + this.command = this.command + " --devmode "; + } + else { + this.command = this.command + " --classic "; + } + } + prepareUserEnvironment() { + // Create microk8s group + sh.echo("creating microk8s group."); + if (!this.isStrictMode) { + util.executeCommand(false, "sudo usermod -a -G microk8s $USER"); + } + else { + util.executeCommand(false, "sudo usermod -a -G snap_microk8s $USER"); + } + sh.echo("creating default kubeconfig location."); + util.executeCommand(false, "mkdir -p '$HOME/.kube/'"); + sh.echo("Generating kubeconfig file to default location."); + util.executeCommand(false, "sudo microk8s kubectl config view --raw > $HOME/.kube/config"); + sh.echo("Change default location ownership."); + util.executeCommand(false, "sudo chown -f -R $USER $HOME/.kube/"); + util.executeCommand(false, "sudo chmod go-rx $HOME/.kube/config"); + } + setupLaunchConfiguration() { + if (this.launchConfigPath !== "") { + util.executeCommand(false, "sudo mkdir -p /var/snap/microk8s/common/"); + util.executeCommand(false, "sudo cp " + this.launchConfigPath + " " + "/var/snap/microk8s/common/.microk8s.yaml"); + } + } + sideloadImages() { + if (this.sideloadImagePath !== "") { + util.executeCommand(false, "sudo mkdir -p /var/snap/microk8s/common/sideload"); + util.executeCommand(false, "sudo cp " + this.sideloadImagePath + "/*.tar" + " " + "/var/snap/microk8s/common/sideload/"); + } + } + failToInstall(error) { + if (error instanceof Error) { + core.setFailed(error.message); + } + else { + console.log('Unexpected error', error); + } + } + waitTillApiServerIsReady() { + return __awaiter(this, void 0, void 0, function* () { + let startTimeInMillis = Date.now(); + let endTimeInMillis = startTimeInMillis + 80000; + let elapsed = Date.now(); + if (endTimeInMillis > elapsed) { + yield util.delay(endTimeInMillis - elapsed); + status.waitForReadyState(); + } + }); + } + install() { + console.log(`'install microk8s [channel: ${this.channel}] [strict mode: ${this.isStrictMode}]'`); + sh.echo("install microk8s [channel: " + this.channel + "] [strict mode: " + this.isStrictMode + "]"); + try { + this.prepareUserEnvironment(); + this.setupLaunchConfiguration(); + this.sideloadImages(); + this.generateMicrok8sInstallCommand(); + util.executeCommand(false, this.command); + this.waitTillApiServerIsReady(); + } + catch (error) { + this.failToInstall(error); + } + } + enableAddons() { + this.addons.forEach((addon) => { + addon.enable(); + }); + } +} +exports.MicroK8s = MicroK8s; diff --git a/lib/status.js b/lib/status.js new file mode 100644 index 0000000..19ca1cc --- /dev/null +++ b/lib/status.js @@ -0,0 +1,75 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verbosewaitForRegistryPvClaim = exports.silentwaitForRegistryPvClaim = exports.verboseWaitForStorageToBeReady = exports.silentWaitForStorageToBeReady = exports.waitForReadyState = void 0; +const util = __importStar(require("./util")); +const sh = __importStar(require("shelljs")); +function waitForReadyState() { + return __awaiter(this, void 0, void 0, function* () { + let ready = false; + while (!ready) { + yield util.delay(2000); + let code = util.executeCommand(true, "sudo microk8s status --wait-ready"); + if (code === 0) { + ready = true; + break; + } + } + }); +} +exports.waitForReadyState = waitForReadyState; +function silentWaitForStorageToBeReady(addon) { + waitForStorageToBeReady(true, addon); +} +exports.silentWaitForStorageToBeReady = silentWaitForStorageToBeReady; +function verboseWaitForStorageToBeReady(addon) { + waitForStorageToBeReady(false, addon); +} +exports.verboseWaitForStorageToBeReady = verboseWaitForStorageToBeReady; +function silentwaitForRegistryPvClaim(addon) { + waitForRegistryPvClaim(true, addon); +} +exports.silentwaitForRegistryPvClaim = silentwaitForRegistryPvClaim; +function verbosewaitForRegistryPvClaim(addon) { + waitForRegistryPvClaim(false, addon); +} +exports.verbosewaitForRegistryPvClaim = verbosewaitForRegistryPvClaim; +function waitForStorageToBeReady(isSilent, addon) { + if (addon === "hostpath-storage") { + sh.echo('Waiting for hostpath-storage to be ready '); + util.executeCommand(isSilent, "sudo microk8s kubectl rollout status deployment/hostpath-provisioner -n kube-system --timeout=90s"); + } +} +function waitForRegistryPvClaim(isSilent, addon) { + if (addon === "registry") { + sh.echo('Waiting for registry volume to be bound'); + util.executeCommand(isSilent, "sudo microk8s kubectl wait --for=jsonpath='{.status.phase}'=Bound pvc/registry-claim -n container-registry --timeout=90s"); + } +} diff --git a/lib/util.js b/lib/util.js new file mode 100644 index 0000000..436a90b --- /dev/null +++ b/lib/util.js @@ -0,0 +1,31 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.delay = exports.executeCommand = void 0; +const sh = __importStar(require("shelljs")); +function executeCommand(isSilent, command) { + return sh.exec(command, { silent: isSilent }).code; +} +exports.executeCommand = executeCommand; +function delay(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} +exports.delay = delay; diff --git a/microk8s-config.yaml b/microk8s-config.yaml new file mode 100644 index 0000000..289943b --- /dev/null +++ b/microk8s-config.yaml @@ -0,0 +1,7 @@ +version: 0.1.0 +addons: + - name: dns + - name: rbac + - name: ingress + - name: hostpath-storage + - name: registry diff --git a/src/addon.ts b/src/addon.ts new file mode 100644 index 0000000..e03f8a5 --- /dev/null +++ b/src/addon.ts @@ -0,0 +1,24 @@ +import * as util from './util'; +import * as status from './status'; +import * as sh from 'shelljs'; + +export class Addon { + addon: string; + + constructor(addon: string) { + this.addon = addon; + } + + public enable() { + sh.echo('Start enabling ' + this.addon); + status.waitForReadyState() + if (this.addon === "kubeflow") { + sh.echo('kubeflow is no longer supported as a addon'); + } else { + util.executeCommand(false, 'sudo microk8s enable ' + this.addon) + status.silentWaitForStorageToBeReady(this.addon) + status.silentwaitForRegistryPvClaim(this.addon) + } + status.waitForReadyState() + } +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 9d0a29e..dc57c99 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,132 +1,42 @@ import * as core from '@actions/core'; -import { exec } from '@actions/exec'; +//import { exec } from '@actions/exec'; import * as sh from 'shelljs'; +import * as util from './util'; +import * as status from './status'; +import * as mk8s from './microk8s'; async function run() { - let channel = core.getInput("channel"); - let addons = core.getInput("addons"); + let addonConfig = core.getInput("addons"); let devMode = core.getInput("devMode"); + let channel = core.getInput("channel"); + let launchConfigPath = core.getInput("launch-configuration"); + let sideloadImagePath = core.getInput("sideload-images-path"); sh.config.fatal = true; sh.config.verbose = true - let isStrict = isStrictMode(channel) - try { - console.log(`'install microk8s [channel: ${channel}] [strict mode: ${isStrict}]'`) - sh.echo("install microk8s [channel: " + channel + "] [strict mode: " + isStrict + "]") - let microK8scommand = "sudo snap install microk8s --channel=" + channel; - if (isStrict ) { - if (devMode === "true") { - microK8scommand = microK8scommand + " --devmode " - } - } else { - microK8scommand = microK8scommand + " --classic " - } - executeCommand(false, microK8scommand) - let startTimeInMillis = Date.now(); - prepareUserEnv(isStrict); - waitForReadyState(isStrict); + try { + let addons = JSON.parse(addonConfig); + let microk8s = new mk8s.MicroK8s(channel, + addons, + devMode, + launchConfigPath, + sideloadImagePath); - if (addons) { - enableAddons(JSON.parse(addons), isStrict); - } + microk8s.install(); + microk8s.enableAddons(); - waitTillApiServerIsReady(startTimeInMillis, isStrict) } catch (error) { - core.setFailed(error.message); - } - -} - -async function waitForReadyState(isStrict: boolean) { - let ready = false; - while (!ready) { - await delay(2000); - let code = executeCommand(true, "sudo microk8s status --wait-ready"); - if (code === 0) { - ready = true; - break; - } - } -} - -function prepareUserEnv(isStrict: boolean) { - // Create microk8s group - sh.echo("creating microk8s group."); - if (!isStrict) { - executeCommand(false, "sudo usermod -a -G microk8s $USER") - } else { - executeCommand(false, "sudo usermod -a -G snap_microk8s $USER") - } - sh.echo("creating default kubeconfig location."); - executeCommand(false, "mkdir -p '/home/runner/.kube/'") - sh.echo("Generating kubeconfig file to default location."); - executeCommand(false, "sudo microk8s kubectl config view --raw > $HOME/.kube/config") - sh.echo("Change default location ownership."); - executeCommand(false, "sudo chown -f -R $USER $HOME/.kube/") - executeCommand(false, "sudo chmod go-rx $HOME/.kube/config") - -} - -function enableAddon(addon: string, isStrict: boolean) { - if (addon) { - sh.echo('Start enabling ' + addon); - waitForReadyState(isStrict) - if (addon === "kubeflow") { - sh.echo('kubeflow is no longer supported as a addon'); + if (error instanceof Error) { + core.setFailed(error.message); } else { - executeCommand(false, 'sudo microk8s enable ' + addon) - waitForStorageToBeReady(isStrict, addon) - waitForRegistryPvClaim(isStrict, addon) + console.log('Unexpected error', error); } - waitForReadyState(isStrict) - } -} - -function delay(ms: number) { - return new Promise(resolve => setTimeout(resolve, ms)); -} - -function enableAddons(addons: string[], isStrict: boolean) { - addons.forEach((addon) => { - enableAddon(addon, isStrict); - }); - -} - -async function waitTillApiServerIsReady(startTimeInMillis: number, isStrict: boolean) { - let endTimeInMillis = startTimeInMillis + 80000; - let elapsed = Date.now(); - - if (endTimeInMillis > elapsed) { - await delay(endTimeInMillis - elapsed) - waitForReadyState(isStrict) - } - -} - -function isStrictMode(channel: string): boolean { - return channel.includes("-strict") -} -function executeCommand(isSilent: boolean, command: string) { - return sh.exec(command, { silent: isSilent }).code; -} - -function waitForStorageToBeReady(isSilent: boolean, addon: string) { - if (addon === "hostpath-storage") { - sh.echo('Waiting for hostpath-storage to be ready '); - executeCommand(isSilent, "sudo microk8s kubectl rollout status deployment/hostpath-provisioner -n kube-system --timeout=90s") } -} -function waitForRegistryPvClaim(isSilent: boolean, addon: string) { - if (addon === "registry") { - sh.echo('Waiting for registry volume to be bound'); - executeCommand(isSilent, "sudo microk8s kubectl wait --for=jsonpath='{.status.phase}'=Bound pvc/registry-claim -n container-registry --timeout=90s") - } } run(); \ No newline at end of file diff --git a/src/microk8s.ts b/src/microk8s.ts new file mode 100644 index 0000000..094aa89 --- /dev/null +++ b/src/microk8s.ts @@ -0,0 +1,113 @@ +import { Addon } from "./addon"; +import * as sh from 'shelljs'; +import * as util from './util'; +import * as core from '@actions/core'; +import * as status from './status'; + +export class MicroK8s { + channel: string; + addons: Array; + isStrictMode: boolean; + isDevMode: boolean; + command: string; + launchConfigPath: string; + sideloadImagePath: string; + + + constructor(channel: string, addons: string[], devMode: string, launchConfigPath: string, sideloadImagePath: string) { + this.channel = channel; + this.addons = new Array(addons.length); + addons.forEach((addonString) => { + let addon = new Addon(addonString); + this.addons.push(addon); + }); + this.isDevMode = devMode === "true"; + this.isStrictMode = this.channel.includes("-strict"); + this.command = "sudo snap install microk8s --channel=" + this.channel; + this.launchConfigPath = launchConfigPath; + this.sideloadImagePath = sideloadImagePath; + } + + private generateMicrok8sInstallCommand() { + if (this.isStrictMode) { + this.command = this.command + " --devmode " + } else { + this.command = this.command + " --classic " + } + } + + private prepareUserEnvironment() { + // Create microk8s group + sh.echo("creating microk8s group."); + if (!this.isStrictMode) { + util.executeCommand(false, "sudo usermod -a -G microk8s $USER") + } else { + util.executeCommand(false, "sudo usermod -a -G snap_microk8s $USER") + } + sh.echo("creating default kubeconfig location."); + util.executeCommand(false, "mkdir -p '$HOME/.kube/'") + sh.echo("Generating kubeconfig file to default location."); + util.executeCommand(false, "sudo microk8s kubectl config view --raw > $HOME/.kube/config") + sh.echo("Change default location ownership."); + util.executeCommand(false, "sudo chown -f -R $USER $HOME/.kube/") + util.executeCommand(false, "sudo chmod go-rx $HOME/.kube/config") + + + } + + private setupLaunchConfiguration() { + if (this.launchConfigPath !== "") { + util.executeCommand(false, "sudo mkdir -p /var/snap/microk8s/common/"); + util.executeCommand(false, "sudo cp " + this.launchConfigPath + " " + "/var/snap/microk8s/common/.microk8s.yaml"); + } + } + + private sideloadImages() { + if (this.sideloadImagePath !== "") { + util.executeCommand(false, "sudo mkdir -p /var/snap/microk8s/common/sideload"); + util.executeCommand(false, "sudo cp " + this.sideloadImagePath + "/*.tar" + " " + "/var/snap/microk8s/common/sideload/"); + } + } + + private failToInstall(error) { + if (error instanceof Error) { + core.setFailed(error.message); + } else { + console.log('Unexpected error', error); + } + } + + private async waitTillApiServerIsReady() { + let startTimeInMillis = Date.now(); + let endTimeInMillis = startTimeInMillis + 80000; + let elapsed = Date.now(); + + if (endTimeInMillis > elapsed) { + await util.delay(endTimeInMillis - elapsed) + status.waitForReadyState() + } + + } + + public install() { + console.log(`'install microk8s [channel: ${this.channel}] [strict mode: ${this.isStrictMode}]'`) + sh.echo("install microk8s [channel: " + this.channel + "] [strict mode: " + this.isStrictMode + "]") + try { + this.prepareUserEnvironment(); + this.setupLaunchConfiguration(); + this.sideloadImages(); + this.generateMicrok8sInstallCommand(); + util.executeCommand(false, this.command); + this.waitTillApiServerIsReady(); + } catch (error) { + this.failToInstall(error); + } + } + + public enableAddons() { + this.addons.forEach((addon) => { + addon.enable(); + }); + } + +} \ No newline at end of file diff --git a/src/status.ts b/src/status.ts new file mode 100644 index 0000000..c2f8a5e --- /dev/null +++ b/src/status.ts @@ -0,0 +1,44 @@ +import * as util from './util'; +import * as sh from 'shelljs'; +import * as status from './status' + +export async function waitForReadyState() { + let ready = false; + while (!ready) { + await util.delay(2000); + let code = util.executeCommand(true, "sudo microk8s status --wait-ready"); + if (code === 0) { + ready = true; + break; + } + } +} + +export function silentWaitForStorageToBeReady(addon: string) { + waitForStorageToBeReady(true, addon); +} + +export function verboseWaitForStorageToBeReady(addon: string) { + waitForStorageToBeReady(false, addon); +} + +export function silentwaitForRegistryPvClaim(addon: string) { + waitForRegistryPvClaim(true, addon); +} + +export function verbosewaitForRegistryPvClaim(addon: string) { + waitForRegistryPvClaim(false, addon); +} +function waitForStorageToBeReady(isSilent: boolean, addon: string) { + if (addon === "hostpath-storage") { + sh.echo('Waiting for hostpath-storage to be ready '); + util.executeCommand(isSilent, "sudo microk8s kubectl rollout status deployment/hostpath-provisioner -n kube-system --timeout=90s") + } +} + +function waitForRegistryPvClaim(isSilent: boolean, addon: string) { + if (addon === "registry") { + sh.echo('Waiting for registry volume to be bound'); + util.executeCommand(isSilent, "sudo microk8s kubectl wait --for=jsonpath='{.status.phase}'=Bound pvc/registry-claim -n container-registry --timeout=90s") + } +} \ No newline at end of file diff --git a/src/util.ts b/src/util.ts new file mode 100644 index 0000000..466890a --- /dev/null +++ b/src/util.ts @@ -0,0 +1,9 @@ +import * as sh from 'shelljs'; + +export function executeCommand(isSilent: boolean, command: string) { + return sh.exec(command, { silent: isSilent }).code; +} + +export function delay(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)); +} \ No newline at end of file From 0b2aedef4f49ab0245b75cbf8f633ff9f0fbbe81 Mon Sep 17 00:00:00 2001 From: balchua Date: Sun, 3 Sep 2023 11:20:39 +0800 Subject: [PATCH 02/16] fix yaml --- .github/workflows/e2e.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index e509485..47bbaec 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -16,7 +16,7 @@ jobs: with: channel: "1.28/stable" launch-configuration: "$HOME/microk8s-config.yaml" - sideload-image-path: "$HOME/sideload/" + sideload-images-path: "$HOME/sideload/" - name: Check Side loaded images run: | From f5cd0de192991abc49434838fb75b9630c8e6f65 Mon Sep 17 00:00:00 2001 From: balchua Date: Sun, 3 Sep 2023 11:28:23 +0800 Subject: [PATCH 03/16] fix group creation --- lib/microk8s.js | 2 +- src/microk8s.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/microk8s.js b/lib/microk8s.js index 6c4acac..d0c7e84 100644 --- a/lib/microk8s.js +++ b/lib/microk8s.js @@ -108,11 +108,11 @@ class MicroK8s { console.log(`'install microk8s [channel: ${this.channel}] [strict mode: ${this.isStrictMode}]'`); sh.echo("install microk8s [channel: " + this.channel + "] [strict mode: " + this.isStrictMode + "]"); try { - this.prepareUserEnvironment(); this.setupLaunchConfiguration(); this.sideloadImages(); this.generateMicrok8sInstallCommand(); util.executeCommand(false, this.command); + this.prepareUserEnvironment(); this.waitTillApiServerIsReady(); } catch (error) { diff --git a/src/microk8s.ts b/src/microk8s.ts index 094aa89..dcf95c4 100644 --- a/src/microk8s.ts +++ b/src/microk8s.ts @@ -40,12 +40,12 @@ export class MicroK8s { // Create microk8s group sh.echo("creating microk8s group."); if (!this.isStrictMode) { - util.executeCommand(false, "sudo usermod -a -G microk8s $USER") + util.executeCommand(false, "sudo usermod -a -G microk8s $USER"); } else { - util.executeCommand(false, "sudo usermod -a -G snap_microk8s $USER") + util.executeCommand(false, "sudo usermod -a -G snap_microk8s $USER"); } sh.echo("creating default kubeconfig location."); - util.executeCommand(false, "mkdir -p '$HOME/.kube/'") + util.executeCommand(false, "mkdir -p '$HOME/.kube/'"); sh.echo("Generating kubeconfig file to default location."); util.executeCommand(false, "sudo microk8s kubectl config view --raw > $HOME/.kube/config") sh.echo("Change default location ownership."); @@ -93,11 +93,11 @@ export class MicroK8s { console.log(`'install microk8s [channel: ${this.channel}] [strict mode: ${this.isStrictMode}]'`) sh.echo("install microk8s [channel: " + this.channel + "] [strict mode: " + this.isStrictMode + "]") try { - this.prepareUserEnvironment(); this.setupLaunchConfiguration(); this.sideloadImages(); this.generateMicrok8sInstallCommand(); util.executeCommand(false, this.command); + this.prepareUserEnvironment(); this.waitTillApiServerIsReady(); } catch (error) { this.failToInstall(error); From 805a51baa2eb0c3739b92faba4a50c7516152bee Mon Sep 17 00:00:00 2001 From: balchua Date: Sun, 3 Sep 2023 11:33:23 +0800 Subject: [PATCH 04/16] create microk8s config file --- .github/workflows/e2e.yaml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 47bbaec..7f63be1 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -6,11 +6,20 @@ jobs: runs-on: ubuntu-latest name: A job to install MicroK8s steps: - - name: build-image + - name: build-image-and-create-microk8s-config run: | mkdir -p $HOME/sideload docker pull alpine:edge docker save alpine:edge > $HOME/sideload/alpine-edge.tar + cat > microk8s-config.yaml << EOF + version: 0.1.0 + addons: + - name: dns + - name: rbac + - name: ingress + - name: hostpath-storage + - name: registry + EOF - uses: balchua/microk8s-actions@feat/launch_config with: From 6b951bb383e7ee1ede932897ea3bff64ee2dbb32 Mon Sep 17 00:00:00 2001 From: balchua Date: Sun, 3 Sep 2023 11:37:14 +0800 Subject: [PATCH 05/16] checkout the micrk8s-config.yaml file --- .github/workflows/e2e.yaml | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 7f63be1..59ad244 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -4,27 +4,25 @@ on: [push] jobs: test: runs-on: ubuntu-latest + name: A job to install MicroK8s steps: + - uses: actions/checkout@v3 + with: + sparse-checkout: | + microk8s-config.yaml + sparse-checkout-cone-mode: false + - name: build-image-and-create-microk8s-config run: | mkdir -p $HOME/sideload docker pull alpine:edge docker save alpine:edge > $HOME/sideload/alpine-edge.tar - cat > microk8s-config.yaml << EOF - version: 0.1.0 - addons: - - name: dns - - name: rbac - - name: ingress - - name: hostpath-storage - - name: registry - EOF - uses: balchua/microk8s-actions@feat/launch_config with: channel: "1.28/stable" - launch-configuration: "$HOME/microk8s-config.yaml" + launch-configuration: "$GITHUB_WORKSPACE/microk8s-config.yaml" sideload-images-path: "$HOME/sideload/" - name: Check Side loaded images From 3789e6bdb54f9a5f644a18bbb8ffb29b689abdea Mon Sep 17 00:00:00 2001 From: balchua Date: Sun, 3 Sep 2023 11:40:47 +0800 Subject: [PATCH 06/16] make sure the .kube dir is created --- lib/microk8s.js | 2 +- src/microk8s.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/microk8s.js b/lib/microk8s.js index d0c7e84..f159a46 100644 --- a/lib/microk8s.js +++ b/lib/microk8s.js @@ -66,7 +66,7 @@ class MicroK8s { util.executeCommand(false, "sudo usermod -a -G snap_microk8s $USER"); } sh.echo("creating default kubeconfig location."); - util.executeCommand(false, "mkdir -p '$HOME/.kube/'"); + util.executeCommand(false, "mkdir -p $HOME/.kube/"); sh.echo("Generating kubeconfig file to default location."); util.executeCommand(false, "sudo microk8s kubectl config view --raw > $HOME/.kube/config"); sh.echo("Change default location ownership."); diff --git a/src/microk8s.ts b/src/microk8s.ts index dcf95c4..ccd5ecd 100644 --- a/src/microk8s.ts +++ b/src/microk8s.ts @@ -45,7 +45,7 @@ export class MicroK8s { util.executeCommand(false, "sudo usermod -a -G snap_microk8s $USER"); } sh.echo("creating default kubeconfig location."); - util.executeCommand(false, "mkdir -p '$HOME/.kube/'"); + util.executeCommand(false, "mkdir -p $HOME/.kube/"); sh.echo("Generating kubeconfig file to default location."); util.executeCommand(false, "sudo microk8s kubectl config view --raw > $HOME/.kube/config") sh.echo("Change default location ownership."); From 3107884d387797d0192bdf3a5ce0a4d4bd2d2af8 Mon Sep 17 00:00:00 2001 From: balchua Date: Sun, 3 Sep 2023 14:23:07 +0800 Subject: [PATCH 07/16] create new test actions --- .github/workflows/e2.yaml | 49 +++++++++++++++++++ .../{e2e.yaml => launch-config.yaml} | 5 +- 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/e2.yaml rename .github/workflows/{e2e.yaml => launch-config.yaml} (91%) diff --git a/.github/workflows/e2.yaml b/.github/workflows/e2.yaml new file mode 100644 index 0000000..712186a --- /dev/null +++ b/.github/workflows/e2.yaml @@ -0,0 +1,49 @@ +name: Test Microk8s +on: [push] + +jobs: + test: + runs-on: ubuntu-latest + name: A job to install MicroK8s + steps: + - uses: balchua/microk8s-actions@master + with: + channel: "1.26/stable" + addons: '["rbac", "dns", "hostpath-storage", "registry"]' + + - name: Check User + run: | + id + sg microk8s -c 'microk8s status' + + - name: Check push to local registry + run: | + docker pull busybox:1 + echo $REGISTRY_IP + docker tag busybox:1 localhost:32000/my-repo/busybox:1 + docker push localhost:32000/my-repo/busybox:1 + curl http://localhost:32000/v2/_catalog + + - name: Test MicroK8s + id: microk8s + run: | + set -ex + kubectl get no + kubectl get pods -A -o wide + sleep 120 # Give it sometime before we start checking for pod readiness. + # wait for storage pod to be ready + kubectl -n kube-system wait --for=condition=ready pod -l k8s-app=hostpath-provisioner --timeout=60s + storage_ready=$? + + if [ $storage_ready -ne 0 ]; then + echo "Error storage not ready." + exit $storage_ready + fi + - name: Test MicroK8s commands + id: microk8s-commands + run: | + set -ex + echo "Executing microk8s status using sg command." + sg microk8s -c 'microk8s status' + echo "Executing microk8s status using sudo command." + sudo microk8s status diff --git a/.github/workflows/e2e.yaml b/.github/workflows/launch-config.yaml similarity index 91% rename from .github/workflows/e2e.yaml rename to .github/workflows/launch-config.yaml index 59ad244..faee5a7 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/launch-config.yaml @@ -28,6 +28,9 @@ jobs: - name: Check Side loaded images run: | sudo microk8s ctr images ls | grep alpine:edge + + - name: Check enabled addons + run: | sudo microk8s status --wait-ready - name: Check User @@ -37,8 +40,8 @@ jobs: - name: Check push to local registry run: | + sudo microk8s kubectl wait --for=jsonpath='{.status.phase}'=Bound pvc/registry-claim -n container-registry --timeout=90s docker pull busybox:1 - echo $REGISTRY_IP docker tag busybox:1 localhost:32000/my-repo/busybox:1 docker push localhost:32000/my-repo/busybox:1 curl http://localhost:32000/v2/_catalog From a6b1b94ef6a1cb44119f619b41925be8f03d2b77 Mon Sep 17 00:00:00 2001 From: balchua Date: Sun, 3 Sep 2023 14:24:26 +0800 Subject: [PATCH 08/16] rename job name and description --- .github/workflows/launch-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/launch-config.yaml b/.github/workflows/launch-config.yaml index faee5a7..636d728 100644 --- a/.github/workflows/launch-config.yaml +++ b/.github/workflows/launch-config.yaml @@ -1,11 +1,11 @@ -name: Test Microk8s +name: Test Launch Configuration Microk8s on: [push] jobs: test: runs-on: ubuntu-latest - name: A job to install MicroK8s + name: A job to install MicroK8s with launch configurations steps: - uses: actions/checkout@v3 with: From 7e6f60bb8d30030edd596f3b4258dc1e205998b4 Mon Sep 17 00:00:00 2001 From: balchua Date: Sun, 3 Sep 2023 14:39:16 +0800 Subject: [PATCH 09/16] wait for registry pod to be ready --- .github/workflows/launch-config.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/launch-config.yaml b/.github/workflows/launch-config.yaml index 636d728..10051e0 100644 --- a/.github/workflows/launch-config.yaml +++ b/.github/workflows/launch-config.yaml @@ -31,7 +31,11 @@ jobs: - name: Check enabled addons run: | - sudo microk8s status --wait-ready + sudo microk8s status --addon dns --wait-ready | grep enabled + sudo microk8s status --addon ingress --wait-ready | grep enabled + sudo microk8s status --addon rbac --wait-ready | grep enabled + sudo microk8s status --addon hostpath-storage --wait-ready | grep enabled + sudo microk8s status --addon registry --wait-ready | grep enabled - name: Check User run: | @@ -41,6 +45,7 @@ jobs: - name: Check push to local registry run: | sudo microk8s kubectl wait --for=jsonpath='{.status.phase}'=Bound pvc/registry-claim -n container-registry --timeout=90s + sudo microk8s kubectl wait pods --for=jsonpath='{.status.phase}'=Running -l app=registry -n container-registry --timeout=90s docker pull busybox:1 docker tag busybox:1 localhost:32000/my-repo/busybox:1 docker push localhost:32000/my-repo/busybox:1 From a0f4d4c5cfc1743cd8f2eec098ae66cb30d95ea6 Mon Sep 17 00:00:00 2001 From: balchua Date: Sun, 3 Sep 2023 14:49:47 +0800 Subject: [PATCH 10/16] wait for ingress to be ready --- .github/workflows/launch-config.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/launch-config.yaml b/.github/workflows/launch-config.yaml index 10051e0..b3c3b98 100644 --- a/.github/workflows/launch-config.yaml +++ b/.github/workflows/launch-config.yaml @@ -31,6 +31,8 @@ jobs: - name: Check enabled addons run: | + sudo microk8s kubectl wait pods --for=jsonpath='{.status.phase}'=Running -l name=nginx-ingress-microk8s -n ingress --timeout=90s + sudo microk8s status --wait-ready sudo microk8s status --addon dns --wait-ready | grep enabled sudo microk8s status --addon ingress --wait-ready | grep enabled sudo microk8s status --addon rbac --wait-ready | grep enabled From 657c64e98b1a5a67cd903dd3af6deec9044d36a0 Mon Sep 17 00:00:00 2001 From: balchua Date: Sun, 3 Sep 2023 14:58:06 +0800 Subject: [PATCH 11/16] test --- .github/workflows/launch-config.yaml | 12 ++++++------ README.md | 28 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/.github/workflows/launch-config.yaml b/.github/workflows/launch-config.yaml index b3c3b98..898f704 100644 --- a/.github/workflows/launch-config.yaml +++ b/.github/workflows/launch-config.yaml @@ -31,13 +31,13 @@ jobs: - name: Check enabled addons run: | - sudo microk8s kubectl wait pods --for=jsonpath='{.status.phase}'=Running -l name=nginx-ingress-microk8s -n ingress --timeout=90s + # sudo microk8s kubectl wait pods --for=jsonpath='{.status.phase}'=Running -l name=nginx-ingress-microk8s -n ingress --timeout=90s sudo microk8s status --wait-ready - sudo microk8s status --addon dns --wait-ready | grep enabled - sudo microk8s status --addon ingress --wait-ready | grep enabled - sudo microk8s status --addon rbac --wait-ready | grep enabled - sudo microk8s status --addon hostpath-storage --wait-ready | grep enabled - sudo microk8s status --addon registry --wait-ready | grep enabled + # sudo microk8s status --addon dns --wait-ready | grep enabled + # sudo microk8s status --addon ingress --wait-ready | grep enabled + # sudo microk8s status --addon rbac --wait-ready | grep enabled + # sudo microk8s status --addon hostpath-storage --wait-ready | grep enabled + # sudo microk8s status --addon registry --wait-ready | grep enabled - name: Check User run: | diff --git a/README.md b/README.md index a2add9f..10a31ba 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,35 @@ New from `v0.2.0` New from `v0.3.0` +### `launch-configuration` +New from `v0.4.0` + +**Optional** A launch configuration is a YAML configuration file that can be applied to a MicroK8s node typically during installation. Example: `/home/runner/microk8s-config.yaml` + +Once you have defined your `launch-configuration`, there is no need to add the addons one by one in the config. + +Example: + +``` yaml +- uses: balchua/microk8s-actions@feat/launch_config + with: + channel: "1.28/stable" + launch-configuration: "$GITHUB_WORKSPACE/microk8s-config.yaml" + sideload-images-path: "$HOME/sideload/" +``` + +**This is only available from MicroK8s `v1.27`** + +### `sideload-images-path` + +New from `v0.4.0` + +**Optional** Side loading images automatically loads image tarballs to MicroK8s Containerd. You can use this to automatically load your images into MicroK8s, without using a registry . Example: `/home/runner/sideload/` + +Please note that this is applicable during MicroK8s installation. + +**This is only available from MicroK8s `v1.27`** ## Example Usage: From 7f277dfa538adc7daa93366454a8eb94d9641b0b Mon Sep 17 00:00:00 2001 From: balchua Date: Sun, 3 Sep 2023 15:02:38 +0800 Subject: [PATCH 12/16] add 3 mins before checking the addons again --- .github/workflows/launch-config.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/launch-config.yaml b/.github/workflows/launch-config.yaml index 898f704..a2961b7 100644 --- a/.github/workflows/launch-config.yaml +++ b/.github/workflows/launch-config.yaml @@ -38,6 +38,8 @@ jobs: # sudo microk8s status --addon rbac --wait-ready | grep enabled # sudo microk8s status --addon hostpath-storage --wait-ready | grep enabled # sudo microk8s status --addon registry --wait-ready | grep enabled + sleep 20000 + sudo microk8s status --wait-ready - name: Check User run: | From 69cb801ee7ebccdd771a9123044c6ba8ec7a70e1 Mon Sep 17 00:00:00 2001 From: balchua Date: Sun, 3 Sep 2023 15:06:44 +0800 Subject: [PATCH 13/16] add timeout before checking the addons --- .github/workflows/launch-config.yaml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/launch-config.yaml b/.github/workflows/launch-config.yaml index a2961b7..bc250d0 100644 --- a/.github/workflows/launch-config.yaml +++ b/.github/workflows/launch-config.yaml @@ -31,15 +31,15 @@ jobs: - name: Check enabled addons run: | - # sudo microk8s kubectl wait pods --for=jsonpath='{.status.phase}'=Running -l name=nginx-ingress-microk8s -n ingress --timeout=90s - sudo microk8s status --wait-ready - # sudo microk8s status --addon dns --wait-ready | grep enabled - # sudo microk8s status --addon ingress --wait-ready | grep enabled - # sudo microk8s status --addon rbac --wait-ready | grep enabled - # sudo microk8s status --addon hostpath-storage --wait-ready | grep enabled - # sudo microk8s status --addon registry --wait-ready | grep enabled - sleep 20000 + echo "wait for a few seconds" + sleep 120 + sudo microk8s kubectl wait pods --for=jsonpath='{.status.phase}'=Running -l name=nginx-ingress-microk8s -n ingress --timeout=300s sudo microk8s status --wait-ready + sudo microk8s status --addon dns --wait-ready | grep enabled + sudo microk8s status --addon ingress --wait-ready | grep enabled + sudo microk8s status --addon rbac --wait-ready | grep enabled + sudo microk8s status --addon hostpath-storage --wait-ready | grep enabled + sudo microk8s status --addon registry --wait-ready | grep enabled - name: Check User run: | From 92fb71bbd51d6cfddef361fe504025dd54bfb642 Mon Sep 17 00:00:00 2001 From: balchua Date: Sun, 3 Sep 2023 15:12:39 +0800 Subject: [PATCH 14/16] ready for release --- .github/workflows/launch-config.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/launch-config.yaml b/.github/workflows/launch-config.yaml index bc250d0..6820865 100644 --- a/.github/workflows/launch-config.yaml +++ b/.github/workflows/launch-config.yaml @@ -41,11 +41,6 @@ jobs: sudo microk8s status --addon hostpath-storage --wait-ready | grep enabled sudo microk8s status --addon registry --wait-ready | grep enabled - - name: Check User - run: | - id - sg microk8s -c 'microk8s status' - - name: Check push to local registry run: | sudo microk8s kubectl wait --for=jsonpath='{.status.phase}'=Bound pvc/registry-claim -n container-registry --timeout=90s From 990417e64c02e8aa18fa5295a7563903365840df Mon Sep 17 00:00:00 2001 From: balchua Date: Sun, 3 Sep 2023 15:25:59 +0800 Subject: [PATCH 15/16] add more notes --- README.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 10a31ba..17d13d1 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,12 @@ Example: New from `v0.4.0` -**Optional** Side loading images automatically loads image tarballs to MicroK8s Containerd. You can use this to automatically load your images into MicroK8s, without using a registry . Example: `/home/runner/sideload/` +**Optional** + +Side load images automatically loads image tarballs to MicroK8s Containerd. +You can use this to automatically load your images into MicroK8s, without using a registry . + +Example: `/home/runner/sideload/` Please note that this is applicable during MicroK8s installation. @@ -166,7 +171,9 @@ For more information regarding kubeflow addon check this [link](https://microk8s ## Building -The main program is a Typescript, located in [src/index.ts](src/index.ts). Before pushing the code to Github, you should compile the source to ES6. +The main program is a Typescript, located in [src](src/). + +Before pushing the code to Github, you should compile the source to ES6. ```shell $ npm run build From 7e84b773fff5b15d42ff49065ca52b3399c79f1a Mon Sep 17 00:00:00 2001 From: balchua Date: Sun, 3 Sep 2023 15:26:57 +0800 Subject: [PATCH 16/16] change to master --- .github/workflows/launch-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/launch-config.yaml b/.github/workflows/launch-config.yaml index 6820865..888cf1c 100644 --- a/.github/workflows/launch-config.yaml +++ b/.github/workflows/launch-config.yaml @@ -19,7 +19,7 @@ jobs: docker pull alpine:edge docker save alpine:edge > $HOME/sideload/alpine-edge.tar - - uses: balchua/microk8s-actions@feat/launch_config + - uses: balchua/microk8s-actions@master with: channel: "1.28/stable" launch-configuration: "$GITHUB_WORKSPACE/microk8s-config.yaml"