Skip to content
This repository was archived by the owner on Dec 9, 2024. It is now read-only.

Commit 2253ce2

Browse files
authored
Use of the kubeless http trigger instead of a custom created ingress (#206)
1 parent 06ed262 commit 2253ce2

9 files changed

+178
-357
lines changed

lib/deploy.js

+75-33
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ const BbPromise = require('bluebird');
2121
const Api = require('kubernetes-client');
2222
const CRD = require('./crd');
2323
const helpers = require('./helpers');
24-
const ingressHelper = require('./ingress');
2524
const moment = require('moment');
25+
const url = require('url');
2626

2727
/** Supported message queue types */
2828
const MQTypes = Object.freeze({ kafka: 'Kafka', nats: 'NATS' });
@@ -434,6 +434,49 @@ function deployScheduleTrigger(name, namespace, schedule, options) {
434434
});
435435
}
436436

437+
function deployHttpTrigger(name, namespace, path, options) {
438+
if (options.ingress.enableTlsAcme && options.ingress.tlsSecretName) {
439+
throw new Error('Cannot specify both enableTlsAcme and tlsSecretName');
440+
}
441+
// fix for issue https://github.com/kubeless/kubeless/issues/1124
442+
const baseAnnotations = {
443+
'kubernetes.io/ingress.class': options.ingress.class || 'nginx',
444+
};
445+
// end fix
446+
const trigger = {
447+
apiVersion: 'kubeless.io/v1beta1',
448+
kind: 'HTTPTrigger',
449+
metadata: {
450+
name,
451+
namespace,
452+
labels: {
453+
'created-by': 'kubeless',
454+
},
455+
annotations: Object.assign(baseAnnotations, options.ingress.additionalAnnotations),
456+
},
457+
spec: {
458+
'basic-auth-secret': options.ingress.basicAuthSecretName || '',
459+
'cors-enable': options.ingress.cors || false,
460+
'function-name': name,
461+
gateway: options.ingress.class || 'nginx', // not working: https://github.com/kubeless/kubeless/issues/1124
462+
'host-name': options.hostname,
463+
path: path.replace(/^\//, ''),
464+
tls: options.ingress.enableTlsAcme || false,
465+
'tls-secret': options.ingress.tlsSecretName || '',
466+
},
467+
};
468+
const httpTriggerApi = new CRD('apis/kubeless.io', 'v1beta1', namespace, 'httptriggers');
469+
options.log(`Creating http trigger for: ${trigger.metadata.name}`);
470+
return httpTriggerApi.getItem(trigger.metadata.name)
471+
.then((res) => {
472+
if (res.code === 404) {
473+
return httpTriggerApi.post({ body: trigger });
474+
}
475+
options.log('Updating existing http trigger');
476+
return httpTriggerApi.put(trigger.metadata.name, { body: trigger });
477+
});
478+
}
479+
437480
function deployFunction(f, namespace, runtime, contentType, options) {
438481
const functionsApi = new CRD('apis/kubeless.io', 'v1beta1', namespace, 'functions');
439482
let environment = options.environment ? parseEnv(options.environment) : null;
@@ -527,10 +570,27 @@ function handleMQTDeployment(trigger, name, namespace, options) {
527570
}
528571

529572
function deployTrigger(event, funcName, namespace, service, options) {
530-
let triggerPromise = new BbPromise((r) => r());
573+
let triggerPromise;
574+
let config;
575+
let defaultHostname;
531576
switch (event.type) {
532577
case 'http':
533-
// TODO: Rely on Kubeless httptrigger object when it support paths
578+
if (_.isEmpty(event.path)) {
579+
throw new Error('You should specify a path for the trigger event');
580+
}
581+
config = helpers.loadKubeConfig();
582+
// eslint-disable-next-line max-len
583+
defaultHostname = `${url.parse(helpers.getKubernetesAPIURL(config)).hostname}.${options.defaultDNSResolution || 'nip.io'}`;
584+
triggerPromise = deployHttpTrigger(
585+
funcName,
586+
namespace,
587+
event.path,
588+
{
589+
log: options.log,
590+
ingress: options.ingress || {},
591+
hostname: event.hostname || options.hostname || defaultHostname,
592+
}
593+
);
534594
break;
535595
case 'trigger':
536596
if (_.isEmpty(event.trigger)) {
@@ -586,38 +646,20 @@ function deploy(functions, runtime, service, options) {
586646
if (res.code && res.code !== 200) {
587647
errors.push(res.message);
588648
}
589-
counter++;
590-
helpers.checkFinished(counter, elements, errors, resolve, reject, {
591-
onSuccess: () => ingressHelper.addIngressRuleIfNecessary(service, functions, {
592-
verbose: options.verbose,
593-
log: options.log,
594-
hostname: options.hostname,
595-
defaultDNSResolution: options.defaultDNSResolution,
596-
ingress: options.ingress,
597-
namespace: ns,
598-
}),
649+
_.each(description.events, event => {
650+
deployTrigger(event, description.id, ns, service, opts)
651+
.catch(triggerErr => errors.push(triggerErr))
652+
.then((tr) => {
653+
if (tr && tr.code && tr.code !== 200) {
654+
errors.push(tr.message);
655+
}
656+
counter++;
657+
helpers.checkFinished(counter, elements, errors, resolve, reject);
658+
});
599659
});
660+
counter++;
661+
helpers.checkFinished(counter, elements, errors, resolve, reject);
600662
});
601-
_.each(description.events, event => {
602-
deployTrigger(event, description.id, ns, service, opts)
603-
.catch(triggerErr => errors.push(triggerErr))
604-
.then((res) => {
605-
if (res && res.code && res.code !== 200) {
606-
errors.push(res.message);
607-
}
608-
counter++;
609-
helpers.checkFinished(counter, elements, errors, resolve, reject, {
610-
onSuccess: () => ingressHelper.addIngressRuleIfNecessary(service, functions, {
611-
verbose: options.verbose,
612-
log: options.log,
613-
hostname: options.hostname,
614-
defaultDNSResolution: options.defaultDNSResolution,
615-
ingress: options.ingress,
616-
namespace: ns,
617-
}),
618-
});
619-
});
620-
});
621663
} else {
622664
counter++;
623665
opts.log(

lib/get-info.js

+18-10
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,24 @@ function info(functions, service, options) {
9393
});
9494
const core = new Api.Core(connectionOptions);
9595
const functionsApi = new CRD('apis/kubeless.io', 'v1beta1', namespace, 'functions');
96-
const extensions = new Api.Extensions(connectionOptions);
96+
const httpTriggerApi = new CRD('apis/kubeless.io', 'v1beta1', namespace, 'httptriggers');
9797
core.ns.services.get((err, servicesInfo) => {
9898
if (err) reject(new Error(err));
9999
functionsApi.getItem(f).catch((ferr) => reject(ferr)).then(fDesc => {
100-
extensions.ns.ingress(service).get((ierr, fIngress) => {
101-
if (ierr && !ierr.message.match(/not found/)) {
102-
reject(new Error(ierr));
100+
let tErr;
101+
let httpTriggerDesc;
102+
httpTriggerApi.getItem(f).catch((ex) => {
103+
tErr = ex;
104+
}).then(res => {
105+
if (res && res.kind === 'Status') {
106+
tErr = res;
107+
} else {
108+
httpTriggerDesc = res;
109+
}
110+
}).finally(() => {
111+
// eslint-disable-next-line max-len
112+
if (tErr && (tErr.code && tErr.code !== 404)) {
113+
reject(new Error(tErr));
103114
}
104115
const functionService = _.find(
105116
servicesInfo.items,
@@ -112,12 +123,9 @@ function info(functions, service, options) {
112123
opts.log(`Not found any information about the function "${f}"`);
113124
} else {
114125
let url = null;
115-
if (fIngress) {
116-
const rule = _.find(fIngress.spec.rules,
117-
r => _.some(r.http.paths, p => p.backend.serviceName === f)
118-
);
119-
const path = _.find(rule.http.paths, p => p.backend.serviceName === f).path;
120-
url = `${rule.host || 'API_URL'}${path}`;
126+
if (httpTriggerDesc) {
127+
// eslint-disable-next-line max-len
128+
url = `${httpTriggerDesc.spec['host-name'] || 'API_URL'}/${httpTriggerDesc.spec.path}`;
121129
}
122130
const fService = {
123131
name: functionService.metadata.name,

lib/ingress.js

-169
This file was deleted.

0 commit comments

Comments
 (0)