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

Commit 08bde69

Browse files
author
Andres
committed
Move ingress functions to its own helper. Fix info command
1 parent b1c1835 commit 08bde69

File tree

7 files changed

+191
-154
lines changed

7 files changed

+191
-154
lines changed

examples/http-custom-path/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ $ curl 192.168.99.100.nip.io/hello
4747
hello world
4848
```
4949

50-
## GCE and Firewall limitation
50+
## GKE and Firewall limitation
5151

5252
For some providers like Google you may need to add a firewall rule for allowing the traffic for the port 80 and 443 so you can connect to the IP the ingress controller provides.
5353

examples/todo-app/backend/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Serverless: Function create successfully deployed
2828
Serverless: Function read-one successfully deployed
2929
```
3030

31-
# Running the Backend in GCE
31+
# Running the Backend in GKE
3232

3333
In case your cluster is running on GCE you need to perform an additional step. If you check the Ingress rules that has been created:
3434
```

lib/deploy.js

Lines changed: 5 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ const _ = require('lodash');
2020
const BbPromise = require('bluebird');
2121
const Api = require('kubernetes-client');
2222
const helpers = require('./helpers');
23+
const ingressHelper = require('./ingress');
2324
const moment = require('moment');
24-
const url = require('url');
2525

2626
function getFunctionDescription(
2727
funcName,
@@ -247,97 +247,6 @@ function redeployFunctionAndWait(body, thirdPartyResources, options) {
247247
});
248248
}
249249

250-
function getEvents(description) {
251-
return !_.isEmpty(description.events) ?
252-
description.events :
253-
[{ type: 'http', path: '/' }];
254-
}
255-
256-
function addIngressRuleIfNecessary(functions, options) {
257-
const opts = _.defaults({}, options, {
258-
verbose: false,
259-
log: console.log,
260-
namespace: 'default',
261-
hostname: null,
262-
});
263-
const config = helpers.loadKubeConfig();
264-
const extensions = new Api.Extensions(helpers.getConnectionOptions(
265-
config, { namespace: options.namespace })
266-
);
267-
const defaultHostname = `${url.parse(helpers.getKubernetesAPIURL(config)).hostname}.nip.io`;
268-
const rules = [];
269-
_.each(functions, (description) => {
270-
const events = getEvents(description);
271-
_.each(events, event => {
272-
if (event.type === 'http') {
273-
const fpath = event.path || '/';
274-
if (event.path !== '/' || !_.isEmpty(event.hostname)) {
275-
const hostname = event.hostname || opts.hostname || defaultHostname;
276-
const absolutePath = _.startsWith(fpath, '/') ?
277-
fpath :
278-
`/${fpath}`;
279-
const previousRule = _.findIndex(rules, r => r.host === hostname);
280-
if (previousRule >= 0) {
281-
rules[previousRule].http.paths.push({
282-
path: absolutePath,
283-
backend: { serviceName: description.id, servicePort: 8080 },
284-
});
285-
} else {
286-
rules.push({
287-
host: hostname,
288-
http: {
289-
paths: [{
290-
path: absolutePath,
291-
backend: { serviceName: description.id, servicePort: 8080 },
292-
}],
293-
},
294-
});
295-
}
296-
}
297-
}
298-
});
299-
});
300-
return new BbPromise((resolve, reject) => {
301-
if (!_.isEmpty(rules)) {
302-
// Found a path to deploy the function
303-
const labels = {};
304-
_.each(functions, f => {
305-
labels[f.id] = '1';
306-
});
307-
const ingressDef = {
308-
kind: 'Ingress',
309-
metadata: {
310-
name: `ingress-${moment.now()}`,
311-
labels,
312-
annotations: {
313-
'kubernetes.io/ingress.class': 'nginx',
314-
'ingress.kubernetes.io/rewrite-target': '/',
315-
},
316-
},
317-
spec: { rules },
318-
};
319-
extensions.ns.ingress.post({ body: ingressDef }, (err) => {
320-
if (err) {
321-
reject(
322-
'Unable to deploy the ingress rule. ' +
323-
`Received: ${err.message}`
324-
);
325-
} else {
326-
if (opts.verbose) {
327-
opts.log('Deployed Ingress rule');
328-
}
329-
resolve();
330-
}
331-
});
332-
} else {
333-
if (opts.verbose) {
334-
opts.log('Skipping ingress rule generation');
335-
}
336-
resolve();
337-
}
338-
});
339-
}
340-
341250
function deploy(functions, runtime, options) {
342251
const opts = _.defaults({}, options, {
343252
hostname: null,
@@ -359,7 +268,9 @@ function deploy(functions, runtime, options) {
359268
);
360269
const thirdPartyResources = new Api.ThirdPartyResources(connectionOptions);
361270
thirdPartyResources.addResource('functions');
362-
const events = getEvents(description);
271+
const events = !_.isEmpty(description.events) ?
272+
description.events :
273+
[{ type: 'http', path: '/' }];
363274
_.each(events, event => {
364275
const funcs = getFunctionDescription(
365276
description.id,
@@ -423,7 +334,7 @@ function deploy(functions, runtime, options) {
423334
// don't try to add an ingress rule
424335
p = new BbPromise((r) => r());
425336
} else {
426-
p = addIngressRuleIfNecessary(functions, {
337+
p = ingressHelper.addIngressRuleIfNecessary(functions, {
427338
verbose: opts.verbose,
428339
log: opts.log,
429340
hostname: opts.hostname,

lib/get-info.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ const _ = require('lodash');
2020
const Api = require('kubernetes-client');
2121
const BbPromise = require('bluebird');
2222
const chalk = require('chalk');
23-
const helpers = require('../lib/helpers');
23+
const helpers = require('./helpers');
24+
const ingressHelper = require('./ingress');
2425

2526
function toMultipleWords(word) {
2627
return word.replace(/([A-Z])/, ' $1').replace(/^./, (l) => l.toUpperCase());
@@ -118,12 +119,16 @@ function info(functions, options) {
118119
opts.log(`Not found any information about the function "${f}"`);
119120
} else {
120121
const fIngress = _.find(ingressInfo.items, item => (
121-
item.metadata.labels && item.metadata.labels.function === f
122+
item.metadata.labels &&
123+
_.isEqual(item.metadata.labels, ingressHelper.getIngressRuleLabels(functions))
122124
));
123125
let url = null;
126+
const rule = _.find(fIngress.spec.rules,
127+
r => _.some(r.http.paths, p => p.backend.serviceName === f)
128+
);
129+
const path = _.find(rule.http.paths, p => p.backend.serviceName === f).path;
124130
if (fIngress) {
125-
url = `${fIngress.spec.rules[0].host || 'API_URL'}` +
126-
`${fIngress.spec.rules[0].http.paths[0].path}`;
131+
url = `${rule.host || 'API_URL'}${path}`;
127132
}
128133
const service = {
129134
name: functionService.metadata.name,

lib/ingress.js

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
/*
2+
Copyright 2017 Bitnami.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
'use strict';
18+
19+
const _ = require('lodash');
20+
const BbPromise = require('bluebird');
21+
const Api = require('kubernetes-client');
22+
const helpers = require('./helpers');
23+
const moment = require('moment');
24+
const url = require('url');
25+
26+
function getIngressRuleLabels(functions) {
27+
const labels = {};
28+
_.each(functions, (desc, f) => {
29+
labels[desc.id || f] = '1';
30+
});
31+
return labels;
32+
}
33+
34+
function addIngressRuleIfNecessary(functions, options) {
35+
const opts = _.defaults({}, options, {
36+
verbose: false,
37+
log: console.log,
38+
namespace: 'default',
39+
hostname: null,
40+
});
41+
const config = helpers.loadKubeConfig();
42+
const extensions = new Api.Extensions(helpers.getConnectionOptions(
43+
config, { namespace: options.namespace })
44+
);
45+
const defaultHostname = `${url.parse(helpers.getKubernetesAPIURL(config)).hostname}.nip.io`;
46+
const rules = [];
47+
_.each(functions, (description) => {
48+
_.each(description.events, event => {
49+
if (event.type === 'http') {
50+
const fpath = event.path || '/';
51+
if (event.path !== '/' || !_.isEmpty(event.hostname)) {
52+
const hostname = event.hostname || opts.hostname || defaultHostname;
53+
const absolutePath = _.startsWith(fpath, '/') ?
54+
fpath :
55+
`/${fpath}`;
56+
const previousRule = _.findIndex(rules, r => r.host === hostname);
57+
if (previousRule >= 0) {
58+
rules[previousRule].http.paths.push({
59+
path: absolutePath,
60+
backend: { serviceName: description.id, servicePort: 8080 },
61+
});
62+
} else {
63+
rules.push({
64+
host: hostname,
65+
http: {
66+
paths: [{
67+
path: absolutePath,
68+
backend: { serviceName: description.id, servicePort: 8080 },
69+
}],
70+
},
71+
});
72+
}
73+
}
74+
}
75+
});
76+
});
77+
return new BbPromise((resolve, reject) => {
78+
if (!_.isEmpty(rules)) {
79+
// Found a path to deploy the function
80+
const labels = getIngressRuleLabels(functions);
81+
const ingressDef = {
82+
kind: 'Ingress',
83+
metadata: {
84+
name: `ingress-${moment.now()}`,
85+
labels,
86+
annotations: {
87+
'kubernetes.io/ingress.class': 'nginx',
88+
'ingress.kubernetes.io/rewrite-target': '/',
89+
},
90+
},
91+
spec: { rules },
92+
};
93+
extensions.ns.ingress.post({ body: ingressDef }, (err) => {
94+
if (err) {
95+
reject(
96+
'Unable to deploy the ingress rule. ' +
97+
`Received: ${err.message}`
98+
);
99+
} else {
100+
if (opts.verbose) {
101+
opts.log('Deployed Ingress rule');
102+
}
103+
resolve();
104+
}
105+
});
106+
} else {
107+
if (opts.verbose) {
108+
opts.log('Skipping ingress rule generation');
109+
}
110+
resolve();
111+
}
112+
});
113+
}
114+
115+
function removeIngressRuleIfNecessary(functions, namespace, options) {
116+
const opts = _.defaults({}, options, {
117+
verbose: false,
118+
log: console.log,
119+
});
120+
const extensions = new Api.Extensions(helpers.getConnectionOptions(helpers.loadKubeConfig(), {
121+
namespace,
122+
}));
123+
return new BbPromise((resolve, reject) => {
124+
extensions.ns.ingress.get((err, ingressInfo) => {
125+
const expectedLabels = getIngressRuleLabels(functions);
126+
const ingressRule = _.find(ingressInfo.items, item => (
127+
item.metadata.labels && _.isEqual(item.metadata.labels, expectedLabels)
128+
));
129+
if (!_.isEmpty(ingressRule)) {
130+
extensions.ns.ingress.delete(ingressRule, (ingErr) => {
131+
if (ingErr) {
132+
reject(
133+
`Unable to remove the ingress rule ${ingressRule}. Received:\n` +
134+
` Code: ${ingErr.code}\n` +
135+
` Message: ${ingErr.message}`
136+
);
137+
} else {
138+
if (opts.verbose) {
139+
opts.log(`Removed Ingress rule ${ingressRule.metadata.name}`);
140+
}
141+
resolve();
142+
}
143+
});
144+
} else {
145+
if (opts.verbose) {
146+
opts.log('Skipping ingress rule clean up');
147+
}
148+
resolve();
149+
}
150+
});
151+
});
152+
}
153+
154+
module.exports = {
155+
getIngressRuleLabels,
156+
addIngressRuleIfNecessary,
157+
removeIngressRuleIfNecessary,
158+
};

lib/remove.js

Lines changed: 2 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -20,48 +20,7 @@ const _ = require('lodash');
2020
const Api = require('kubernetes-client');
2121
const BbPromise = require('bluebird');
2222
const helpers = require('../lib/helpers');
23-
24-
function removeIngressRuleIfNecessary(functions, namespace, options) {
25-
const opts = _.defaults({}, options, {
26-
verbose: false,
27-
log: console.log,
28-
});
29-
const extensions = new Api.Extensions(helpers.getConnectionOptions(helpers.loadKubeConfig(), {
30-
namespace,
31-
}));
32-
return new BbPromise((resolve, reject) => {
33-
extensions.ns.ingress.get((err, ingressInfo) => {
34-
const expectedLabels = {};
35-
_.each(functions, f => {
36-
expectedLabels[f.id] = '1';
37-
});
38-
const ingressRule = _.find(ingressInfo.items, item => (
39-
item.metadata.labels && _.isEqual(item.metadata.labels, expectedLabels)
40-
));
41-
if (!_.isEmpty(ingressRule)) {
42-
extensions.ns.ingress.delete(ingressRule, (ingErr) => {
43-
if (ingErr) {
44-
reject(
45-
`Unable to remove the ingress rule ${ingressRule}. Received:\n` +
46-
` Code: ${ingErr.code}\n` +
47-
` Message: ${ingErr.message}`
48-
);
49-
} else {
50-
if (opts.verbose) {
51-
opts.log(`Removed Ingress rule ${ingressRule.metadata.name}`);
52-
}
53-
resolve();
54-
}
55-
});
56-
} else {
57-
if (opts.verbose) {
58-
opts.log('Skipping ingress rule clean up');
59-
}
60-
resolve();
61-
}
62-
});
63-
});
64-
}
23+
const ingressHelper = require('./ingress');
6524

6625
function removeFunction(functions, options) {
6726
const opts = _.defaults({}, options, {
@@ -97,7 +56,7 @@ function removeFunction(functions, options) {
9756
} else {
9857
counter++;
9958
if (counter === _.keys(functions).length) {
100-
removeIngressRuleIfNecessary(
59+
ingressHelper.removeIngressRuleIfNecessary(
10160
functions,
10261
connectionOptions.namespace,
10362
{ verbose: opts.verbose, log: opts.log }

0 commit comments

Comments
 (0)