Skip to content

Commit

Permalink
Add MicroK8s as a platform option (#146)
Browse files Browse the repository at this point in the history
  • Loading branch information
thokra authored and l0rd committed Jul 1, 2019
1 parent a1f1e82 commit 6c96c58
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 4 deletions.
11 changes: 9 additions & 2 deletions src/commands/server/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { MinishiftAddonHelper } from '../../installers/minishift-addon'
import { OperatorHelper } from '../../installers/operator'
import { DockerDesktopHelper } from '../../platforms/docker-desktop'
import { K8sHelper } from '../../platforms/k8s'
import { MicroK8sHelper } from '../../platforms/microk8s'
import { MinikubeHelper } from '../../platforms/minikube'
import { MinishiftHelper } from '../../platforms/minishift'
import { OpenshiftHelper } from '../../platforms/openshift'
Expand Down Expand Up @@ -92,7 +93,7 @@ export default class Start extends Command {
}),
platform: string({
char: 'p',
description: 'Type of Kubernetes platform. Valid values are \"minikube\", \"minishift\", \"k8s\", \"openshift\".',
description: 'Type of Kubernetes platform. Valid values are \"minikube\", \"minishift\", \"k8s\", \"openshift\", \"microk8s\".',
default: 'minikube'
})
}
Expand Down Expand Up @@ -144,6 +145,7 @@ export default class Start extends Command {
kube = new KubeHelper(flags)
Start.setPlaformDefaults(flags)
const minikube = new MinikubeHelper()
const microk8s = new MicroK8sHelper()
const minishift = new MinishiftHelper()
const openshift = new OpenshiftHelper()
const k8s = new K8sHelper()
Expand All @@ -160,7 +162,7 @@ export default class Start extends Command {
this.error(`🛑 Current platform is ${flags.platform}. Minishift addon is only available on top of Minishift platform.`)
}
} else if (flags.installer === 'helm') {
if (flags.platform !== 'k8s' && flags.platform !== 'minikube' && flags.platform !== 'docker-desktop') {
if (flags.platform !== 'k8s' && flags.platform !== 'minikube' && flags.platform !== 'microk8s' && flags.platform !== 'docker-desktop') {
this.error(`🛑 Current platform is ${flags.platform}. Helm installer is only available on top of Kubernetes flavor platform (including Minikube, Docker Desktop).`)
}
}
Expand All @@ -178,6 +180,11 @@ export default class Start extends Command {
title: '✈️ Minishift preflight checklist',
task: () => minishift.startTasks(flags, this)
})
} else if (flags.platform === 'microk8s') {
platformCheckTasks.add({
title: '✈️ MicroK8s preflight checklist',
task: () => microk8s.startTasks(flags, this)
})
} else if (flags.platform === 'openshift') {
platformCheckTasks.add({
title: '✈️ Openshift preflight checklist',
Expand Down
4 changes: 2 additions & 2 deletions src/installers/operator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class OperatorHelper {
const exist = await che.cheNamespaceExist(flags.chenamespace)
if (exist) {
task.title = `${task.title}...It already exist.`
} else if (flags.platform === 'minikube' || flags.platform === 'k8s') {
} else if (flags.platform === 'minikube' || flags.platform === 'k8s' || flags.platform === 'microk8s') {
await execa.shell(`kubectl create namespace ${flags.chenamespace}`)
task.title = `${task.title}...done.`
} else if (flags.platform === 'minishift' || flags.platform === 'openshift') {
Expand All @@ -53,7 +53,7 @@ export class OperatorHelper {
const exist = await kube.serviceAccountExist(this.operatorServiceAccount, flags.chenamespace)
if (exist) {
task.title = `${task.title}...It already exist.`
} else if (flags.platform === 'minikube' || flags.platform === 'k8s') {
} else if (flags.platform === 'minikube' || flags.platform === 'k8s' || flags.platform === 'microk8s') {
await execa.shell(`kubectl create serviceaccount ${this.operatorServiceAccount} -n=${flags.chenamespace}`)
task.title = `${task.title}...done.`
} else if (flags.platform === 'minishift' || flags.platform === 'openshift') {
Expand Down
120 changes: 120 additions & 0 deletions src/platforms/microk8s.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
// tslint:disable:object-curly-spacing

import { Command } from '@oclif/command'
import * as commandExists from 'command-exists'
import * as execa from 'execa'
import * as Listr from 'listr'

export class MicroK8sHelper {
startTasks(flags: any, command: Command): Listr {
return new Listr([
{
title: 'Verify if kubectl is installed',
task: () => {
if (!commandExists.sync('kubectl')) {
command.error('E_REQUISITE_NOT_FOUND')
}
}
},
{ title: 'Verify if microk8s is installed',
task: () => {
if (!commandExists.sync('microk8s.status')) {
command.error('E_REQUISITE_NOT_FOUND', { code: 'E_REQUISITE_NOT_FOUND' })
}
}
},
{ title: 'Verify if microk8s is running',
task: async (ctx: any) => {
ctx.isMicroK8sRunning = await this.isMicroK8sRunning()
}
},
{ title: 'Start microk8s',
skip: (ctx: any) => {
if (ctx.isMicroK8sRunning) {
return 'MicroK8s is already running.'
}
},
task: () => {
// microk8s.start requires sudo permissions
// this.startMicroK8s()
command.error('MicroK8s is not running.', { code: 'E_REQUISITE_NOT_RUNNING' })
}
},
// { title: 'Verify microk8s memory configuration', skip: () => 'Not implemented yet', task: () => {}},
// { title: 'Verify kubernetes version', skip: () => 'Not implemented yet', task: () => {}},
{ title: 'Verify if microk8s ingress and storage addons is enabled',
task: async (ctx: any) => {
ctx.enabledAddons = await this.enabledAddons()
}
},
{ title: 'Enable microk8s ingress addon',
skip: (ctx: any) => {
if (ctx.enabledAddons.ingress) {
return 'Ingress addon is already enabled.'
}
},
task: () => this.enableIngressAddon()
},
{ title: 'Enable microk8s storage addon',
skip: (ctx: any) => {
if (ctx.enabledAddons.storage) {
return 'Storage addon is already enabled.'
}
},
task: () => {
// Enabling storage requires sudo permissions
// this.enableStorageAddon()
return command.error('The storage addon hasn\'t been enabled in microk8s', { code: 'E_REQUISITE_NOT_FOUND' })
}
},
{ title: 'Retrieving microk8s IP and domain for ingress URLs',
enabled: () => flags.domain !== undefined,
task: async (_ctx: any, task: any) => {
const ip = await this.getMicroK8sIP()
flags.domain = ip + '.nip.io'
task.title = `${task.title}...${flags.domain}.`
}
},
], {renderer: flags['listr-renderer'] as any})
}

async isMicroK8sRunning(): Promise<boolean> {
const { code } = await execa('microk8s.status', { timeout: 1000, reject: false })
if (code === 0) { return true } else { return false }
}

async startMicroK8s() {
execa('microk8s.start', { timeout: 180000 })
}

async enabledAddons(): Promise<object> {
const { stdout } = await execa('microk8s.status', [], { timeout: 10000 })
return {
ingress: stdout.includes('ingress: enabled'),
storage: stdout.includes('storage: enabled')
}
}

async enableIngressAddon() {
await execa('microk8s.enable', ['ingress'], { timeout: 10000 })
}

async enableStorageAddon() {
await execa('microk8s.enable', ['storage'], { timeout: 10000 })
}

async getMicroK8sIP(): Promise<string> {
const { stdout } = await execa('microk8s.config', { timeout: 10000 })
const regMatch = /server:\s*https?:\/\/([\d.]+)/.exec(stdout)
return regMatch ? regMatch[1] : ''
}
}
46 changes: 46 additions & 0 deletions test/platforms/microk8s.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
// tslint:disable:object-curly-spacing
import { expect, fancy } from 'fancy-test'
import {MicroK8sHelper} from '../../src/platforms/microk8s';
import * as execa from 'execa';

jest.mock('execa');

let mh = new MicroK8sHelper()

describe('start', () => {
fancy
.it('verifies that microk8s is running', async () => {
(execa as any).mockResolvedValue({ code: 0 })
const res = await mh.isMicroK8sRunning()
expect(res).to.equal(true)
})

fancy
.it('verifies that microk8s is not running', async () => {
(execa as any).mockResolvedValue({ code: 1 })
const res = await mh.isMicroK8sRunning()
expect(res).to.equal(false)
})

fancy
.it('obtains the ip', async () => {
const output = `apiVersion: v1
clusters:
- cluster:
server: http://127.0.0.1:8080
name: microk8s-cluster`;

(execa as any).mockResolvedValue({ code: 0, stdout: output })
const res = await mh.getMicroK8sIP()
expect(res).to.equal('127.0.0.1')
})
})

0 comments on commit 6c96c58

Please sign in to comment.