Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade APIVersion of Knative CR #6

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 75 additions & 36 deletions src/serverless.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
const path = require('path')
const { isEmpty, mergeDeepRight } = require('ramda')
const kubernetes = require('@kubernetes/client-node')
const { Component } = require('@serverless/core')

const defaults = {
kubeConfigPath: path.join(process.env.HOME, '.kube', 'config'),
knativeGroup: 'serving.knative.dev',
knativeVersion: 'v1alpha1',
knativeVersion: 'v1',
registryAddress: 'docker.io',
namespace: 'default'
}

class KnativeServing extends Component {
async deploy(inputs = {}) {
const config = {
...defaults,
...inputs
}
async default(inputs = {}) {
const config = mergeDeepRight(defaults, inputs)

const k8sCustom = this.getKubernetesClient(kubernetes.CustomObjectsApi)
const k8sCore = this.getKubernetesClient(config.kubeConfigPath, kubernetes.CoreV1Api)
const k8sCustom = this.getKubernetesClient(config.kubeConfigPath, kubernetes.CustomObjectsApi)

let serviceExists = true
try {
Expand All @@ -36,29 +37,59 @@ class KnativeServing extends Component {
const serviceUrl = await this.getServiceUrl(k8sCustom, config)
config.serviceUrl = serviceUrl

const istioIngressIp = await this.getIstioIngressIp(k8sCore)
config.istioIngressIp = istioIngressIp

this.state = config
return this.state
}

async remove(inputs = {}) {
const config = {
...defaults,
...inputs,
...this.state
let config = mergeDeepRight(defaults, inputs)
if (isEmpty(config)) {
config = this.state
}

const k8sCustom = this.getKubernetesClient(kubernetes.CustomObjectsApi)
const k8sCustom = this.getKubernetesClient(config.kubeConfigPath, kubernetes.CustomObjectsApi)

let params = Object.assign({}, config)
const manifest = this.getManifest(params)
params = Object.assign(params, { manifest })
await this.deleteService(k8sCustom, params)

this.state = {}
await this.save()
return {}
}

async info(inputs = {}) {
const config = mergeDeepRight(defaults, inputs)

const k8sCore = this.getKubernetesClient(config.kubeConfigPath, kubernetes.CoreV1Api)
const k8sCustom = this.getKubernetesClient(config.kubeConfigPath, kubernetes.CustomObjectsApi)
const serviceUrls = await this.getServiceUrls(k8sCustom, config)
config.serviceUrls = serviceUrls

const istioIngressIp = await this.getIstioIngressIp(k8sCore)
config.istioIngressIp = istioIngressIp

this.state = config
await this.save()
return this.state
}

// "private" methods
async getIstioIngressIp(k8s) {
try {
const res = await k8s.readNamespacedService('istio-ingressgateway', 'istio-system')
if (res.body && res.body.status.loadBalancer && res.body.status.loadBalancer.ingress) {
return res.body.status.loadBalancer.ingress[0].ip
}
} catch (_err) {
// ignore istio errors to leverage usage of kourier
}
}

async getServiceUrl(k8s, config) {
let url
do {
Expand All @@ -71,30 +102,27 @@ class KnativeServing extends Component {
return url
}

getKubernetesClient(type) {
const { endpoint, port } = this.credentials.kubernetes
const token = this.credentials.kubernetes.serviceAccountToken
const skipTLSVerify = this.credentials.kubernetes.skipTlsVerify == 'true'
const kc = new kubernetes.KubeConfig()
kc.loadFromOptions({
clusters: [
{
name: 'cluster',
skipTLSVerify,
server: `${endpoint}:${port}`
}
],
users: [{ name: 'user', token }],
contexts: [
{
name: 'context',
user: 'user',
cluster: 'cluster'
}
],
currentContext: 'context'
})
return kc.makeApiClient(type)
async getServiceUrls(k8s, config) {
let urls = new Map()
do {
const services = await this.listServices(k8s, config)
if (services.response.statusCode == 200 && services.body.items) {
services.body.items.forEach( s => {
const serviceName = s.metadata.name
const serviceUrl = s.status.url
urls.set(serviceName, serviceUrl)
})
}
await new Promise((resolve) => setTimeout(() => resolve(), 2000))
} while (!urls)
return urls
}

getKubernetesClient(configPath, type) {
let kc = new kubernetes.KubeConfig()
kc.loadFromFile(configPath)
kc = kc.makeApiClient(type)
return kc
}

getManifest(svc) {
Expand All @@ -109,6 +137,14 @@ class KnativeServing extends Component {
if (svc.pullPolicy) {
imageConfig.imagePullPolicy = svc.pullPolicy
}

const annotations = {}
if (svc.autoscaler) {
for (const key in svc.autoscaler) {
const value = (typeof svc.autoscaler[key] == 'number') ? svc.autoscaler[key].toString() : svc.autoscaler[key]
annotations[`autoscaling.knative.dev/${key}`] = value
}
}
return {
apiVersion: `${svc.knativeGroup}/${svc.knativeVersion}`,
kind: 'Service',
Expand All @@ -118,6 +154,9 @@ class KnativeServing extends Component {
},
spec: {
template: {
metadata: {
annotations
},
spec: {
containers: [
imageConfig
Expand Down