Permalink
Browse files

Changes to the imagelayer ui application for use as a frontend in kub…

…ernetes

Presents the UI code as static resources as before
Links are changed for paths
   /registry -> proxied to an cluster service named imagelayers
   /badge    -> proxied to a cluster service named badger

manifests/imagelayers-all.yaml is a complete kubernetes specification
for all three replication controllers and services
  • Loading branch information...
1 parent b96951e commit 8544de6bd6d481e7abeac41ee394fcbec6181947 ntfrnzn committed Mar 14, 2016
Showing with 365 additions and 73 deletions.
  1. +3 −2 Dockerfile
  2. +25 −1 README.md
  3. +12 −10 app/scripts/controllers/badgedialog.js
  4. +1 −1 app/views/badgeDialog.html
  5. +147 −0 manifest/imagelayers-all.yaml
  6. +93 −11 nginx.conf
  7. +0 −1 package.json
  8. +84 −47 test/spec/controllers/badgedialog.js
View
@@ -1,7 +1,8 @@
-FROM centurylink/nginx:1.6.2
+FROM nginx:1.8.1
-MAINTAINER CenturyLink Labs <ctl-labs-futuretech@centurylink.com>
+MAINTAINER Nathan Franzen <nathan.franzen@ctl.io>
EXPOSE 9000
+EXPOSE 8080
ADD nginx.conf /etc/nginx/nginx.conf
ADD /dist /data/dist
View
@@ -13,8 +13,32 @@ ImageLayers uses Grunt. To install Grunt, you must first have [npm installed on
The last step is to install Compass. ImageLayers recommends using the latest version of Ruby.
`gem install compass`
-Next, make sure the [imagelayers API](https://github.com/CenturyLinkLabs/imagelayers/) is running.
+Next, make sure the [imagelayers API](https://github.com/CenturyLinkLabs/imagelayers/) is running.
Run `grunt` for building the UI and `grunt serve` for preview. The ImageLayers UI will automatically open in a browser window.
+### Deploying in Kubernetes
+
+The [ImageLayers API](https://github.com/CenturyLinkLabs/imagelayers/) is
+deployed in a Kubernetes cluster as a separate replication controller with
+associated service. The api service is not available from oputside the cluster,
+and is reached by proxying all requests through the same nginx server that hosts
+this application.
+
+To build the version of imagelayers ui that proxies these requests:
+```
+$ IMAGE_LAYERS_API="" grunt build --force
+$ docker build -t [repositoryname]/imagelayers-ui:[version] .
+```
+
+A prototype of the kubernetes manifest is found in the manifest subdirectory and
+can be deployed with kubectl. The api can be scaled independently of the frontend.
+```
+$ kubectl create -f manifest/imagelayers-all.yaml
+$ kubectl scale rc imagelayers --replicas=3
+```
+
+The imagelayer-ui is defined as type Loadbalancer, and a new external endpoint
+will be allocated upon deployment
+
## Testing
Running `grunt test` will run the unit tests with karma.
@@ -16,21 +16,24 @@
function BadgeDialogCtrl($scope, $sce) {
var nameChanged = function(current, previous) {
var newName = current.name,
- oldName = previous.name;
+ oldName = previous.name;
return (newName !== undefined &&
- newName !== oldName);
+ newName !== oldName);
};
var newImage = function() {
- return { name: '', tag: 'latest' };
+ return {
+ name: '',
+ tag: 'latest'
+ };
};
$scope.selectedImage = newImage();
$scope.imageList = function() {
var data = $scope.graph,
- list = [];
+ list = [];
angular.forEach(data, function(image) {
image.repo.label = image.repo.name + ':' + image.repo.tag;
@@ -66,23 +69,22 @@
$scope.asciiDocCopied = false;
}, true);
- $scope.badgeAsHtml = function () {
+ $scope.badgeAsHtml = function() {
if ($scope.selectedImage.selected !== true) {
return "";
}
return $sce.trustAsHtml("<a href='https://imagelayers.io/?images=" + $scope.selectedImage.name + ":" + $scope.selectedImage.tag + "' title='Get your own badge on imagelayers.io'>" +
- "<img src='https://badge.imagelayers.io/" + $scope.selectedImage.name + ":" + $scope.selectedImage.tag + ".svg'></a>");
+ "<img src='https://imagelayers.io/badge/" + $scope.selectedImage.name + ":" + $scope.selectedImage.tag + ".svg'></a>");
};
- $scope.badgeAsMarkdown = function () {
+ $scope.badgeAsMarkdown = function() {
if ($scope.selectedImage.selected !== true) {
return "";
}
- return "[![](https://badge.imagelayers.io/" + $scope.selectedImage.name + ":" + $scope.selectedImage.tag + ".svg)]" +
- "(https://imagelayers.io/?images=" + $scope.selectedImage.name + ":" + $scope.selectedImage.tag + " 'Get your own badge on imagelayers.io')";
- };
+ return "[![](https://imagelayers.io/badge/" + $scope.selectedImage.name + ":" + $scope.selectedImage.tag + ".svg)]" +
+ "(https://imagelayers.io/?images=" + $scope.selectedImage.name + ":" + $scope.selectedImage.tag + " 'Get your own badge on imagelayers.io')"; };
$scope.badgeAsAsciiDoc = function() {
if ($scope.selectedImage.selected !== true) {
@@ -29,7 +29,7 @@
<section ng-if="selectedImage.selected">
<div class="preview">
<label>Badge Preview</label>
- <img loading-src="https://badge.imagelayers.io/{{ selectedImage.name }}:{{ selectedImage.tag }}.svg">
+ <img loading-src="/badge/{{ selectedImage.name }}:{{ selectedImage.tag }}.svg">
</div>
<ul>
<li>
@@ -0,0 +1,147 @@
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ app: imagelayers
+ name: imagelayers
+ namespace: default
+spec:
+ ports:
+ - port: 80
+ protocol: TCP
+ targetPort: 8888
+ selector:
+ app: imagelayers
+ sessionAffinity: None
+ type: ClusterIP
+---
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ app: badger
+ name: badger
+ namespace: default
+spec:
+ ports:
+ - port: 80
+ protocol: TCP
+ targetPort: 3000
+ selector:
+ app: badger
+ sessionAffinity: None
+ type: ClusterIP
+---
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ app: imagelayers-web
+ name: imagelayers-web
+ namespace: default
+spec:
+ ports:
+ - port: 80
+ protocol: TCP
+ targetPort: 9000
+ nodePort: 30900
+ selector:
+ app: imagelayers-web
+ sessionAffinity: None
+ type: NodePort
+---
+apiVersion: v1
+kind: ReplicationController
+metadata:
+ labels:
+ app: imagelayers
+ name: imagelayers
+ namespace: default
+spec:
+ replicas: 1
+ selector:
+ app: imagelayers
+ template:
+ metadata:
+ creationTimestamp: null
+ labels:
+ app: imagelayers
+ name: imagelayers
+ spec:
+ containers:
+ - image: centurylink/imagelayers-api
+ imagePullPolicy: IfNotPresent
+ name: imagelayers
+ resources: {}
+ securityContext:
+ privileged: false
+ terminationMessagePath: /dev/termination-log
+ dnsPolicy: ClusterFirst
+ restartPolicy: Always
+ terminationGracePeriodSeconds: 30
+---
+apiVersion: v1
+kind: ReplicationController
+metadata:
+ labels:
+ app: imagelayers-web
+ version: kubernetes-v1.0
+ name: imagelayers-web
+ namespace: default
+spec:
+ replicas: 1
+ selector:
+ app: imagelayers-web
+ version: kubernetes-v1.0
+ template:
+ metadata:
+ creationTimestamp: null
+ labels:
+ app: imagelayers-web
+ version: kubernetes-v1.0
+ name: imagelayers-web
+ spec:
+ containers:
+ - image: ntfrnzn/imagelayers-ui:kubernetes-v1.0
+ imagePullPolicy: IfNotPresent
+ name: imagelayers-web
+ resources: {}
+ securityContext:
+ privileged: false
+ terminationMessagePath: /dev/termination-log
+ dnsPolicy: ClusterFirst
+ restartPolicy: Always
+ terminationGracePeriodSeconds: 30
+---
+apiVersion: v1
+kind: ReplicationController
+metadata:
+ labels:
+ app: badger
+ name: badger
+ namespace: default
+spec:
+ replicas: 1
+ selector:
+ app: badger
+ template:
+ metadata:
+ creationTimestamp: null
+ labels:
+ app: badger
+ name: badger
+ spec:
+ containers:
+ - image: centurylink/badger
+ imagePullPolicy: IfNotPresent
+ name: badger
+ resources: {}
+ env:
+ - name: MODE
+ value: production
+ securityContext:
+ privileged: false
+ terminationMessagePath: /dev/termination-log
+ dnsPolicy: ClusterFirst
+ restartPolicy: Always
+ terminationGracePeriodSeconds: 30
View
@@ -1,7 +1,7 @@
user nobody nogroup;
worker_processes 1;
-daemon off;
-error_log /dev/stderr info;
+
+error_log /dev/stderr warn;
events {
worker_connections 1024;
@@ -10,11 +10,31 @@ events {
http {
include mime.types;
- log_format main '$remote_addr - $remote_user [$time_local] "$request" '
- '$status $body_bytes_sent "$http_referer" '
- '"$http_user_agent" "$http_x_forwarded_for"';
+ log_format main '{'
+ '"body_bytes_sent":"$body_bytes_sent",'
+ '"host":"$host",'
+ '"hostname":"$hostname",'
+ '"http_forwarded":"$http_forwarded",'
+ '"http_referer":"$http_referer",'
+ '"http_user_agent":"$http_user_agent",'
+ '"http_x_forwarded_for":"$http_x_forwarded_for",'
+ '"query_string":"$query_string",'
+ '"remote_addr":"$remote_addr",'
+ '"remote_user":"$remote_user",'
+ '"request_method":"$request_method",'
+ '"request_time":"$request_time",'
+ '"request":"$request",'
+ '"scheme":"$scheme",'
+ '"server_port":"$server_port",'
+ '"status":"$status",'
+ '"time_iso8601":"$time_iso8601",'
+ '"upstream_addr":"$upstream_addr",'
+ '"upstream_response_time":"$upstream_response_time",'
+ '"upstream_status":"$upstream_status"'
+ '}';
access_log /dev/stdout main;
+ # error_log /dev/stdout debug;
sendfile on;
tcp_nopush on;
@@ -23,9 +43,50 @@ http {
gzip on;
+ upstream imagelayers-api {
+ server imagelayers;
+ }
+
+ upstream badger {
+ server badger;
+ }
+
+ ## health and status check
+ server {
+ listen 8080;
+
+ location /nginx_status {
+ stub_status on;
+ access_log off;
+ }
+ }
+
+ # used only by clients directly addressing this service
server {
listen 9000;
- server_name localhost;
+ server_name badge.imagelayers.io;
+
+ location / {
+ access_log /dev/stdout main;
+
+ proxy_redirect off;
+
+ proxy_set_header Host 'badge.imagelayers.io';
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header Connection 'Keep-Alive';
+
+ proxy_pass http://badger/;
+ }
+
+ error_page 404 500 502 503 504 /error.html;
+ location = /error.html {
+ root html;
+ }
+ }
+
+ server {
+ listen 9000 default_server;
+ server_name imagelayers.io;
location / {
root /data/dist;
@@ -35,11 +96,32 @@ http {
try_files $uri $uri/ /index.html;
}
- location /nginx_status {
- stub_status on;
- access_log off;
- allow 172.17.0.0/16;
- deny all;
+ # forward all requests for /registry to the internal imagelayers-api service
+ location /registry {
+ access_log /dev/stdout main;
+
+ rewrite /registry/(.*) /registry/$1 break;
+ proxy_redirect off;
+
+ proxy_set_header Host 'imagelayers.io';
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header Connection 'Keep-Alive';
+
+ proxy_pass http://imagelayers-api/;
+ }
+
+ # forward all requests for /badge to the internal badge service
+ location /badge {
+ access_log /dev/stdout main;
+
+ rewrite /badge/(.*) /$1 break;
+ proxy_redirect off;
+
+ proxy_set_header Host 'badge.imagelayers.io';
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header Connection 'Keep-Alive';
+
+ proxy_pass http://badger/;
}
error_page 404 500 502 503 504 /error.html;
Oops, something went wrong.

0 comments on commit 8544de6

Please sign in to comment.