Skip to content

Commit 270bb7c

Browse files
committed
Merge pull request #1 from AcalephStorage/feature/gh-login
Minimal Dashboard (w/ Github login)
2 parents 6de9981 + b530560 commit 270bb7c

File tree

190 files changed

+2694
-10
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

190 files changed

+2694
-10
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@
1515
/libpeerconnection.log
1616
npm-debug.log
1717
testem.log
18+
/.env

.jshintrc

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
"predef": [
33
"document",
44
"window",
5-
"-Promise"
5+
"-Promise",
6+
"moment"
67
],
78
"browser": true,
89
"boss": true,

.watchmanconfig

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"ignore_dirs": ["tmp"]
2+
"ignore_dirs": ["tmp", "dist"]
33
}

Caddyfile

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
0.0.0.0:5000 {
2+
gzip
3+
root /home/apps/kontinuous-ui/dist
4+
rewrite / {
5+
regexp .*
6+
ext /
7+
to /index.html
8+
}
9+
log stdout
10+
}

Dockerfile

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
FROM node:0.12.7
2+
3+
# Install ember, bower, forego, and caddy
4+
RUN npm install -g [email protected] && \
5+
npm install -g [email protected] && \
6+
wget https://bin.equinox.io/c/ekMN3bCZFUn/forego-stable-linux-amd64.tgz -O /tmp/forego.tar.gz && \
7+
tar xvz -C /usr/local/bin -f /tmp/forego.tar.gz && \
8+
rm /tmp/forego.tar.gz && \
9+
chmod 0744 /usr/local/bin/forego && \
10+
wget https://github.com/mholt/caddy/releases/download/v0.7.6/caddy_linux_amd64.tar.gz -O /tmp/caddy.tar.gz && \
11+
tar xvz -C /usr/local/bin -f /tmp/caddy.tar.gz && \
12+
rm /tmp/caddy.tar.gz
13+
14+
ADD . /home/apps/kontinuous-ui
15+
WORKDIR /home/apps/kontinuous-ui
16+
17+
RUN npm install && \
18+
bower install --allow-root
19+
ENV KUBERNETES_API_URL kubernetes.default
20+
ENV KUBERNETES_API_TOKEN_PATH /run/secrets/kubernetes.io/serviceaccount/token
21+
ENV KUBERNETES_API_TOKEN token
22+
23+
CMD ["/usr/local/bin/forego", "start", "-f", "config/Procfile", "-p", "5000"]

app/adapters/application.js

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import DS from 'ember-data';
2+
import DataAdapterMixin from 'ember-simple-auth/mixins/data-adapter-mixin';
3+
import Configuration from '../config/environment';
4+
import Ember from 'ember';
5+
6+
export default DS.RESTAdapter.extend(DataAdapterMixin, {
7+
8+
authorizer: 'authorizer:kontinuous',
9+
defaultSerializer: 'kontinuous',
10+
host: Configuration.APP.kontinuousAPI.host,
11+
namespace: `api/${Configuration.APP.kontinuousAPI.version}`,
12+
13+
handleResponse(status, headers, payload) {
14+
if (payload && payload.hasOwnProperty('Code') && (payload.Code >= 400 && payload.Code <= 500)) {
15+
return new DS.AdapterError(payload);
16+
}
17+
return this._super(...arguments);
18+
},
19+
20+
21+
queryRecord(store, type, query) {
22+
var q = Ember.copy(query),
23+
url = this.buildURL(type.modelName, null, null, "queryRecord", q);
24+
25+
if (this.sortQueryParams) {
26+
q = this.sortQueryParams(q);
27+
}
28+
29+
return this.ajax(url, "GET", { data: q });
30+
},
31+
32+
query(store, type, query) {
33+
var q = Ember.copy(query),
34+
url = this.buildURL(type.modelName, null, null, "query", q);
35+
36+
if (this.sortQueryParams) {
37+
q = this.sortQueryParams(q);
38+
}
39+
40+
return this.ajax(url, "GET", { data: q });
41+
},
42+
43+
urlForQueryRecord: function(query, modelName) {
44+
var urlParts = this._buildURL(modelName).split('/');
45+
46+
if (Ember.isPresent(query.owner) && Ember.isPresent(query.repo)) {
47+
urlParts.push(query.owner, query.repo);
48+
delete query.owner;
49+
delete query.repo;
50+
}
51+
52+
return urlParts.join('/');
53+
},
54+
55+
});

app/adapters/build.js

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import ApplicationAdapter from './application';
2+
import DS from 'ember-data';
3+
import Ember from 'ember';
4+
5+
export default ApplicationAdapter.extend({
6+
7+
createRecord: function (store, type, snapshot) {
8+
var pipeline = snapshot.record.get('pipeline');
9+
if (Ember.isNone(pipeline)) {
10+
return new DS.AdapterError();
11+
}
12+
var data = {},
13+
url = this.buildURL(type.modelName, null, snapshot, 'createRecord');
14+
15+
var serializer = store.serializerFor(type.modelName);
16+
serializer.serializeIntoHash(data, type, snapshot, { includeId: false });
17+
18+
delete data.stages;
19+
20+
return this.ajax(url, 'POST', {
21+
headers: {'X-Custom-Event': 'dashboard'},
22+
data: data,
23+
});
24+
},
25+
26+
urlForCreateRecord(modelName, snapshot) {
27+
var urlParts = this._buildURL(modelName).split('/');
28+
urlParts.removeObject(this.pathForType(modelName));
29+
30+
var owner = snapshot.record.get('pipeline.owner'),
31+
repo = snapshot.record.get('pipeline.repo');
32+
33+
if (Ember.isPresent(owner) && Ember.isPresent(repo)) {
34+
urlParts.push('pipelines', owner, repo);
35+
}
36+
37+
urlParts.push(this.pathForType(modelName));
38+
return urlParts.join('/');
39+
}
40+
});

app/adapters/k8s-log.js

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import Ember from 'ember';
2+
import K8sAdapter from './k8s';
3+
4+
export default K8sAdapter.extend({
5+
6+
defaultSerializer: 'k8s-log',
7+
8+
pathForType() {
9+
return 'log';
10+
},
11+
12+
queryRecord(store, type, _data) {
13+
let data = Ember.copy(_data);
14+
15+
var urlParts = this.buildURL(type.modelName, null, null, "query", data).split('/');
16+
urlParts.removeObject(this.pathForType());
17+
18+
if (Ember.isPresent(data.namespace) && Ember.isPresent(data.podName)) {
19+
urlParts.push('namespaces', data.namespace);
20+
urlParts.push('pods', data.podName);
21+
delete data.namespace;
22+
delete data.podName;
23+
}
24+
25+
urlParts.push(this.pathForType());
26+
let url = urlParts.join('/');
27+
return this.ajax(url, "GET", { data: data });
28+
},
29+
30+
ajaxOptions() {
31+
var hash = this._super.apply(this, arguments);
32+
hash.dataType = "text";
33+
return hash;
34+
}
35+
36+
});

app/adapters/k8s.js

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import RESTAdapter from 'ember-data/adapters/rest';
2+
import DataAdapterMixin from 'ember-simple-auth/mixins/data-adapter-mixin';
3+
import Configuration from '../config/environment';
4+
import Ember from 'ember';
5+
import DS from 'ember-data';
6+
7+
export default RESTAdapter.extend(DataAdapterMixin, {
8+
9+
authorizer: 'authorizer:k8s',
10+
defaultSerializer: 'k8s',
11+
host: Configuration.APP.k8sAPI.host,
12+
namespace: `api/${Configuration.APP.k8sAPI.version}`,
13+
14+
pathForType(modelName) {
15+
var trimmed = modelName.replace(/^k8s-+/, '');
16+
return trimmed.pluralize();
17+
},
18+
19+
_setNamespace(type, snapshot) {
20+
var namespace = this.get('namespace');
21+
22+
if (type.modelName !== 'namespace') {
23+
this.set('namespace', namespace + '/namespaces/' + this.serialize(snapshot).metadata.namespace);
24+
}
25+
26+
return namespace;
27+
},
28+
29+
queryRecord(store, type, _data) {
30+
let data = Ember.copy(_data);
31+
let path = this.pathForType(type.modelName);
32+
let urlParts = this.buildURL(type.modelName, null, null, path, data).split('/');
33+
urlParts.removeObject(path);
34+
35+
if (Ember.isPresent(data.namespace) && Ember.isPresent(data.name)) {
36+
urlParts.push('namespaces', data.namespace);
37+
urlParts.push(path, data.name);
38+
delete data.namespace;
39+
delete data.name;
40+
}
41+
42+
let url = urlParts.join('/');
43+
return this.ajax(url, "GET", { data: data });
44+
},
45+
46+
handleResponse(status, headers, payload) {
47+
if (payload.hasOwnProperty('kind') && payload.kind === 'Status' && (payload.code >= 400 && payload.code <= 500)) {
48+
return new DS.AdapterError(payload);
49+
}
50+
return this._super(...arguments);
51+
}
52+
});

app/adapters/pod.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import K8sAdapter from './k8s';
2+
3+
export default K8sAdapter.extend();

app/adapters/stage.js

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import ApplicationAdapter from './application';
2+
import Ember from 'ember';
3+
4+
export default ApplicationAdapter.extend({
5+
6+
_getLogs(query) {
7+
let q = Ember.copy(query);
8+
let urlParts = this.urlForQueryRecord(q).split('/');
9+
urlParts.push('logs');
10+
let url = urlParts.join('/');
11+
return this.ajax(url, 'GET', {data: q});
12+
},
13+
14+
urlForQueryRecord: function(query, modelName) {
15+
var urlParts = this._buildURL(modelName).split('/');
16+
17+
if (Ember.isPresent(query.owner) && Ember.isPresent(query.repo) && Ember.isPresent(query.buildNumber) && Ember.isPresent(query.stageIndex)) {
18+
urlParts.push('pipelines', query.owner, query.repo, 'builds', query.buildNumber, 'stages', query.stageIndex);
19+
delete query.owner;
20+
delete query.repo;
21+
delete query.buildNumber;
22+
delete query.stageIndex;
23+
}
24+
return urlParts.join('/');
25+
},
26+
});

app/authenticators/k8s.js

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import Ember from 'ember';
2+
import BaseAuthenticator from 'ember-simple-auth/authenticators/base';
3+
import config from '../config/environment';
4+
5+
export default BaseAuthenticator.extend({
6+
7+
tokenEndpoint: config.APP.k8sAPI.host + '/sessions/create',
8+
9+
restore(data) {
10+
return new Ember.RSVP.Promise((resolve, reject) => {
11+
if (Ember.isEmpty(data.token)) {
12+
resolve(data);
13+
} else {
14+
reject();
15+
}
16+
});
17+
},
18+
19+
authenticate(options) {
20+
return new Ember.RSVP.Promise((resolve, reject) => {
21+
Ember.$.ajax({
22+
url: this.tokenEndpoint,
23+
type: 'POST',
24+
data: JSON.stringify({
25+
username: options.username,
26+
password: options.password
27+
}),
28+
})
29+
.then((response) => {
30+
Ember.run(() => {
31+
resolve({token: response.id_token});
32+
});
33+
}, (xhr) => {
34+
Ember.run(() => {
35+
reject(xhr.responseText);
36+
});
37+
});
38+
});
39+
},
40+
41+
invalidate() {
42+
return Ember.RSVP.resolve();
43+
}
44+
});

app/authenticators/kontinuous.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import Ember from 'ember';
2+
import ToriiAuthenticator from 'ember-simple-auth/authenticators/torii';
3+
4+
export default ToriiAuthenticator.extend({
5+
torii: Ember.inject.service()
6+
});

app/authorizers/k8s.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import Ember from 'ember';
2+
import BaseAuthorizer from 'ember-simple-auth/authorizers/base';
3+
4+
const {isEmpty} = Ember;
5+
6+
export default BaseAuthorizer.extend({
7+
8+
authorize(sessionData, block) {
9+
const token = sessionData.jwt;
10+
if (!isEmpty(token)) {
11+
block('Authorization', `Bearer ${token}`);
12+
}
13+
}
14+
15+
});

app/authorizers/kontinuous.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import Ember from 'ember';
2+
import BaseAuthorizer from 'ember-simple-auth/authorizers/base';
3+
4+
const {isEmpty} = Ember;
5+
6+
export default BaseAuthorizer.extend({
7+
8+
authorize(sessionData, block) {
9+
const token = sessionData.jwt;
10+
if (!isEmpty(token)) {
11+
block('Authorization', `Bearer ${token}`);
12+
}
13+
}
14+
15+
});

0 commit comments

Comments
 (0)