This commit is contained in:
bradygmsft 2018-07-15 20:21:45 -07:00
Родитель a8efccc3fa
Коммит d7920eaad1
716 изменённых файлов: 210977 добавлений и 10 удалений

163
README.md
Просмотреть файл

@ -1,14 +1,157 @@
# Phippy and Friends
# Contributing
The [Children's Guide to Kubernetes](https://deis.com/blog/2016/kubernetes-illustrated-guide/) is a simple, gentle answer a father gives his daughter, when she inquisitively asked about Kubernetes.
This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visit https://cla.microsoft.com.
We loved the story and the imagery in it and thought the characters from the Illustrated Guide would make for an interesting demo. The demo has a few services, each of which represent an individual character in the story, as well as some we added. Each service is written in a different language, showing how the AKS cluster can run anything you can bring it.
When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
provided by the bot. You will only need to do this once across all repos using our CLA.
## Prerequisites
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
Here's a short list of all the things you'll need to do. Don't worry - you'll be up and running in about thirty minutes.
1. An [Azure](https://azure.microsoft.com/en-us/free/) subscription. You can [Sign up for Free](https://azure.microsoft.com/en-us/free/) and see for yourself how Azure Kubernetes Service (AKS) is the best place for developers using Kubernetes.
1. An Azure Kubernetes Service (AKS) Cluster, enabled with Http Application Routing (this is **on** by default when you create a cluster via the Azure portal).
1. An Azure Container Registry instance (or a Docker Hub account if you prefer to use Docker Hub).
1. You'll need to install a few tools handy for developing with containers and Kubernetes, and the Azure CLI:
1. [The Azure CLI](https://docs.microsoft.com/en-us/cli/azure/?view=azure-cli-latest)
1. [Helm](http://helm.sh) and [Draft](https://draft.sh/) are also required, as they enable deploying and debugging code in Kubernetes.
1. [Visual Studio Code](http://code.visualstudio.com) and the [Kubernetes extension](https://marketplace.visualstudio.com/items?itemName=ms-kubernetes-tools.vscode-kubernetes-tools) for it would also be great to have.
## Get Started!
To get started, follow these simple steps.
### Clone and Open the Code
The Phippy and Friends repository is public. Just clone it to your local machine and open the folder up in Visual Studio Code to get started.
```bash
git clone https://github.com/bradygmsft/phippy-demo.git
cd phippy-demo
code .
```
### Get your AKS Ingress URL
A few of the services will provide HTML UIs. To enable external access, Ingress needs to be set up on each of these services using the external DNS of the cluster. Don't worry, though, this is easy. You can use VS Code's integrated terminal or the Cloud Shell tools in VS Code to run this `az` command line call, which will get your AKS cluster's external DNS.
```bash
az aks show -n <your cluster name> -g <your resource group name> --query addonProfiles.httpApplicationRouting.config.HTTPApplicationRoutingZoneName
```
![Get DNS via AZ](media/get-url-via-az.png)
You can also get the DNS from the Azure portal if you prefer.
![Get DNS via Portal](media/get-url-in-portal.png)
We'll be deploying the **parrot** service first (more on that in a moment), so let's take a look at the `values.yaml` file for parrot. The `values.yaml` file is where you can customize your service, release, deployment, and in our case, ingress settings. Find the `basedomain` property.
![Parrot's ingress](media/find-parrot-ingress-to-edit.png)
Change the value of the `basedomain` property to match the DNS for your AKS cluster.
![Parrot's ingress](media/edit-parrot-ingress.png)
### Connect to your Registry
If you want to select which registry to push to, use the command below:
```bash
draft config set registry <your Docker hub or Azure Container Registry>
```
If you're using ACR, you can also log into your registry using the Azure CLI.
```bash
az acr login -n <your ACR instance name> -g <your ACR instance resource group>
```
### Deploy Parrot and Captain Kube with Draft and Helm
Now you'll create the first two services, **parrot** and **captainkube**.
1. The captainkube service, a simple GoLang app, is represented by Captain Kube from the Children's Illustrated Guide to Kubernetes. This service constantly watches the pods running in the Kubernetes cluster. Whenever a pod is activated, updated, or deleted from the cluster, captainkube tells the parrot service what just happened.
1. The parrot service is essentially an ASP.NET Core app with a Web API back-end. The Web API bubbles events up to the HTML client via a SignalR Hub. Parrot essentially "parrots" what captainkube is telling him in the form of [Semantic UI](http://semantic-ui.com) cards on the UI side. When services pop into the cluster, they're represented by characters shown in the cards.
These two baseline services need to be running first, so you can Draft them up into the cluster using the commands below.
```bash
cd parrot
draft up
cd ..
cd captainkube
draft up
cd ..
```
You'll be provided feedback as the deployment takes place.
![Drafting parrot and captainkube](media/drafting-parrot-and-captain.png)
## Validate the Deployment
Once the deployment has completed, enter this Kubernetes CLI command to see everything you've deployed into the cluster.
```bash
kubectl get svc,pod,ing --namespace phippyandfriends
```
You should see something like this in your terminal window.
```bash
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
parrot-parrot ClusterIP 10.0.224.230 <none> 80/TCP 3m
NAME READY STATUS RESTARTS AGE
captainkube-captainkube-f5b4487c5-shw4p 1/1 Running 0 3m
parrot-parrot-677cc74b47-zdw6z 1/1 Running 0 3m
NAME HOSTS ADDRESS PORTS
parrot-parrot parrot.0d7b3d707c094da087a7.westus.aksapp.io 80
```
It may take a few minutes for the ingress DNS to be matched up to the public IP address for the cluster. If you don't see an IP address listed for the `parrot` service, just type this command and watch the terminal window update automatically until you have a public IP address for the ingress.
```bash
kubectl get ing --namespace phippyandfriends -w
```
Eventually, your ingress will reflect the public IP address, which is your sign that parrot's DNS will work. So copy it from the terminal window.
![Copy the Ingress URI](media/copy-ingress-url.png)
Drop parrot's ingress URI into a web browser and you'll see the dashboard, which confirms you've got two services - parrot and captainkube - running in your cluster.
![Parrot Dashboard](media/parrot-dashboard.png)
### But where is Phippy?
The Phippy service is a super-simple PHP app.
Next, CD into the phippy directory, as we definitely want to make sure we deploy our star of the show, Phippy, into our AKS cluster. Use the same `draft up` command as you did for parrot and captainkube, and you'll see the phippy service's deployment status as it occurs.
The moment the deployment finishes, the dashboard will light up with Phippy!
![Phippy is Here](media/phippy-is-here.png)
### Watch in Real-time
The final service is a basic Node.js application represented by the Node.js-decorated [Azure Brady, the Open Cloud Ninja Sloth](https://github.com/Microsoft/OpenCloudNinjaSloth).
You can cd into this service's folder and deploy it using `draft up` as you did with the others. But for fun, do this in a window that's side-by-side with the parrot dashboard. This way you can see services appear as you `draft up` and vanish as you `draft delete`.
### Try Scaling your Apps
Scale your nodebrady by running this:
```bash
kubectl scale deployment/nodebrady-nodebrady --replicas 3 --namespace phippyandfriends
```
Watch as more brady ninjas come to life!
## Issues?
Phippy and Friends is open-source, and we'd love your contributions. Submit issues, then work those issues and send us a pull request. Customize the parrot dashboard with a theme, put the characters on a boat, launch them into space. We'd love to see what other characters you'll add to the dashboard!

Просмотреть файл

@ -0,0 +1,6 @@
Dockerfile
draft.toml
chart/
NOTICE
Godeps/
vendor/

Просмотреть файл

4
captainkube/.draftignore Normal file
Просмотреть файл

@ -0,0 +1,4 @@
*.swp
*.tmp
*.temp
.git*

15
captainkube/Dockerfile Normal file
Просмотреть файл

@ -0,0 +1,15 @@
# Build
FROM golang:1.9 as builder
WORKDIR /go/src/github.com/sabbour/phippy
COPY main.go .
RUN go get -d -v
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
# Run
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/sabbour/phippy/app .
CMD ["./app"]

Просмотреть файл

@ -0,0 +1,21 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj

Просмотреть файл

@ -0,0 +1,4 @@
apiVersion: v1
description: This app represents Captain Kube, who is taking care of all the containers in the cluster.
name: captainkube
version: v0.1.0

Просмотреть файл

@ -0,0 +1,6 @@
Tail the logs of the lighthouse pod
- kubectl logs -f --namespace {{ .Release.Namespace }} \
$(kubectl get pods --namespace {{ .Release.Namespace }} \
-l app={{ template "fullname" . }} \
-o jsonpath='{ .items[0].metadata.name }')

Просмотреть файл

@ -0,0 +1,16 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "fullname" -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}

Просмотреть файл

@ -0,0 +1,33 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "fullname" . }}
labels:
app: {{ template "fullname" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ template "fullname" . }}
template:
metadata:
labels:
app: {{ template "fullname" . }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: 3000
livenessProbe:
httpGet:
path: /healthz
port: 3000
initialDelaySeconds: 3
periodSeconds: 3
resources:
{{ toYaml .Values.resources | indent 12 }}

Просмотреть файл

@ -0,0 +1,3 @@
replicaCount: 1
image:
pullPolicy: Always

10
captainkube/draft.toml Normal file
Просмотреть файл

@ -0,0 +1,10 @@
[environments]
[environments.development]
name = "captainkube"
namespace = "phippyandfriends"
wait = true
watch = false
watch-delay = 2
auto-connect = false
dockerfile = ""
chart = ""

154
captainkube/main.go Normal file
Просмотреть файл

@ -0,0 +1,154 @@
package main
import (
"time"
"bytes"
"encoding/json"
"net/http"
"log"
"reflect"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/cache"
)
type Pod struct {
Container string
ContainerImage string
Name string
Namespace string
Status string
Action string
}
func main() {
log.Println("Starting up Captain Kube")
informerChannel := make(chan struct{})
go runinformer(informerChannel)
runhealthz()
<-informerChannel
log.Println("Captain Kube shutting down")
}
func runhealthz() {
// Start listening for health checks
mux := http.NewServeMux()
mux.HandleFunc("/healthz", func(w http.ResponseWriter, req *http.Request) {
checkReq, err := http.NewRequest(http.MethodGet, "http://parrot-parrot/", bytes.NewBuffer([]byte(``)))
httpclient := &http.Client{}
_, err = httpclient.Do(checkReq)
if err != nil {
log.Println("Parrot is unreachable")
w.WriteHeader(http.StatusServiceUnavailable)
} else {
w.WriteHeader(http.StatusOK)
}
})
log.Println("Listening for health checks...")
http.ListenAndServe(":3000", mux)
}
func runinformer(done chan struct{}) {
// creates the in-cluster config
config, err := rest.InClusterConfig()
if err != nil {
panic(err.Error())
}
// creates the client
client, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err.Error())
}
// Clear the cluster status, start with a blank slate
req, err := http.NewRequest(http.MethodDelete, "http://parrot-parrot/api/ClusterStatus", bytes.NewBuffer([]byte(``)))
httpclient := &http.Client{}
_, err = httpclient.Do(req)
if err != nil {
log.Printf("The HTTP request failed with error %s", err)
} else {
log.Printf("\n\n**** Cleared parrot****\n\n")
}
watchList := cache.NewListWatchFromClient(client.Core().RESTClient(), "pods", v1.NamespaceAll, fields.Everything())
// Setup the informer that will start watching for pod triggers
informer := cache.NewSharedIndexInformer(
watchList,
&v1.Pod{},
10*time.Second,
cache.Indexers{},
) // We only want `Pod`, force resync every 10 seconds
// Setup the trigger handlers that will receive triggers
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
// This method is executed when a new pod is created
AddFunc: func(obj interface{}) {
pod, ok := obj.(*v1.Pod) // cast the object as a pod
if !ok {
//log.Printf("Couldn't cast object as pod: %s", obj)
return
}
pingparrot(pod,"Added") // Ping the parrot
},
// This method is executed when an existing pod is updated
UpdateFunc: func(oldObj, newObj interface{}) {
newPod, ok := newObj.(*v1.Pod) // cast the object as a pod
if !ok {
//log.Printf("Couldn't cast object as pod: %s", newObj)
return
}
// Deep compare objects and only notify if they are truly different
if !reflect.DeepEqual(oldObj, newObj) {
pingparrot(newPod,"Updated") // Ping the parrot
}
},
// This method is executed when an existing pod is deleted
DeleteFunc: func(obj interface{}) {
pod, ok := obj.(*v1.Pod) // cast the object as a pod
if !ok {
//log.Printf("Couldn't cast object as pod: %s", obj)
return
}
pingparrot(pod,"Deleted") // Ping the parrot
},
})
// Start the informer, until `done` is closed
informer.Run(done)
}
func pingparrot(pod *v1.Pod, state string) {
if pod.ObjectMeta.Namespace != "kube-system" {
log.Printf("Pod %s: %s", state, pod.ObjectMeta.Name)
log.Printf("namespace: %s", pod.ObjectMeta.Namespace)
log.Printf("status: %s", pod.Status.Phase)
log.Printf("startTime: %s", pod.Status.StartTime)
log.Printf("conditions:")
for _, condition := range pod.Status.Conditions {
log.Printf("\ttype: %s", condition.Type)
log.Printf("\tlastTransitionTime: %s", condition.LastTransitionTime)
}
// shrink the object we send over
p := Pod{Action: state, Container: pod.Spec.Containers[0].Name, ContainerImage: pod.Spec.Containers[0].Image, Name: pod.ObjectMeta.Name, Namespace: pod.ObjectMeta.Namespace, Status: string(pod.Status.Phase)}
jsonValue, _ := json.Marshal(p)
//log.Printf("\n%s\n",jsonValue)
_, err := http.Post("http://parrot-parrot/api/ClusterStatus", "application/json", bytes.NewBuffer(jsonValue))
if err != nil {
log.Printf("The HTTP request failed with error %s", err)
} else {
log.Printf("Notified parrot: %s", state)
}
log.Printf("\n\n")
}
}

Двоичные данные
media/copy-ingress-url.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 195 KiB

Двоичные данные
media/draft-up-phippy.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 642 KiB

Двоичные данные
media/drafting-parrot-and-captain.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 972 KiB

Двоичные данные
media/edit-parrot-ingress.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 669 KiB

Двоичные данные
media/find-parrot-ingress-to-edit.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 677 KiB

Двоичные данные
media/get-url-in-portal.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 687 KiB

Двоичные данные
media/get-url-via-az.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 441 KiB

Двоичные данные
media/parrot-dashboard.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 887 KiB

Двоичные данные
media/phippy-is-here.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.2 MiB

6
nodebrady/.dockerignore Normal file
Просмотреть файл

@ -0,0 +1,6 @@
Dockerfile
draft.toml
chart/
NOTICE
node_modules
npm-debug.log

Просмотреть файл

4
nodebrady/.draftignore Normal file
Просмотреть файл

@ -0,0 +1,4 @@
*.swp
*.tmp
*.temp
.git*

13
nodebrady/.editorconfig Normal file
Просмотреть файл

@ -0,0 +1,13 @@
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

21
nodebrady/.jshintrc Normal file
Просмотреть файл

@ -0,0 +1,21 @@
{
"node": true,
"esnext": true,
"bitwise": true,
"camelcase": true,
"curly": true,
"eqeqeq": true,
"immed": true,
"indent": 2,
"latedef": true,
"newcap": true,
"noarg": true,
"quotmark": "single",
"regexp": true,
"undef": true,
"unused": true,
"strict": true,
"trailing": true,
"smarttabs": true,
"white": true
}

32
nodebrady/Dockerfile Normal file
Просмотреть файл

@ -0,0 +1,32 @@
# Build
FROM node:carbon AS base
WORKDIR /app
# Dependencies
FROM base AS dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
COPY package*.json ./
# Install app dependencies including 'devDependencies'
RUN npm install
# Copy Files/Build ----
FROM dependencies AS build
WORKDIR /app
COPY . /app
# Release with Alpine
FROM node:8.9-alpine AS release
# Create app directory
WORKDIR /app
COPY --from=dependencies /app/package.json ./
# Install app dependencies
RUN npm install --only=production
COPY --from=build /app ./
CMD ["npm", "start"]

30
nodebrady/app.js Normal file
Просмотреть файл

@ -0,0 +1,30 @@
'use strict';
const messages = require('./controllers/messages');
const compress = require('koa-compress');
const logger = require('koa-logger');
const serve = require('koa-static');
const route = require('koa-route');
const koa = require('koa');
const path = require('path');
const app = module.exports = koa();
// Logger
app.use(logger());
app.use(route.get('/', messages.home));
app.use(route.get('/messages', messages.list));
app.use(route.get('/messages/:id', messages.fetch));
app.use(route.post('/messages', messages.create));
app.use(route.get('/async', messages.delay));
app.use(route.get('/promise', messages.promise));
// Serve static files
app.use(serve(path.join(__dirname, 'public')));
// Compress
app.use(compress());
if (!module.parent) {
app.listen(3000);
console.log('listening on port 3000');
}

Просмотреть файл

@ -0,0 +1,21 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj

Просмотреть файл

@ -0,0 +1,4 @@
apiVersion: v1
description: Azure Brady in his Node.js attire.
name: nodebrady
version: v0.1.0

Просмотреть файл

@ -0,0 +1,6 @@
Tail the logs of the lighthouse pod
- kubectl logs -f --namespace {{ .Release.Namespace }} \
$(kubectl get pods --namespace {{ .Release.Namespace }} \
-l app={{ template "fullname" . }} \
-o jsonpath='{ .items[0].metadata.name }')

Просмотреть файл

@ -0,0 +1,16 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "fullname" -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}

Просмотреть файл

@ -0,0 +1,27 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "fullname" . }}
labels:
app: {{ template "fullname" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ template "fullname" . }}
template:
metadata:
labels:
app: {{ template "fullname" . }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: {{ .Values.service.internalPort }}
resources:
{{ toYaml .Values.resources | indent 12 }}

Просмотреть файл

@ -0,0 +1,22 @@
{{ if .Values.ingress.enabled }}
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: {{ template "fullname" . }}
labels:
app: {{ template "fullname" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
annotations:
kubernetes.io/ingress.class: addon-http-application-routing
spec:
rules:
- host: {{ .Release.Name }}.{{ .Values.ingress.basedomain }}
http:
paths:
- path: /
backend:
serviceName: {{ template "fullname" . }}
servicePort: {{ .Values.service.externalPort }}
{{ end }}

Просмотреть файл

@ -0,0 +1,17 @@
apiVersion: v1
kind: Service
metadata:
name: {{ template "fullname" . }}
labels:
app: {{ template "fullname" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
spec:
ports:
- port: {{ .Values.service.externalPort }}
protocol: TCP
targetPort: {{ .Values.service.internalPort }}
selector:
app: {{ template "fullname" . }}
type: ClusterIP

Просмотреть файл

@ -0,0 +1,9 @@
replicaCount: 1
image:
pullPolicy: Always
service:
internalPort: 3000
externalPort: 80
ingress:
enabled: false
#basedomain: CHANGE_TO_YOUR_DNS.REGION.aksapp.io # replace with your own from the portal

Просмотреть файл

@ -0,0 +1,55 @@
'use strict';
const views = require('co-views');
const parse = require('co-body');
const messages = [
{ id: 0,
message: 'Koa next generation web framework for node.js'
},
{ id: 1,
message: 'Koa is a new web framework designed by the team behind Express'
}
];
const render = views(__dirname + '/../views', {
map: { html: 'swig' }
});
module.exports.home = function *home(ctx) {
this.body = yield render('list', { 'messages': messages });
};
module.exports.list = function *list() {
this.body = yield messages;
};
module.exports.fetch = function *fetch(id) {
const message = messages[id];
if (!message) {
this.throw(404, 'message with id = ' + id + ' was not found');
}
this.body = yield message;
};
module.exports.create = function *create() {
const message = yield parse(this);
const id = messages.push(message) - 1;
message.id = id;
this.redirect('/');
};
const asyncOperation = () => callback =>
setTimeout(
() => callback(null, 'this was loaded asynchronously and it took 2 seconds to complete'),
2000);
const returnsPromise = () =>
new Promise((resolve, reject) =>
setTimeout(() => resolve('promise resolved after 2 seconds'), 2000));
module.exports.delay = function *delay() {
this.body = yield asyncOperation();
};
module.exports.promise = function *promise() {
this.body = yield returnsPromise();
};

10
nodebrady/draft.toml Normal file
Просмотреть файл

@ -0,0 +1,10 @@
[environments]
[environments.development]
name = "nodebrady"
namespace = "phippyandfriends"
wait = true
watch = false
watch-delay = 2
auto-connect = false
dockerfile = ""
chart = ""

906
nodebrady/package-lock.json сгенерированный Normal file
Просмотреть файл

@ -0,0 +1,906 @@
{
"name": "nodeapp",
"version": "0.0.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"accepts": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
"integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
"requires": {
"mime-types": "2.1.18",
"negotiator": "0.6.1"
}
},
"amdefine": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="
},
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
},
"ansi-styles": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
},
"any-promise": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
"integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
},
"async": {
"version": "0.2.10",
"resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
"integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E="
},
"bluebird": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
"integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA=="
},
"bytes": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz",
"integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk="
},
"camelcase": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
"integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk="
},
"chalk": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
"requires": {
"ansi-styles": "2.2.1",
"escape-string-regexp": "1.0.5",
"has-ansi": "2.0.0",
"strip-ansi": "3.0.1",
"supports-color": "2.0.0"
}
},
"co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
},
"co-body": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/co-body/-/co-body-4.2.0.tgz",
"integrity": "sha1-dN8g+nMmISXcRUgq8E40LqjbNRU=",
"requires": {
"inflation": "2.0.0",
"qs": "4.0.0",
"raw-body": "2.1.7",
"type-is": "1.6.16"
}
},
"co-render": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/co-render/-/co-render-1.1.0.tgz",
"integrity": "sha1-kPRl+rncXiNhF8WATJ/PByTm0WA=",
"requires": {
"consolidate": "0.14.5",
"debug": "2.6.9"
}
},
"co-views": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/co-views/-/co-views-2.1.0.tgz",
"integrity": "sha1-8bJNWC3mxNwEOmOsuRJZPVm/qGw=",
"requires": {
"co-render": "1.1.0",
"debug": "2.6.9",
"object-assign": "4.1.1"
}
},
"combined-stream": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz",
"integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=",
"dev": true,
"requires": {
"delayed-stream": "0.0.5"
}
},
"commander": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz",
"integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=",
"dev": true
},
"component-emitter": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz",
"integrity": "sha1-KWWU8nU9qmOZbSrwjRWpURbJrsM=",
"dev": true
},
"composition": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/composition/-/composition-2.3.0.tgz",
"integrity": "sha1-dCgFN0yrVQxSCjNmL1pzLgII1vI=",
"requires": {
"any-promise": "1.3.0",
"co": "4.6.0"
}
},
"compressible": {
"version": "2.0.14",
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.14.tgz",
"integrity": "sha1-MmxfUH+7BV9UEWeCuWmoG2einac=",
"requires": {
"mime-db": "1.34.0"
},
"dependencies": {
"mime-db": {
"version": "1.34.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.34.0.tgz",
"integrity": "sha1-RS0Oz/XDA0am3B5kseruDTcZ/5o="
}
}
},
"consolidate": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.14.5.tgz",
"integrity": "sha1-WiUEe8dvcwcmZ8jLUsmJiI9JTGM=",
"requires": {
"bluebird": "3.5.1"
}
},
"content-disposition": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
"integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ="
},
"content-type": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
},
"cookiejar": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-1.3.2.tgz",
"integrity": "sha1-YdMini2iDIWQMiM1ApWKm331gkk=",
"dev": true
},
"cookies": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/cookies/-/cookies-0.7.1.tgz",
"integrity": "sha1-fIphX1SBxhq58WyDNzG8uPZjuZs=",
"requires": {
"depd": "1.1.2",
"keygrip": "1.0.2"
}
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
"dev": true
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
},
"deep-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="
},
"delayed-stream": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz",
"integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=",
"dev": true
},
"delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
},
"depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
},
"destroy": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
},
"diff": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz",
"integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=",
"dev": true
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"error-inject": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/error-inject/-/error-inject-1.0.0.tgz",
"integrity": "sha1-4rPZG1Su1nLzCdlQ0VSFD6EdTzc="
},
"escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
"extend": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/extend/-/extend-1.2.1.tgz",
"integrity": "sha1-oPX9bPyDpf5J72mNYOyKYk3UV2w=",
"dev": true
},
"form-data": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.2.tgz",
"integrity": "sha1-EUPCE1eRGnjdeROxibS6tdXVdEU=",
"dev": true,
"requires": {
"async": "0.2.10",
"combined-stream": "0.0.7",
"mime": "1.2.11"
},
"dependencies": {
"mime": {
"version": "1.2.11",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz",
"integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=",
"dev": true
}
}
},
"formidable": {
"version": "1.0.14",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.0.14.tgz",
"integrity": "sha1-Kz9MQRy7X91pXESEPiojUUpDIxo=",
"dev": true
},
"fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
},
"glob": {
"version": "3.2.11",
"resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz",
"integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=",
"dev": true,
"requires": {
"inherits": "2.0.3",
"minimatch": "0.3.0"
}
},
"growl": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz",
"integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=",
"dev": true
},
"has-ansi": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
"requires": {
"ansi-regex": "2.1.1"
}
},
"http-assert": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.3.0.tgz",
"integrity": "sha1-oxpc+IyHPsu1eWkH1NbxMujAHko=",
"requires": {
"deep-equal": "1.0.1",
"http-errors": "1.6.3"
}
},
"http-errors": {
"version": "1.6.3",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
"integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
"requires": {
"depd": "1.1.2",
"inherits": "2.0.3",
"setprototypeof": "1.1.0",
"statuses": "1.5.0"
}
},
"humanize-number": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/humanize-number/-/humanize-number-0.0.2.tgz",
"integrity": "sha1-EcCvakcWQ2M1iFiASPF5lUFInBg="
},
"iconv-lite": {
"version": "0.4.13",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz",
"integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI="
},
"inflation": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz",
"integrity": "sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8="
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"jade": {
"version": "0.26.3",
"resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz",
"integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=",
"dev": true,
"requires": {
"commander": "0.6.1",
"mkdirp": "0.3.0"
},
"dependencies": {
"commander": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz",
"integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=",
"dev": true
},
"mkdirp": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz",
"integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=",
"dev": true
}
}
},
"keygrip": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.0.2.tgz",
"integrity": "sha1-rTKXxVcGneqLz+ek+kkbdcXd65E="
},
"koa": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/koa/-/koa-1.6.0.tgz",
"integrity": "sha512-tW7xJGDG4LyhFUTtzIyqJCIaJIFgkre1tJPGNe/moRKOIU0L9vEIhW5z7iMX7FJTkYm45urdbPOGBp0VlWF03w==",
"requires": {
"accepts": "1.3.5",
"co": "4.6.0",
"composition": "2.3.0",
"content-disposition": "0.5.2",
"content-type": "1.0.4",
"cookies": "0.7.1",
"debug": "2.6.9",
"delegates": "1.0.0",
"destroy": "1.0.4",
"error-inject": "1.0.0",
"escape-html": "1.0.3",
"fresh": "0.5.2",
"http-assert": "1.3.0",
"http-errors": "1.6.3",
"koa-compose": "2.5.1",
"koa-is-json": "1.0.0",
"mime-types": "2.1.18",
"on-finished": "2.3.0",
"only": "0.0.2",
"parseurl": "1.3.2",
"statuses": "1.5.0",
"type-is": "1.6.16",
"vary": "1.1.2"
}
},
"koa-compose": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-2.5.1.tgz",
"integrity": "sha1-cmz7F2lN5cufvwPArfFyMD+D8VY="
},
"koa-compress": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/koa-compress/-/koa-compress-1.0.9.tgz",
"integrity": "sha1-pgMDa+2rG5kH6nfMp9aUZzhS4/U=",
"requires": {
"bytes": "2.4.0",
"compressible": "2.0.14",
"koa-is-json": "1.0.0",
"statuses": "1.5.0"
}
},
"koa-is-json": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/koa-is-json/-/koa-is-json-1.0.0.tgz",
"integrity": "sha1-JzwH7c3Ljfaiwat9We52SRRR7BQ="
},
"koa-logger": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/koa-logger/-/koa-logger-1.3.1.tgz",
"integrity": "sha1-rT9fIZOzM0Mo8+uZphj0sEvui9U=",
"requires": {
"bytes": "1.0.0",
"chalk": "1.1.3",
"humanize-number": "0.0.2",
"passthrough-counter": "1.0.0"
},
"dependencies": {
"bytes": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz",
"integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g="
}
}
},
"koa-route": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/koa-route/-/koa-route-2.4.2.tgz",
"integrity": "sha1-DeInmJ5qpzNHaKu/sWxRmtmn+nE=",
"requires": {
"debug": "2.6.9",
"methods": "1.1.2",
"path-to-regexp": "1.7.0"
}
},
"koa-send": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/koa-send/-/koa-send-3.3.0.tgz",
"integrity": "sha1-WkriRVZGgMbs9geeknX6UXOoYdw=",
"requires": {
"co": "4.6.0",
"debug": "2.6.9",
"mz": "2.7.0",
"resolve-path": "1.4.0"
}
},
"koa-static": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/koa-static/-/koa-static-2.1.0.tgz",
"integrity": "sha1-z+KS6n2ryWqnI+SkiGFcxlrnQWk=",
"requires": {
"debug": "2.6.9",
"koa-send": "3.3.0"
}
},
"lru-cache": {
"version": "2.7.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz",
"integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=",
"dev": true
},
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
"methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
},
"mime": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.2.5.tgz",
"integrity": "sha1-nu0HMCKov14WyFZsaGe4gyv7+hM=",
"dev": true
},
"mime-db": {
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
"integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ=="
},
"mime-types": {
"version": "2.1.18",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
"integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
"requires": {
"mime-db": "1.33.0"
}
},
"minimatch": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz",
"integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=",
"dev": true,
"requires": {
"lru-cache": "2.7.3",
"sigmund": "1.0.1"
}
},
"minimist": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
"integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="
},
"mkdirp": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true,
"requires": {
"minimist": "0.0.8"
},
"dependencies": {
"minimist": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"dev": true
}
}
},
"mocha": {
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-2.5.3.tgz",
"integrity": "sha1-FhvlvetJZ3HrmzV0UFC2IrWu/Fg=",
"dev": true,
"requires": {
"commander": "2.3.0",
"debug": "2.2.0",
"diff": "1.4.0",
"escape-string-regexp": "1.0.2",
"glob": "3.2.11",
"growl": "1.9.2",
"jade": "0.26.3",
"mkdirp": "0.5.1",
"supports-color": "1.2.0",
"to-iso-string": "0.0.2"
},
"dependencies": {
"debug": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
"integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
"dev": true,
"requires": {
"ms": "0.7.1"
}
},
"escape-string-regexp": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz",
"integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=",
"dev": true
},
"ms": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
"integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=",
"dev": true
},
"supports-color": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz",
"integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=",
"dev": true
}
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"mz": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
"requires": {
"any-promise": "1.3.0",
"object-assign": "4.1.1",
"thenify-all": "1.6.0"
}
},
"negotiator": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
"integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
"on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
"requires": {
"ee-first": "1.1.1"
}
},
"only": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz",
"integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q="
},
"optimist": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
"integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
"requires": {
"minimist": "0.0.10",
"wordwrap": "0.0.3"
}
},
"parseurl": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
"integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M="
},
"passthrough-counter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/passthrough-counter/-/passthrough-counter-1.0.0.tgz",
"integrity": "sha1-GWfZ5m2lcrXAI8eH2xEqOHqxZvo="
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"path-to-regexp": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz",
"integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=",
"requires": {
"isarray": "0.0.1"
}
},
"qs": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz",
"integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc="
},
"raw-body": {
"version": "2.1.7",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz",
"integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=",
"requires": {
"bytes": "2.4.0",
"iconv-lite": "0.4.13",
"unpipe": "1.0.0"
}
},
"readable-stream": {
"version": "1.0.27-1",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.27-1.tgz",
"integrity": "sha1-a2eYPCA1fO/QfwFlABoW1xDZEHg=",
"dev": true,
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"isarray": "0.0.1",
"string_decoder": "0.10.31"
}
},
"reduce-component": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/reduce-component/-/reduce-component-1.0.1.tgz",
"integrity": "sha1-4Mk1QsV0UhvqE98PlIjtgqt3xdo=",
"dev": true
},
"resolve-path": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz",
"integrity": "sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc=",
"requires": {
"http-errors": "1.6.3",
"path-is-absolute": "1.0.1"
}
},
"setprototypeof": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
},
"sigmund": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz",
"integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=",
"dev": true
},
"source-map": {
"version": "0.1.34",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz",
"integrity": "sha1-p8/omux7FoLDsZjQrPtH19CQVms=",
"requires": {
"amdefine": "1.0.1"
}
},
"statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
"dev": true
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"requires": {
"ansi-regex": "2.1.1"
}
},
"superagent": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/superagent/-/superagent-0.18.0.tgz",
"integrity": "sha1-nUN1o64sT71V/SDVsSokcNL8j2I=",
"dev": true,
"requires": {
"component-emitter": "1.1.2",
"cookiejar": "1.3.2",
"debug": "0.7.4",
"extend": "1.2.1",
"form-data": "0.1.2",
"formidable": "1.0.14",
"methods": "0.0.1",
"mime": "1.2.5",
"qs": "0.6.6",
"readable-stream": "1.0.27-1",
"reduce-component": "1.0.1"
},
"dependencies": {
"debug": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz",
"integrity": "sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk=",
"dev": true
},
"methods": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/methods/-/methods-0.0.1.tgz",
"integrity": "sha1-J3yQ+L7zlwlkWoNxxRw7bGSOBow=",
"dev": true
},
"qs": {
"version": "0.6.6",
"resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz",
"integrity": "sha1-bgFQmP9RlouKPIGQAdXyyJvEsQc=",
"dev": true
}
}
},
"supertest": {
"version": "0.12.1",
"resolved": "https://registry.npmjs.org/supertest/-/supertest-0.12.1.tgz",
"integrity": "sha1-Aqu8vs8UiDhnSXExi+QCGyX6GIE=",
"dev": true,
"requires": {
"methods": "1.0.0",
"superagent": "0.18.0"
},
"dependencies": {
"methods": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.0.0.tgz",
"integrity": "sha1-mnPYY3XfzvJu9hyj5Lii4lOKgOM=",
"dev": true
}
}
},
"supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
},
"swig": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/swig/-/swig-1.4.2.tgz",
"integrity": "sha1-QIXKBFM2kQS11IPihBs5t64aq6U=",
"requires": {
"optimist": "0.6.1",
"uglify-js": "2.4.24"
}
},
"thenify": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz",
"integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=",
"requires": {
"any-promise": "1.3.0"
}
},
"thenify-all": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
"integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=",
"requires": {
"thenify": "3.3.0"
}
},
"to-iso-string": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz",
"integrity": "sha1-TcGeZk38y+Jb2NtQiwDG2hWCVdE=",
"dev": true
},
"type-is": {
"version": "1.6.16",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
"integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
"requires": {
"media-typer": "0.3.0",
"mime-types": "2.1.18"
}
},
"uglify-js": {
"version": "2.4.24",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.24.tgz",
"integrity": "sha1-+tV1XB4Vd2WLsG/5q25UjJW+vW4=",
"requires": {
"async": "0.2.10",
"source-map": "0.1.34",
"uglify-to-browserify": "1.0.2",
"yargs": "3.5.4"
}
},
"uglify-to-browserify": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
"integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc="
},
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
"window-size": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
"integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0="
},
"wordwrap": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
"integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="
},
"yargs": {
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz",
"integrity": "sha1-2K/49mXpTDS9JZvevRv68N3TU2E=",
"requires": {
"camelcase": "1.2.1",
"decamelize": "1.2.0",
"window-size": "0.1.0",
"wordwrap": "0.0.2"
},
"dependencies": {
"wordwrap": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
"integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8="
}
}
}
}
}

23
nodebrady/package.json Normal file
Просмотреть файл

@ -0,0 +1,23 @@
{
"name": "nodebrady",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node app.js",
"test": "mocha"
},
"dependencies": {
"koa": "^1.2.0",
"koa-logger": "^1.2.0",
"koa-static": "^2.0.0",
"koa-route": "^2.4.2",
"koa-compress": "^1.0.6",
"co-views": "^2.1.0",
"swig": "^1.3.2",
"co-body": "^4.0.0"
},
"devDependencies": {
"supertest": "^0.12.1",
"mocha": "^2.4.5"
}
}

Просмотреть файл

Просмотреть файл

@ -0,0 +1,25 @@
ul {
margin: 100px auto 0;
list-style: none;
width: 700px;
font: 30px helvetica;
font-weight: 100;
}
li {
margin-bottom: 50px;
}
form {
width: 700px;
margin: 0 auto;
}
textarea {
border-style: none;
width: 700px;
margin-left: 20px;
height: 100px;
font: 30px helvetica;
font-weight: 100;
}

Просмотреть файл

@ -0,0 +1,30 @@
/*global describe, it*/
'use strict';
const superagent = require('supertest');
const app = require('../app');
const request = superagent(app.listen());
describe('Routes', () => {
describe('GET /', () => {
it('should return 200', done => {
request
.get('/')
.expect(200, done);
});
});
describe('GET /messages', () => {
it('should return 200', done => {
request
.get('/messages')
.expect('Content-Type', /json/)
.expect(200, done);
});
});
describe('GET /messages/notfound', () => {
it('should return 404', done => {
request
.get('/messages/notfound')
.expect(404, done);
});
});
});

Просмотреть файл

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}Messages{% endblock %}</title>
<link rel="stylesheet" type="text/css" href="styles/main.css">
</head>
<body>
<section id="content">
{% block content %}
<p>Forgot to add content?</p>
{% endblock %}
</section>
</body>
</html>

15
nodebrady/views/list.html Normal file
Просмотреть файл

@ -0,0 +1,15 @@
{% extends 'layout.html' %}
{% block title %}Messages{% endblock %}
{% block content %}
<ul class="messages">
{% for message in messages %}
<li class="message">{{ message.message }}</li>
{% endfor %}
</ul>
<form action="/messages" method="post" id="message-form">
<textarea placeholder="Insert a message" name="message"
onkeydown="if (event.keyCode == 13) document.getElementById('message-form').submit();"></textarea>
</form>
{% endblock %}

7
parrot/.dockerignore Normal file
Просмотреть файл

@ -0,0 +1,7 @@
Dockerfile
draft.toml
chart/
NOTICE
bin/
obj/
!published/

0
parrot/.draft-tasks.toml Normal file
Просмотреть файл

4
parrot/.draftignore Normal file
Просмотреть файл

@ -0,0 +1,4 @@
*.swp
*.tmp
*.temp
.git*

46
parrot/.vscode/launch.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,46 @@
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/bin/Debug/netcoreapp2.0/parrot.dll",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"internalConsoleOptions": "openOnSessionStart",
"launchBrowser": {
"enabled": true,
"args": "${auto-detect-url}",
"windows": {
"command": "cmd.exe",
"args": "/C start ${auto-detect-url}"
},
"osx": {
"command": "open"
},
"linux": {
"command": "xdg-open"
}
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Views"
}
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickProcess}"
}
,]
}

15
parrot/.vscode/tasks.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,15 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/parrot.csproj"
],
"problemMatcher": "$msCompile"
}
]
}

Просмотреть файл

@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using parrot;
using parrot.Models;
namespace api.Controllers
{
[Route("api/[controller]")]
public class ClusterStatusController : Controller
{
public ClusterStatusController(ILogger<ClusterStatusController> logger, DaemonHub hub)
{
_hub = hub;
_logger = logger;
}
private DaemonHub _hub;
private readonly ILogger _logger;
[HttpGet]
public ActionResult Get()
{
return new OkResult();
}
[HttpDelete]
public ActionResult Delete()
{
_logger.LogDebug("Incoming Cluster Clear");
try {
_hub.clearClusterView();
}
catch(Exception ex) {
HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
_logger.LogWarning(ex, "Error clearing cluster view");
return Json(new { status="error",message=$"error updating cluster view {ex.Message}"});
}
return new OkResult();
}
[HttpPost]
public ActionResult Post([FromBody]Pod pod)
{
_logger.LogDebug("Incoming Cluster Update");
_logger.LogDebug(pod.ToString());
try {
_hub.updateClusterView(pod);
}
catch(Exception ex) {
HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
_logger.LogWarning(ex, "Error updating cluster view");
return Json(new { status="error",message=$"error updating cluster view {ex.Message}"});
}
return new OkResult();
}
}
}

Просмотреть файл

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using parrot.Models;
namespace parrot.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}

Просмотреть файл

@ -0,0 +1,127 @@
"metadata": {
"name": "nodeapp-nodeapp-66845c9868-phvqv",
"generateName": "nodeapp-nodeapp-66845c9868-",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/pods/nodeapp-nodeapp-66845c9868-phvqv",
"uid": "2c843057-75b3-11e8-bdbc-b20c0e5c020c",
"resourceVersion": "403506",
"creationTimestamp": "2018-06-22T00:28:24Z",
"labels": {
"app": "nodeapp-nodeapp",
"pod-template-hash": "2240175424"
},
"ownerReferences": [
{
"apiVersion": "extensions/v1beta1",
"kind": "ReplicaSet",
"name": "nodeapp-nodeapp-66845c9868",
"uid": "2c82728a-75b3-11e8-bdbc-b20c0e5c020c",
"controller": true,
"blockOwnerDeletion": true
}
]
},
"spec": {
"volumes": [
{
"name": "default-token-w8ncl",
"secret": {
"secretName": "default-token-w8ncl",
"defaultMode": 420
}
}
],
"containers": [
{
"name": "nodeapp",
"image": "phippy.azurecr.io/nodeapp:a11a2889166b4e3031ac506e35c238d9f8756fa3",
"ports": [
{
"containerPort": 3000,
"protocol": "TCP"
}
],
"resources": {},
"volumeMounts": [
{
"name": "default-token-w8ncl",
"readOnly": true,
"mountPath": "/var/run/secrets/kubernetes.io/serviceaccount"
}
],
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File",
"imagePullPolicy": "Always"
}
],
"restartPolicy": "Always",
"terminationGracePeriodSeconds": 30,
"dnsPolicy": "ClusterFirst",
"serviceAccountName": "default",
"serviceAccount": "default",
"nodeName": "aks-agentpool-19990256-0",
"securityContext": {},
"imagePullSecrets": [
{
"name": "draft-pullsecret"
}
],
"schedulerName": "default-scheduler",
"tolerations": [
{
"key": "node.kubernetes.io/not-ready",
"operator": "Exists",
"effect": "NoExecute",
"tolerationSeconds": 300
},
{
"key": "node.kubernetes.io/unreachable",
"operator": "Exists",
"effect": "NoExecute",
"tolerationSeconds": 300
}
]
},
"status": {
"phase": "Running",
"conditions": [
{
"type": "Initialized",
"status": "True",
"lastProbeTime": null,
"lastTransitionTime": "2018-06-22T00:28:24Z"
},
{
"type": "Ready",
"status": "True",
"lastProbeTime": null,
"lastTransitionTime": "2018-06-22T00:28:26Z"
},
{
"type": "PodScheduled",
"status": "True",
"lastProbeTime": null,
"lastTransitionTime": "2018-06-22T00:28:24Z"
}
],
"hostIP": "10.240.0.4",
"podIP": "10.244.0.53",
"startTime": "2018-06-22T00:28:24Z",
"containerStatuses": [
{
"name": "nodeapp",
"state": {
"running": {
"startedAt": "2018-06-22T00:28:26Z"
}
},
"lastState": {},
"ready": true,
"restartCount": 0,
"image": "phippy.azurecr.io/nodeapp:a11a2889166b4e3031ac506e35c238d9f8756fa3",
"imageID": "docker-pullable://phippy.azurecr.io/nodeapp@sha256:b6cddce8c015b215bf1268420825b9ec3fca9e4075aee42bacf264cd055c010f",
"containerID": "docker://874c69c9b6a8cf4c9bc820ef762d55133fffd43074f52f15f1cb6388f371e51a"
}
],
"qosClass": "BestEffort"
}

16
parrot/Dockerfile Normal file
Просмотреть файл

@ -0,0 +1,16 @@
FROM microsoft/aspnetcore-build:2.0 AS build-env
WORKDIR /app
# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore
# Copy everything else and build
COPY . ./
RUN dotnet publish -c Release -o out
# Build runtime image
FROM microsoft/aspnetcore:2.0
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "parrot.dll"]

75
parrot/Hubs/Daemon.cs Normal file
Просмотреть файл

@ -0,0 +1,75 @@
using System.Threading.Tasks;
using System.Collections;
using System.Linq;
using System.Collections.Generic;
using Microsoft.AspNetCore.SignalR;
using parrot.Models;
namespace parrot
{
public class DaemonHub : Hub
{
static List<Pod> Pods { get; set; }
static List<string> DeletedPods { get; set; }
static DaemonHub()
{
Pods = new List<Pod>();
DeletedPods = new List<string>();
}
const string POD_DELETED_STATUS = "Deleted";
public override Task OnConnectedAsync()
{
Clients.All.SendAsync("clusterViewUpdated", Pods);
return base.OnConnectedAsync();
}
public void AddPod(Pod pod)
{
if(!DeletedPods.Contains(pod.Name))
{
Pods.Add(pod);
}
}
public void RemovePod(Pod pod)
{
Pods.Remove(Pods.First(x => x.Name == pod.Name));
DeletedPods.Add(pod.Name);
}
public void UpdatePod(Pod pod)
{
Pods.First(x => x.Name == pod.Name).Name = pod.Name;
Pods.First(x => x.Name == pod.Name).Container = pod.Container;
Pods.First(x => x.Name == pod.Name).NameSpace = pod.NameSpace;
Pods.First(x => x.Name == pod.Name).Status = pod.Status;
}
public void clearClusterView()
{
Pods.Clear();
Clients.All.SendAsync("clusterViewUpdated", Pods);
}
public void updateClusterView(Pod pod)
{
// If the container image is "image:tag", strip the ":tag", otherwise leave it alone
// not all images are tagged, so..
if(pod.ContainerImage.Contains(':'))
pod.ContainerImage = pod.ContainerImage.Substring(0, pod.ContainerImage.IndexOf(':'));
if (Pods.Any(x => x.Name == pod.Name))
if (pod.Action == POD_DELETED_STATUS)
RemovePod(pod);
else
UpdatePod(pod);
else
AddPod(pod);
Clients.All.SendAsync("clusterViewUpdated", Pods);
}
}
}

Просмотреть файл

@ -0,0 +1,11 @@
using System;
namespace parrot.Models
{
public class ErrorViewModel
{
public string RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
}
}

22
parrot/Models/Pod.cs Normal file
Просмотреть файл

@ -0,0 +1,22 @@
using System;
namespace parrot.Models
{
public class Pod
{
public string Name { get; set; }
public string Container { get; set; }
public string NameSpace { get; set; }
public string ContainerImage { get; set; }
public string Status { get; set; }
public string Action { get; set; }
public string CardImageUrl
{
get { return string.Format("/media/{0}.png", Container); }
}
public override string ToString() {
return $"Name: {Name}\nContainer: {Container}\nNameSpace: {NameSpace}\nContainerImage: {ContainerImage}\nStatus: {Status}\nAction: {Action}\nCardImageUrl: {CardImageUrl}";
}
}
}

9
parrot/NOTICE Normal file
Просмотреть файл

@ -0,0 +1,9 @@
MIT License:
Copyright (C) 2017 Cloudbase Solutions, Srl
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

25
parrot/Program.cs Normal file
Просмотреть файл

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace parrot
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
}

59
parrot/Startup.cs Normal file
Просмотреть файл

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace parrot
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<DaemonHub>(new DaemonHub());
services.AddMvc();
services.AddSignalR();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseSignalR(routes => {
routes.MapHub<DaemonHub>("/daemonhub");
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}

Просмотреть файл

@ -0,0 +1,34 @@
@{
ViewData["Title"] = "parrot";
}
<ul id="pods">
</ul>
<div class="ui link cards" id="podcards" data-bind="foreach: pods">
<div class="ui card">
<div class="image">
<img data-bind="attr:{src: cardImageUrl}"/>
</div>
<div class="content">
<a class="header"><span data-bind="text: container"></span></a>
</div>
<div class="extra content">
<span data-bind="text: name"></span>
</div>
</div>
</div>
@section footer
{
<div class="ui centered seven wide column">
<h4 class="ui centered inverted header">Connection Status: <span id="connectionStatus">Idle</span></h4>
</div>
}
@section scripts
{
<script src="~/scripts/knockout-3.4.2.js"></script>
<script src="~/scripts/signalr.min.js"></script>
<script src="~/scripts/daemon.js"></script>
}

Просмотреть файл

@ -0,0 +1,22 @@
@model ErrorViewModel
@{
ViewData["Title"] = "Error";
}
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}
<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
<strong>Development environment should not be enabled in deployed applications</strong>, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>, and restarting the application.
</p>

Просмотреть файл

@ -0,0 +1,54 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - parrot</title>
<link rel="stylesheet" type="text/css" href="~/semantic/semantic.min.css">
<style type="text/css">
body {
background-color: #FFFFFF;
}
.ui.menu .item img.logo {
margin-right: 1.5em;
}
.main.container {
margin-top: 7em;
}
.wireframe {
margin-top: 2em;
}
.ui.footer.segment {
margin: 5em 0em 0em;
padding: 5em 0em;
}
</style>
</head>
<body>
<div class="ui fixed inverted menu">
<div class="ui container">
<a href="/" class="header item">
<img class="logo" src="~/media/parrot.png">
parrot tells us whatever captain kube is saying is happening in the cluster
</a>
</div>
</div>
<div class="ui main container">
@RenderBody()
</div>
<div class="ui inverted vertical footer segment">
@RenderSection("Footer", required: false)
</div>
<script
src="https://code.jquery.com/jquery-3.1.1.min.js"
integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
crossorigin="anonymous"></script>
<script src="semantic/semantic.min.js"></script>
@RenderSection("Scripts", required: false)
</body>
</html>

Просмотреть файл

@ -0,0 +1,18 @@
<environment include="Development">
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
</environment>
<environment exclude="Development">
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.14.0/jquery.validate.min.js"
asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator"
crossorigin="anonymous"
integrity="sha384-Fnqn3nxp3506LP/7Y3j/25BlWeA3PXTyT1l78LjECcPaKCV12TsZP7yyMxOe/G/k">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validation.unobtrusive/3.2.6/jquery.validate.unobtrusive.min.js"
asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
crossorigin="anonymous"
integrity="sha384-JrXK+k53HACyavUKOsL+NkmSesD2P+73eDMrbTtTk0h4RmOF8hF8apPlkp26JlyH">
</script>
</environment>

Просмотреть файл

@ -0,0 +1,3 @@
@using parrot
@using parrot.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Просмотреть файл

@ -0,0 +1,3 @@
@{
Layout = "_Layout";
}

Просмотреть файл

@ -0,0 +1,10 @@
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}

8
parrot/appsettings.json Normal file
Просмотреть файл

@ -0,0 +1,8 @@
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning"
}
}
}

24
parrot/bundleconfig.json Normal file
Просмотреть файл

@ -0,0 +1,24 @@
// Configure bundling and minification for the project.
// More info at https://go.microsoft.com/fwlink/?LinkId=808241
[
{
"outputFileName": "wwwroot/css/site.min.css",
// An array of relative input file paths. Globbing patterns supported
"inputFiles": [
"wwwroot/css/site.css"
]
},
{
"outputFileName": "wwwroot/js/site.min.js",
"inputFiles": [
"wwwroot/js/site.js"
],
// Optionally specify minification options
"minify": {
"enabled": true,
"renameLocals": true
},
// Optionally generate .map file
"sourceMap": false
}
]

Просмотреть файл

@ -0,0 +1,21 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj

Просмотреть файл

@ -0,0 +1,4 @@
apiVersion: v1
description: Parrot is Captain Kube's sidekick, who shows everything the captain's doing on-screen.
name: parrot
version: v0.1.0

Просмотреть файл

@ -0,0 +1,6 @@
Tail the logs of the lighthouse pod
- kubectl logs -f --namespace {{ .Release.Namespace }} \
$(kubectl get pods --namespace {{ .Release.Namespace }} \
-l app={{ template "fullname" . }} \
-o jsonpath='{ .items[0].metadata.name }')

Просмотреть файл

@ -0,0 +1,16 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "fullname" -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}

Просмотреть файл

@ -0,0 +1,28 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "fullname" . }}
labels:
app: {{ template "fullname" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ template "fullname" . }}
template:
metadata:
labels:
app: {{ template "fullname" . }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
resources:
{{ toYaml .Values.resources | indent 12 }}
env:
- name: ASPNETCORE_ENVIRONMENT
value: Development

Просмотреть файл

@ -0,0 +1,22 @@
{{ if .Values.ingress.enabled }}
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: {{ template "fullname" . }}
labels:
app: {{ template "fullname" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
annotations:
kubernetes.io/ingress.class: addon-http-application-routing
spec:
rules:
- host: {{ .Release.Name }}.{{ .Values.ingress.basedomain }}
http:
paths:
- path: /
backend:
serviceName: {{ template "fullname" . }}
servicePort: {{ .Values.service.externalPort }}
{{ end }}

Просмотреть файл

@ -0,0 +1,17 @@
apiVersion: v1
kind: Service
metadata:
name: {{ template "fullname" . }}
labels:
app: {{ template "fullname" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
spec:
ports:
- port: {{ .Values.service.externalPort }}
protocol: TCP
targetPort: {{ .Values.service.internalPort }}
selector:
app: {{ template "fullname" . }}
type: ClusterIP

Просмотреть файл

@ -0,0 +1,9 @@
replicaCount: 1
image:
pullPolicy: Always
service:
internalPort: 80
externalPort: 80
ingress:
enabled: true
basedomain: <REPLACE WITH YOUR OWN AKS CLUSTER>.<YOUR REGION>.aksapp.io # replace with your own from the portal

10
parrot/draft.toml Normal file
Просмотреть файл

@ -0,0 +1,10 @@
[environments]
[environments.development]
name = "parrot"
namespace = "phippyandfriends"
wait = true
watch = false
watch-delay = 2
auto-connect = false
dockerfile = ""
chart = ""

6184
parrot/package-lock.json сгенерированный Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

15
parrot/package.json Normal file
Просмотреть файл

@ -0,0 +1,15 @@
{
"name": "parrot",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@aspnet/signalr": "^1.0.0",
"semantic-ui": "^2.3.2"
}
}

17
parrot/parrot.csproj Normal file
Просмотреть файл

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" />
<PackageReference Include="Microsoft.Azure.SignalR" Version="1.0.0-preview1-100" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.2" />
<DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="2.0.0" />
</ItemGroup>
</Project>

22
parrot/semantic.json Normal file
Просмотреть файл

@ -0,0 +1,22 @@
{
"base": "semantic/",
"paths": {
"source": {
"config": "src/theme.config",
"definitions": "src/definitions/",
"site": "src/site/",
"themes": "src/themes/"
},
"output": {
"packaged": "../wwwroot/semantic/",
"uncompressed": "../wwwroot/semantic/components/",
"compressed": "../wwwroot/semantic/components/",
"themes": "../wwwroot/semantic/themes/"
},
"clean": "../wwwroot/semantic/"
},
"permission": false,
"autoInstall": false,
"rtl": false,
"version": "2.3.2"
}

Просмотреть файл

@ -0,0 +1,72 @@
/*******************************
Set-up
*******************************/
var
gulp = require('gulp-help')(require('gulp')),
// read user config to know what task to load
config = require('./tasks/config/user'),
// watch changes
watch = require('./tasks/watch'),
// build all files
build = require('./tasks/build'),
buildJS = require('./tasks/build/javascript'),
buildCSS = require('./tasks/build/css'),
buildAssets = require('./tasks/build/assets'),
// utility
clean = require('./tasks/clean'),
version = require('./tasks/version'),
// docs tasks
serveDocs = require('./tasks/docs/serve'),
buildDocs = require('./tasks/docs/build'),
// rtl
buildRTL = require('./tasks/rtl/build'),
watchRTL = require('./tasks/rtl/watch')
;
/*******************************
Tasks
*******************************/
gulp.task('default', false, [
'watch'
]);
gulp.task('watch', 'Watch for site/theme changes', watch);
gulp.task('build', 'Builds all files from source', build);
gulp.task('build-javascript', 'Builds all javascript from source', buildJS);
gulp.task('build-css', 'Builds all css from source', buildCSS);
gulp.task('build-assets', 'Copies all assets from source', buildAssets);
gulp.task('clean', 'Clean dist folder', clean);
gulp.task('version', 'Displays current version of Semantic', version);
/*--------------
Docs
---------------*/
/*
Lets you serve files to a local documentation instance
https://github.com/Semantic-Org/Semantic-UI-Docs/
*/
gulp.task('serve-docs', 'Serve file changes to SUI Docs', serveDocs);
gulp.task('build-docs', 'Build all files and add to SUI Docs', buildDocs);
/*--------------
RTL
---------------*/
if(config.rtl) {
gulp.task('watch-rtl', 'Watch files as RTL', watchRTL);
gulp.task('build-rtl', 'Build all files as RTL', buildRTL);
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,122 @@
/*!
* # Semantic UI - Breadcrumb
* http://github.com/semantic-org/semantic-ui/
*
*
* Released under the MIT license
* http://opensource.org/licenses/MIT
*
*/
/*******************************
Theme
*******************************/
@type : 'collection';
@element : 'breadcrumb';
@import (multiple) '../../theme.config';
/*******************************
Breadcrumb
*******************************/
.ui.breadcrumb {
line-height: 1;
display: @display;
margin: @verticalMargin 0em;
vertical-align: @verticalAlign;
}
.ui.breadcrumb:first-child {
margin-top: 0em;
}
.ui.breadcrumb:last-child {
margin-bottom: 0em;
}
/*******************************
Content
*******************************/
/* Divider */
.ui.breadcrumb .divider {
display: inline-block;
opacity: @dividerOpacity;
margin: 0em @dividerSpacing 0em;
font-size: @dividerSize;
color: @dividerColor;
vertical-align: @dividerVerticalAlign;
}
/* Link */
.ui.breadcrumb a {
color: @linkColor;
}
.ui.breadcrumb a:hover {
color: @linkHoverColor;
}
/* Icon Divider */
.ui.breadcrumb .icon.divider {
font-size: @iconDividerSize;
vertical-align: @iconDividerVerticalAlign;
}
/* Section */
.ui.breadcrumb a.section {
cursor: pointer;
}
.ui.breadcrumb .section {
display: inline-block;
margin: @sectionMargin;
padding: @sectionPadding;
}
/* Loose Coupling */
.ui.breadcrumb.segment {
display: inline-block;
padding: @segmentPadding;
}
/*******************************
States
*******************************/
.ui.breadcrumb .active.section {
font-weight: @activeFontWeight;
}
/*******************************
Variations
*******************************/
.ui.mini.breadcrumb {
font-size: @mini;
}
.ui.tiny.breadcrumb {
font-size: @tiny;
}
.ui.small.breadcrumb {
font-size: @small;
}
.ui.breadcrumb {
font-size: @medium;
}
.ui.large.breadcrumb {
font-size: @large;
}
.ui.big.breadcrumb {
font-size: @big;
}
.ui.huge.breadcrumb {
font-size: @huge;
}
.ui.massive.breadcrumb {
font-size: @massive;
}
.loadUIOverrides();

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,481 @@
/*!
* # Semantic UI - Message
* http://github.com/semantic-org/semantic-ui/
*
*
* Released under the MIT license
* http://opensource.org/licenses/MIT
*
*/
/*******************************
Theme
*******************************/
@type : 'collection';
@element : 'message';
@import (multiple) '../../theme.config';
/*******************************
Message
*******************************/
.ui.message {
position: relative;
min-height: 1em;
margin: @verticalMargin 0em;
background: @background;
padding: @padding;
line-height: @lineHeight;
color: @textColor;
transition: @transition;
border-radius: @borderRadius;
box-shadow: @boxShadow;
}
.ui.message:first-child {
margin-top: 0em;
}
.ui.message:last-child {
margin-bottom: 0em;
}
/*--------------
Content
---------------*/
/* Header */
.ui.message .header {
display: @headerDisplay;
font-family: @headerFont;
font-weight: @headerFontWeight;
margin: @headerMargin;
}
/* Default font size */
.ui.message .header:not(.ui) {
font-size: @headerFontSize;
}
/* Paragraph */
.ui.message p {
opacity: @messageTextOpacity;
margin: @messageParagraphMargin 0em;
}
.ui.message p:first-child {
margin-top: 0em;
}
.ui.message p:last-child {
margin-bottom: 0em;
}
.ui.message .header + p {
margin-top: @headerParagraphDistance;
}
/* List */
.ui.message .list:not(.ui) {
text-align: left;
padding: 0em;
opacity: @listOpacity;
list-style-position: @listStylePosition;
margin: @listMargin 0em 0em;
}
.ui.message .list:not(.ui):first-child {
margin-top: 0em;
}
.ui.message .list:not(.ui):last-child {
margin-bottom: 0em;
}
.ui.message .list:not(.ui) li {
position: relative;
list-style-type: none;
margin: 0em 0em @listItemMargin @listItemIndent;
padding: 0em;
}
.ui.message .list:not(.ui) li:before {
position: absolute;
content: '•';
left: -1em;
height: 100%;
vertical-align: baseline;
}
.ui.message .list:not(.ui) li:last-child {
margin-bottom: 0em;
}
/* Icon */
.ui.message > .icon {
margin-right: @iconDistance;
}
/* Close Icon */
.ui.message > .close.icon {
cursor: pointer;
position: absolute;
margin: 0em;
top: @closeTopDistance;
right: @closeRightDistance;
opacity: @closeOpacity;
transition: @closeTransition;
}
.ui.message > .close.icon:hover {
opacity: 1;
}
/* First / Last Element */
.ui.message > :first-child {
margin-top: 0em;
}
.ui.message > :last-child {
margin-bottom: 0em;
}
/*******************************
Coupling
*******************************/
.ui.dropdown .menu > .message {
margin: 0px -@borderWidth;
}
/*******************************
States
*******************************/
/*--------------
Visible
---------------*/
.ui.visible.visible.visible.visible.message {
display: block;
}
.ui.icon.visible.visible.visible.visible.message {
display: flex;
}
/*--------------
Hidden
---------------*/
.ui.hidden.hidden.hidden.hidden.message {
display: none;
}
/*******************************
Variations
*******************************/
/*--------------
Compact
---------------*/
.ui.compact.message {
display: inline-block;
}
.ui.compact.icon.message {
display: inline-flex;
}
/*--------------
Attached
---------------*/
.ui.attached.message {
margin-bottom: @attachedYOffset;
border-radius: @borderRadius @borderRadius 0em 0em;
box-shadow: @attachedBoxShadow;
margin-left: @attachedXOffset;
margin-right: @attachedXOffset;
}
.ui.attached + .ui.attached.message:not(.top):not(.bottom) {
margin-top: @attachedYOffset;
border-radius: 0em;
}
.ui.bottom.attached.message {
margin-top: @attachedYOffset;
border-radius: 0em 0em @borderRadius @borderRadius;
box-shadow: @attachedBottomBoxShadow;
}
.ui.bottom.attached.message:not(:last-child) {
margin-bottom: @verticalMargin;
}
.ui.attached.icon.message {
width: auto;
}
/*--------------
Icon
---------------*/
.ui.icon.message {
display: flex;
width: 100%;
align-items: center;
}
.ui.icon.message > .icon:not(.close) {
display: block;
flex: 0 0 auto;
width: auto;
line-height: 1;
vertical-align: @iconVerticalAlign;
font-size: @iconSize;
opacity: @iconOpacity;
}
.ui.icon.message > .content {
display: block;
flex: 1 1 auto;
vertical-align: @iconVerticalAlign;
}
.ui.icon.message .icon:not(.close) + .content {
padding-left: @iconContentDistance;
}
.ui.icon.message .circular.icon {
width: 1em;
}
/*--------------
Floating
---------------*/
.ui.floating.message {
box-shadow: @floatingBoxShadow;
}
/*--------------
Colors
---------------*/
.ui.black.message {
background-color: @black;
color: @invertedTextColor;
}
/*--------------
Types
---------------*/
/* Positive */
.ui.positive.message {
background-color: @positiveBackgroundColor;
color: @positiveTextColor;
}
.ui.positive.message,
.ui.attached.positive.message {
box-shadow: @positiveBoxShadow;
}
.ui.positive.message .header {
color: @positiveHeaderColor;
}
/* Negative */
.ui.negative.message {
background-color: @negativeBackgroundColor;
color: @negativeTextColor;
}
.ui.negative.message,
.ui.attached.negative.message {
box-shadow: @negativeBoxShadow;
}
.ui.negative.message .header {
color: @negativeHeaderColor;
}
/* Info */
.ui.info.message {
background-color: @infoBackgroundColor;
color: @infoTextColor;
}
.ui.info.message,
.ui.attached.info.message {
box-shadow: @infoBoxShadow;
}
.ui.info.message .header {
color: @infoHeaderColor;
}
/* Warning */
.ui.warning.message {
background-color: @warningBackgroundColor;
color: @warningTextColor;
}
.ui.warning.message,
.ui.attached.warning.message {
box-shadow: @warningBoxShadow;
}
.ui.warning.message .header {
color: @warningHeaderColor;
}
/* Error */
.ui.error.message {
background-color: @errorBackgroundColor;
color: @errorTextColor;
}
.ui.error.message,
.ui.attached.error.message {
box-shadow: @errorBoxShadow;
}
.ui.error.message .header {
color: @errorHeaderColor;
}
/* Success */
.ui.success.message {
background-color: @successBackgroundColor;
color: @successTextColor;
}
.ui.success.message,
.ui.attached.success.message {
box-shadow: @successBoxShadow;
}
.ui.success.message .header {
color: @successHeaderColor;
}
/* Colors */
.ui.inverted.message,
.ui.black.message {
background-color: @black;
color: @invertedTextColor;
}
.ui.red.message {
background-color: @redBackground;
color: @redTextColor;
box-shadow: @redBoxShadow;
}
.ui.red.message .header {
color: @redHeaderColor;
}
.ui.orange.message {
background-color: @orangeBackground;
color: @orangeTextColor;
box-shadow: @orangeBoxShadow;
}
.ui.orange.message .header {
color: @orangeHeaderColor;
}
.ui.yellow.message {
background-color: @yellowBackground;
color: @yellowTextColor;
box-shadow: @yellowBoxShadow;
}
.ui.yellow.message .header {
color: @yellowHeaderColor;
}
.ui.olive.message {
background-color: @oliveBackground;
color: @oliveTextColor;
box-shadow: @oliveBoxShadow;
}
.ui.olive.message .header {
color: @oliveHeaderColor;
}
.ui.green.message {
background-color: @greenBackground;
color: @greenTextColor;
box-shadow: @greenBoxShadow;
}
.ui.green.message .header {
color: @greenHeaderColor;
}
.ui.teal.message {
background-color: @tealBackground;
color: @tealTextColor;
box-shadow: @tealBoxShadow;
}
.ui.teal.message .header {
color: @tealHeaderColor;
}
.ui.blue.message {
background-color: @blueBackground;
color: @blueTextColor;
box-shadow: @blueBoxShadow;
}
.ui.blue.message .header {
color: @blueHeaderColor;
}
.ui.violet.message {
background-color: @violetBackground;
color: @violetTextColor;
box-shadow: @violetBoxShadow;
}
.ui.violet.message .header {
color: @violetHeaderColor;
}
.ui.purple.message {
background-color: @purpleBackground;
color: @purpleTextColor;
box-shadow: @purpleBoxShadow;
}
.ui.purple.message .header {
color: @purpleHeaderColor;
}
.ui.pink.message {
background-color: @pinkBackground;
color: @pinkTextColor;
box-shadow: @pinkBoxShadow;
}
.ui.pink.message .header {
color: @pinkHeaderColor;
}
.ui.brown.message {
background-color: @brownBackground;
color: @brownTextColor;
box-shadow: @brownBoxShadow;
}
.ui.brown.message .header {
color: @brownHeaderColor;
}
/*--------------
Sizes
---------------*/
.ui.mini.message {
font-size: @relativeMini;
}
.ui.tiny.message {
font-size: @relativeTiny;
}
.ui.small.message {
font-size: @relativeSmall;
}
.ui.message {
font-size: @relativeMedium;
}
.ui.large.message {
font-size: @relativeLarge;
}
.ui.big.message {
font-size: @relativeBig;
}
.ui.huge.message {
font-size: @relativeHuge;
}
.ui.massive.message {
font-size: @relativeMassive;
}
.loadUIOverrides();

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,143 @@
/*!
* # Semantic UI - Container
* http://github.com/semantic-org/semantic-ui/
*
*
* Released under the MIT license
* http://opensource.org/licenses/MIT
*
*/
/*******************************
Theme
*******************************/
@type : 'element';
@element : 'container';
@import (multiple) '../../theme.config';
/*******************************
Container
*******************************/
/* All Sizes */
.ui.container {
display: block;
max-width: @maxWidth !important;
}
/* Mobile */
@media only screen and (max-width: @largestMobileScreen) {
.ui.container {
width: @mobileWidth !important;
margin-left: @mobileGutter !important;
margin-right: @mobileGutter !important;
}
.ui.grid.container {
width: @mobileGridWidth !important;
}
.ui.relaxed.grid.container {
width: @mobileRelaxedGridWidth !important;
}
.ui.very.relaxed.grid.container {
width: @mobileVeryRelaxedGridWidth !important;
}
}
/* Tablet */
@media only screen and (min-width: @tabletBreakpoint) and (max-width: @largestTabletScreen) {
.ui.container {
width: @tabletWidth;
margin-left: @tabletGutter !important;
margin-right: @tabletGutter !important;
}
.ui.grid.container {
width: @tabletGridWidth !important;
}
.ui.relaxed.grid.container {
width: @tabletRelaxedGridWidth !important;
}
.ui.very.relaxed.grid.container {
width: @tabletVeryRelaxedGridWidth !important;
}
}
/* Small Monitor */
@media only screen and (min-width: @computerBreakpoint) and (max-width: @largestSmallMonitor) {
.ui.container {
width: @computerWidth;
margin-left: @computerGutter !important;
margin-right: @computerGutter !important;
}
.ui.grid.container {
width: @computerGridWidth !important;
}
.ui.relaxed.grid.container {
width: @computerRelaxedGridWidth !important;
}
.ui.very.relaxed.grid.container {
width: @computerVeryRelaxedGridWidth !important;
}
}
/* Large Monitor */
@media only screen and (min-width: @largeMonitorBreakpoint) {
.ui.container {
width: @largeMonitorWidth;
margin-left: @largeMonitorGutter !important;
margin-right: @largeMonitorGutter !important;
}
.ui.grid.container {
width: @largeMonitorGridWidth !important;
}
.ui.relaxed.grid.container {
width: @largeMonitorRelaxedGridWidth !important;
}
.ui.very.relaxed.grid.container {
width: @largeMonitorVeryRelaxedGridWidth !important;
}
}
/*******************************
Types
*******************************/
/* Text Container */
.ui.text.container {
font-family: @textFontFamily;
max-width: @textWidth !important;
line-height: @textLineHeight;
}
.ui.text.container {
font-size: @textSize;
}
/* Fluid */
.ui.fluid.container {
width: 100%;
}
/*******************************
Variations
*******************************/
.ui[class*="left aligned"].container {
text-align: left;
}
.ui[class*="center aligned"].container {
text-align: center;
}
.ui[class*="right aligned"].container {
text-align: right;
}
.ui.justified.container {
text-align: justify;
hyphens: auto;
}
.loadUIOverrides();

Просмотреть файл

@ -0,0 +1,255 @@
/*!
* # Semantic UI - Divider
* http://github.com/semantic-org/semantic-ui/
*
*
* Released under the MIT license
* http://opensource.org/licenses/MIT
*
*/
/*******************************
Theme
*******************************/
@type : 'element';
@element : 'divider';
@import (multiple) '../../theme.config';
/*******************************
Divider
*******************************/
.ui.divider {
margin: @margin;
line-height: 1;
height: 0em;
font-weight: @fontWeight;
text-transform: @textTransform;
letter-spacing: @letterSpacing;
color: @color;
user-select: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
/*--------------
Basic
---------------*/
.ui.divider:not(.vertical):not(.horizontal) {
border-top: @shadowWidth solid @shadowColor;
border-bottom: @highlightWidth solid @highlightColor;
}
/*--------------
Coupling
---------------*/
/* Allow divider between each column row */
.ui.grid > .column + .divider,
.ui.grid > .row > .column + .divider {
left: auto;
}
/*--------------
Horizontal
---------------*/
.ui.horizontal.divider {
display: table;
white-space: nowrap;
height: auto;
margin: @horizontalMargin;
line-height: 1;
text-align: center;
}
.ui.horizontal.divider:before,
.ui.horizontal.divider:after {
content: '';
display: table-cell;
position: relative;
top: 50%;
width: 50%;
background-repeat: no-repeat;
}
.ui.horizontal.divider:before {
background-position: right @horizontalDividerMargin top 50%;
}
.ui.horizontal.divider:after {
background-position: left @horizontalDividerMargin top 50%;
}
/*--------------
Vertical
---------------*/
.ui.vertical.divider {
position: absolute;
z-index: 2;
top: 50%;
left: 50%;
margin: 0rem;
padding: 0em;
width: auto;
height: 50%;
line-height: 0em;
text-align: center;
transform: translateX(-50%);
}
.ui.vertical.divider:before,
.ui.vertical.divider:after {
position: absolute;
left: 50%;
content: '';
z-index: 3;
border-left: @shadowWidth solid @shadowColor;
border-right: @highlightWidth solid @highlightColor;
width: 0%;
height: @verticalDividerHeight;
}
.ui.vertical.divider:before {
top: -100%;
}
.ui.vertical.divider:after {
top: auto;
bottom: 0px;
}
/* Inside grid */
@media only screen and (max-width : @largestMobileScreen) {
.ui.stackable.grid .ui.vertical.divider,
.ui.grid .stackable.row .ui.vertical.divider {
display: table;
white-space: nowrap;
height: auto;
margin: @horizontalMargin;
overflow: hidden;
line-height: 1;
text-align: center;
position: static;
top: 0;
left: 0;
transform: none;
}
.ui.stackable.grid .ui.vertical.divider:before,
.ui.grid .stackable.row .ui.vertical.divider:before,
.ui.stackable.grid .ui.vertical.divider:after,
.ui.grid .stackable.row .ui.vertical.divider:after {
position: static;
left: 0;
border-left: none;
border-right: none;
content: '';
display: table-cell;
position: relative;
top: 50%;
width: 50%;
background-repeat: no-repeat;
}
.ui.stackable.grid .ui.vertical.divider:before,
.ui.grid .stackable.row .ui.vertical.divider:before {
background-position: right @horizontalDividerMargin top 50%;
}
.ui.stackable.grid .ui.vertical.divider:after,
.ui.grid .stackable.row .ui.vertical.divider:after {
background-position: left @horizontalDividerMargin top 50%;
}
}
/*--------------
Icon
---------------*/
.ui.divider > .icon {
margin: @dividerIconMargin;
font-size: @dividerIconSize;
height: 1em;
vertical-align: middle;
}
/*******************************
Variations
*******************************/
/*--------------
Hidden
---------------*/
.ui.hidden.divider {
border-color: transparent !important;
}
.ui.hidden.divider:before,
.ui.hidden.divider:after {
display: none;
}
/*--------------
Inverted
---------------*/
.ui.divider.inverted,
.ui.vertical.inverted.divider,
.ui.horizontal.inverted.divider {
color: @invertedTextColor;
}
.ui.divider.inverted,
.ui.divider.inverted:after,
.ui.divider.inverted:before {
border-top-color: @invertedShadowColor !important;
border-left-color: @invertedShadowColor !important;
border-bottom-color: @invertedHighlightColor !important;
border-right-color: @invertedHighlightColor !important;
}
/*--------------
Fitted
---------------*/
.ui.fitted.divider {
margin: 0em;
}
/*--------------
Clearing
---------------*/
.ui.clearing.divider {
clear: both;
}
/*--------------
Section
---------------*/
.ui.section.divider {
margin-top: @sectionMargin;
margin-bottom: @sectionMargin;
}
/*--------------
Sizes
---------------*/
.ui.divider {
font-size: @medium;
}
.loadUIOverrides();

Просмотреть файл

@ -0,0 +1,52 @@
/*!
* # Semantic UI - Flag
* http://github.com/semantic-org/semantic-ui/
*
*
* Released under the MIT license
* http://opensource.org/licenses/MIT
*
*/
/*******************************
Theme
*******************************/
@type : 'element';
@element : 'flag';
@import (multiple) '../../theme.config';
/*******************************
Flag
*******************************/
i.flag:not(.icon) {
display: inline-block;
width: @width;
height: @height;
line-height: @height;
vertical-align: @verticalAlign;
margin: 0em @margin 0em 0em;
text-decoration: inherit;
speak: none;
font-smoothing: antialiased;
backface-visibility: hidden;
}
/* Sprite */
i.flag:not(.icon):before {
display: inline-block;
content: '';
background: url(@spritePath) no-repeat -108px -1976px;
width: @width;
height: @height;
}
.loadUIOverrides();

Просмотреть файл

@ -0,0 +1,708 @@
/*!
* # Semantic UI - Header
* http://github.com/semantic-org/semantic-ui/
*
*
* Released under the MIT license
* http://opensource.org/licenses/MIT
*
*/
/*******************************
Theme
*******************************/
@type : 'element';
@element : 'header';
@import (multiple) '../../theme.config';
/*******************************
Header
*******************************/
/* Standard */
.ui.header {
border: none;
margin: @margin;
padding: @verticalPadding @horizontalPadding;
font-family: @fontFamily;
font-weight: @fontWeight;
line-height: @lineHeight;
text-transform: @textTransform;
color: @textColor;
}
.ui.header:first-child {
margin-top: @firstMargin;
}
.ui.header:last-child {
margin-bottom: @lastMargin;
}
/*--------------
Sub Header
---------------*/
.ui.header .sub.header {
display: block;
font-weight: @normal;
padding: 0em;
margin: @subHeaderMargin;
font-size: @subHeaderFontSize;
line-height: @subHeaderLineHeight;
color: @subHeaderColor;
}
/*--------------
Icon
---------------*/
.ui.header > .icon {
display: table-cell;
opacity: @iconOpacity;
font-size: @iconSize;
padding-top: @iconOffset;
vertical-align: @iconAlignment;
}
/* With Text Node */
.ui.header .icon:only-child {
display: inline-block;
padding: 0em;
margin-right: @iconMargin;
}
/*-------------------
Image
--------------------*/
.ui.header > .image:not(.icon),
.ui.header > img {
display: inline-block;
margin-top: @imageOffset;
width: @imageWidth;
height: @imageHeight;
vertical-align: @imageAlignment;
}
.ui.header > .image:not(.icon):only-child,
.ui.header > img:only-child {
margin-right: @imageMargin;
}
/*--------------
Content
---------------*/
.ui.header .content {
display: inline-block;
vertical-align: @contentAlignment;
}
/* After Image */
.ui.header > img + .content,
.ui.header > .image + .content {
padding-left: @imageMargin;
vertical-align: @contentImageAlignment;
}
/* After Icon */
.ui.header > .icon + .content {
padding-left: @iconMargin;
display: table-cell;
vertical-align: @contentIconAlignment;
}
/*--------------
Loose Coupling
---------------*/
.ui.header .ui.label {
font-size: @labelSize;
margin-left: @labelDistance;
vertical-align: @labelVerticalAlign;
}
/* Positioning */
.ui.header + p {
margin-top: @nextParagraphDistance;
}
/*******************************
Types
*******************************/
/*--------------
Page
---------------*/
h1.ui.header {
font-size: @h1;
}
h2.ui.header {
font-size: @h2;
}
h3.ui.header {
font-size: @h3;
}
h4.ui.header {
font-size: @h4;
}
h5.ui.header {
font-size: @h5;
}
/* Sub Header */
h1.ui.header .sub.header {
font-size: @h1SubHeaderFontSize;
}
h2.ui.header .sub.header {
font-size: @h2SubHeaderFontSize;
}
h3.ui.header .sub.header {
font-size: @h3SubHeaderFontSize;
}
h4.ui.header .sub.header {
font-size: @h4SubHeaderFontSize;
}
h5.ui.header .sub.header {
font-size: @h5SubHeaderFontSize;
}
/*--------------
Content Heading
---------------*/
.ui.huge.header {
min-height: 1em;
font-size: @hugeFontSize;
}
.ui.large.header {
font-size: @largeFontSize;
}
.ui.medium.header {
font-size: @mediumFontSize;
}
.ui.small.header {
font-size: @smallFontSize;
}
.ui.tiny.header {
font-size: @tinyFontSize;
}
/* Sub Header */
.ui.huge.header .sub.header {
font-size: @hugeSubHeaderFontSize;
}
.ui.large.header .sub.header {
font-size: @hugeSubHeaderFontSize;
}
.ui.header .sub.header {
font-size: @subHeaderFontSize;
}
.ui.small.header .sub.header {
font-size: @smallSubHeaderFontSize;
}
.ui.tiny.header .sub.header {
font-size: @tinySubHeaderFontSize;
}
/*--------------
Sub Heading
---------------*/
.ui.sub.header {
padding: 0em;
margin-bottom: @subHeadingDistance;
font-weight: @subHeadingFontWeight;
font-size: @subHeadingFontSize;
text-transform: @subHeadingTextTransform;
color: @subHeadingColor;
}
.ui.small.sub.header {
font-size: @smallSubHeadingSize;
}
.ui.sub.header {
font-size: @subHeadingFontSize;
}
.ui.large.sub.header {
font-size: @largeSubHeadingSize;
}
.ui.huge.sub.header {
font-size: @hugeSubHeadingSize;
}
/*-------------------
Icon
--------------------*/
.ui.icon.header {
display: inline-block;
text-align: center;
margin: @iconHeaderTopMargin 0em @iconHeaderBottomMargin;
}
.ui.icon.header:after {
content: '';
display: block;
height: 0px;
clear: both;
visibility: hidden;
}
.ui.icon.header:first-child {
margin-top: @iconHeaderFirstMargin;
}
.ui.icon.header .icon {
float: none;
display: block;
width: auto;
height: auto;
line-height: 1;
padding: 0em;
font-size: @iconHeaderSize;
margin: 0em auto @iconHeaderMargin;
opacity: @iconHeaderOpacity;
}
.ui.icon.header .content {
display: block;
padding: 0em;
}
.ui.icon.header .circular.icon {
font-size: @circularHeaderIconSize;
}
.ui.icon.header .square.icon {
font-size: @squareHeaderIconSize;
}
.ui.block.icon.header .icon {
margin-bottom: 0em;
}
.ui.icon.header.aligned {
margin-left: auto;
margin-right: auto;
display: block;
}
/*******************************
States
*******************************/
.ui.disabled.header {
opacity: @disabledOpacity;
}
/*******************************
Variations
*******************************/
/*-------------------
Inverted
--------------------*/
.ui.inverted.header {
color: @invertedColor;
}
.ui.inverted.header .sub.header {
color: @invertedSubHeaderColor;
}
.ui.inverted.attached.header {
background: @invertedAttachedBackground;
box-shadow: none;
border-color: transparent;
}
.ui.inverted.block.header {
background: @invertedBlockBackground;
box-shadow: none;
}
.ui.inverted.block.header {
border-bottom: none;
}
/*-------------------
Colors
--------------------*/
/*--- Red ---*/
.ui.red.header {
color: @red !important;
}
a.ui.red.header:hover {
color: @redHover !important;
}
.ui.red.dividing.header {
border-bottom: @dividedColoredBorderWidth solid @red;
}
/* Inverted */
.ui.inverted.red.header {
color: @lightRed !important;
}
a.ui.inverted.red.header:hover {
color: @lightRedHover !important;
}
/*--- Orange ---*/
.ui.orange.header {
color: @orange !important;
}
a.ui.orange.header:hover {
color: @orangeHover !important;
}
.ui.orange.dividing.header {
border-bottom: @dividedColoredBorderWidth solid @orange;
}
/* Inverted */
.ui.inverted.orange.header {
color: @lightOrange !important;
}
a.ui.inverted.orange.header:hover {
color: @lightOrangeHover !important;
}
/*--- Olive ---*/
.ui.olive.header {
color: @olive !important;
}
a.ui.olive.header:hover {
color: @oliveHover !important;
}
.ui.olive.dividing.header {
border-bottom: @dividedColoredBorderWidth solid @olive;
}
/* Inverted */
.ui.inverted.olive.header {
color: @lightOlive !important;
}
a.ui.inverted.olive.header:hover {
color: @lightOliveHover !important;
}
/*--- Yellow ---*/
.ui.yellow.header {
color: @yellow !important;
}
a.ui.yellow.header:hover {
color: @yellowHover !important;
}
.ui.yellow.dividing.header {
border-bottom: @dividedColoredBorderWidth solid @yellow;
}
/* Inverted */
.ui.inverted.yellow.header {
color: @lightYellow !important;
}
a.ui.inverted.yellow.header:hover {
color: @lightYellowHover !important;
}
/*--- Green ---*/
.ui.green.header {
color: @green !important;
}
a.ui.green.header:hover {
color: @greenHover !important;
}
.ui.green.dividing.header {
border-bottom: @dividedColoredBorderWidth solid @green;
}
/* Inverted */
.ui.inverted.green.header {
color: @lightGreen !important;
}
a.ui.inverted.green.header:hover {
color: @lightGreenHover !important;
}
/*--- Teal ---*/
.ui.teal.header {
color: @teal !important;
}
a.ui.teal.header:hover {
color: @tealHover !important;
}
.ui.teal.dividing.header {
border-bottom: @dividedColoredBorderWidth solid @teal;
}
/* Inverted */
.ui.inverted.teal.header {
color: @lightTeal !important;
}
a.ui.inverted.teal.header:hover {
color: @lightTealHover !important;
}
/*--- Blue ---*/
.ui.blue.header {
color: @blue !important;
}
a.ui.blue.header:hover {
color: @blueHover !important;
}
.ui.blue.dividing.header {
border-bottom: @dividedColoredBorderWidth solid @blue;
}
/* Inverted */
.ui.inverted.blue.header {
color: @lightBlue !important;
}
a.ui.inverted.blue.header:hover {
color: @lightBlueHover !important;
}
/*--- Violet ---*/
.ui.violet.header {
color: @violet !important;
}
a.ui.violet.header:hover {
color: @violetHover !important;
}
.ui.violet.dividing.header {
border-bottom: @dividedColoredBorderWidth solid @violet;
}
/* Inverted */
.ui.inverted.violet.header {
color: @lightViolet !important;
}
a.ui.inverted.violet.header:hover {
color: @lightVioletHover !important;
}
/*--- Purple ---*/
.ui.purple.header {
color: @purple !important;
}
a.ui.purple.header:hover {
color: @purpleHover !important;
}
.ui.purple.dividing.header {
border-bottom: @dividedColoredBorderWidth solid @purple;
}
/* Inverted */
.ui.inverted.purple.header {
color: @lightPurple !important;
}
a.ui.inverted.purple.header:hover {
color: @lightPurpleHover !important;
}
/*--- Pink ---*/
.ui.pink.header {
color: @pink !important;
}
a.ui.pink.header:hover {
color: @pinkHover !important;
}
.ui.pink.dividing.header {
border-bottom: @dividedColoredBorderWidth solid @pink;
}
/* Inverted */
.ui.inverted.pink.header {
color: @lightPink !important;
}
a.ui.inverted.pink.header:hover {
color: @lightPinkHover !important;
}
/*--- Brown ---*/
.ui.brown.header {
color: @brown !important;
}
a.ui.brown.header:hover {
color: @brownHover !important;
}
.ui.brown.dividing.header {
border-bottom: @dividedColoredBorderWidth solid @brown;
}
/* Inverted */
.ui.inverted.brown.header {
color: @lightBrown !important;
}
a.ui.inverted.brown.header:hover {
color: @lightBrownHover !important;
}
/*--- Grey ---*/
.ui.grey.header {
color: @grey !important;
}
a.ui.grey.header:hover {
color: @greyHover !important;
}
.ui.grey.dividing.header {
border-bottom: @dividedColoredBorderWidth solid @grey;
}
/* Inverted */
.ui.inverted.grey.header {
color: @lightGrey !important;
}
a.ui.inverted.grey.header:hover {
color: @lightGreyHover !important;
}
/*-------------------
Aligned
--------------------*/
.ui.left.aligned.header {
text-align: left;
}
.ui.right.aligned.header {
text-align: right;
}
.ui.centered.header,
.ui.center.aligned.header {
text-align: center;
}
.ui.justified.header {
text-align: justify;
}
.ui.justified.header:after {
display: inline-block;
content: '';
width: 100%;
}
/*-------------------
Floated
--------------------*/
.ui.floated.header,
.ui[class*="left floated"].header {
float: left;
margin-top: 0em;
margin-right: @floatedMargin;
}
.ui[class*="right floated"].header {
float: right;
margin-top: 0em;
margin-left: @floatedMargin;
}
/*-------------------
Fitted
--------------------*/
.ui.fitted.header {
padding: 0em;
}
/*-------------------
Dividing
--------------------*/
.ui.dividing.header {
padding-bottom: @dividedBorderPadding;
border-bottom: @dividedBorder;
}
.ui.dividing.header .sub.header {
padding-bottom: @dividedSubHeaderPadding;
}
.ui.dividing.header .icon {
margin-bottom: @dividedIconPadding;
}
.ui.inverted.dividing.header {
border-bottom-color: @invertedDividedBorderColor;
}
/*-------------------
Block
--------------------*/
.ui.block.header {
background: @blockBackground;
padding: @blockVerticalPadding @blockHorizontalPadding;
box-shadow: @blockBoxShadow;
border: @blockBorder;
border-radius: @blockBorderRadius;
}
.ui.tiny.block.header {
font-size: @tinyBlock;
}
.ui.small.block.header {
font-size: @smallBlock;
}
.ui.block.header:not(h1):not(h2):not(h3):not(h4):not(h5):not(h6) {
font-size: @mediumBlock;
}
.ui.large.block.header {
font-size: @largeBlock;
}
.ui.huge.block.header {
font-size: @hugeBlock;
}
/*-------------------
Attached
--------------------*/
.ui.attached.header {
background: @attachedBackground;
padding: @attachedVerticalPadding @attachedHorizontalPadding;
margin-left: @attachedOffset;
margin-right: @attachedOffset;
box-shadow: @attachedBoxShadow;
border: @attachedBorder;
}
.ui.attached.block.header {
background: @blockBackground;
}
.ui.attached:not(.top):not(.bottom).header {
margin-top: 0em;
margin-bottom: 0em;
border-top: none;
border-radius: 0em;
}
.ui.top.attached.header {
margin-bottom: 0em;
border-radius: @attachedBorderRadius @attachedBorderRadius 0em 0em;
}
.ui.bottom.attached.header {
margin-top: 0em;
border-top: none;
border-radius: 0em 0em @attachedBorderRadius @attachedBorderRadius;
}
/* Attached Sizes */
.ui.tiny.attached.header {
font-size: @tinyAttachedSize;
}
.ui.small.attached.header {
font-size: @smallAttachedSize;
}
.ui.attached.header:not(h1):not(h2):not(h3):not(h4):not(h5):not(h6) {
font-size: @mediumAttachedSize;
}
.ui.large.attached.header {
font-size: @largeAttachedSize;
}
.ui.huge.attached.header {
font-size: @hugeAttachedSize;
}
/*-------------------
Sizing
--------------------*/
.ui.header:not(h1):not(h2):not(h3):not(h4):not(h5):not(h6) {
font-size: @mediumFontSize;
}
.loadUIOverrides();

Просмотреть файл

@ -0,0 +1,501 @@
/*!
* # Semantic UI - Icon
* http://github.com/semantic-org/semantic-ui/
*
*
* Released under the MIT license
* http://opensource.org/licenses/MIT
*
*/
/*******************************
Theme
*******************************/
@type : 'element';
@element : 'icon';
@import (multiple) '../../theme.config';
/*******************************
Icon
*******************************/
@font-face {
font-family: 'Icons';
src: @fallbackSRC;
src: @src;
font-style: normal;
font-weight: @normal;
font-variant: normal;
text-decoration: inherit;
text-transform: none;
}
i.icon {
display: inline-block;
opacity: @opacity;
margin: 0em @distanceFromText 0em 0em;
width: @width;
height: @height;
font-family: 'Icons';
font-style: normal;
font-weight: @normal;
text-decoration: inherit;
text-align: center;
speak: none;
font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
backface-visibility: hidden;
}
i.icon:before {
background: none !important;
}
/*******************************
Types
*******************************/
/*--------------
Loading
---------------*/
i.icon.loading {
height: 1em;
line-height: 1;
animation: icon-loading @loadingDuration linear infinite;
}
@keyframes icon-loading {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
/*******************************
States
*******************************/
i.icon.hover {
opacity: 1 !important;
}
i.icon.active {
opacity: 1 !important;
}
i.emphasized.icon {
opacity: 1 !important;
}
i.disabled.icon {
opacity: @disabledOpacity !important;
}
/*******************************
Variations
*******************************/
/*-------------------
Fitted
--------------------*/
i.fitted.icon {
width: auto;
margin: 0em !important;
}
/*-------------------
Link
--------------------*/
i.link.icon, i.link.icons {
cursor: pointer;
opacity: @linkOpacity;
transition: opacity @defaultDuration @defaultEasing;
}
i.link.icon:hover, i.link.icons:hover {
opacity: 1 !important;
}
/*-------------------
Circular
--------------------*/
i.circular.icon {
border-radius: 500em !important;
line-height: 1 !important;
padding: @circularPadding !important;
box-shadow: @circularShadow;
width: @circularSize !important;
height: @circularSize !important;
}
i.circular.inverted.icon {
border: none;
box-shadow: none;
}
/*-------------------
Flipped
--------------------*/
i.flipped.icon,
i.horizontally.flipped.icon {
transform: scale(-1, 1);
}
i.vertically.flipped.icon {
transform: scale(1, -1);
}
/*-------------------
Rotated
--------------------*/
i.rotated.icon,
i.right.rotated.icon,
i.clockwise.rotated.icon {
transform: rotate(90deg);
}
i.left.rotated.icon,
i.counterclockwise.rotated.icon {
transform: rotate(-90deg);
}
/*-------------------
Bordered
--------------------*/
i.bordered.icon {
line-height: 1;
vertical-align: baseline;
width: @borderedSize;
height: @borderedSize;
padding: @borderedVerticalPadding @borderedHorizontalPadding !important;
box-shadow: @borderedShadow;
}
i.bordered.inverted.icon {
border: none;
box-shadow: none;
}
/*-------------------
Inverted
--------------------*/
/* Inverted Shapes */
i.inverted.bordered.icon,
i.inverted.circular.icon {
background-color: @black !important;
color: @white !important;
}
i.inverted.icon {
color: @white;
}
/*-------------------
Colors
--------------------*/
/* Red */
i.red.icon {
color: @red !important;
}
i.inverted.red.icon {
color: @lightRed !important;
}
i.inverted.bordered.red.icon,
i.inverted.circular.red.icon {
background-color: @red !important;
color: @white !important;
}
/* Orange */
i.orange.icon {
color: @orange !important;
}
i.inverted.orange.icon {
color: @lightOrange !important;
}
i.inverted.bordered.orange.icon,
i.inverted.circular.orange.icon {
background-color: @orange !important;
color: @white !important;
}
/* Yellow */
i.yellow.icon {
color: @yellow !important;
}
i.inverted.yellow.icon {
color: @lightYellow !important;
}
i.inverted.bordered.yellow.icon,
i.inverted.circular.yellow.icon {
background-color: @yellow !important;
color: @white !important;
}
/* Olive */
i.olive.icon {
color: @olive !important;
}
i.inverted.olive.icon {
color: @lightOlive !important;
}
i.inverted.bordered.olive.icon,
i.inverted.circular.olive.icon {
background-color: @olive !important;
color: @white !important;
}
/* Green */
i.green.icon {
color: @green !important;
}
i.inverted.green.icon {
color: @lightGreen !important;
}
i.inverted.bordered.green.icon,
i.inverted.circular.green.icon {
background-color: @green !important;
color: @white !important;
}
/* Teal */
i.teal.icon {
color: @teal !important;
}
i.inverted.teal.icon {
color: @lightTeal !important;
}
i.inverted.bordered.teal.icon,
i.inverted.circular.teal.icon {
background-color: @teal !important;
color: @white !important;
}
/* Blue */
i.blue.icon {
color: @blue !important;
}
i.inverted.blue.icon {
color: @lightBlue !important;
}
i.inverted.bordered.blue.icon,
i.inverted.circular.blue.icon {
background-color: @blue !important;
color: @white !important;
}
/* Violet */
i.violet.icon {
color: @violet !important;
}
i.inverted.violet.icon {
color: @lightViolet !important;
}
i.inverted.bordered.violet.icon,
i.inverted.circular.violet.icon {
background-color: @violet !important;
color: @white !important;
}
/* Purple */
i.purple.icon {
color: @purple !important;
}
i.inverted.purple.icon {
color: @lightPurple !important;
}
i.inverted.bordered.purple.icon,
i.inverted.circular.purple.icon {
background-color: @purple !important;
color: @white !important;
}
/* Pink */
i.pink.icon {
color: @pink !important;
}
i.inverted.pink.icon {
color: @lightPink !important;
}
i.inverted.bordered.pink.icon,
i.inverted.circular.pink.icon {
background-color: @pink !important;
color: @white !important;
}
/* Brown */
i.brown.icon {
color: @brown !important;
}
i.inverted.brown.icon {
color: @lightBrown !important;
}
i.inverted.bordered.brown.icon,
i.inverted.circular.brown.icon {
background-color: @brown !important;
color: @white !important;
}
/* Grey */
i.grey.icon {
color: @grey !important;
}
i.inverted.grey.icon {
color: @lightGrey !important;
}
i.inverted.bordered.grey.icon,
i.inverted.circular.grey.icon {
background-color: @grey !important;
color: @white !important;
}
/* Black */
i.black.icon {
color: @black !important;
}
i.inverted.black.icon {
color: @lightBlack !important;
}
i.inverted.bordered.black.icon,
i.inverted.circular.black.icon {
background-color: @black !important;
color: @white !important;
}
/*-------------------
Sizes
--------------------*/
i.mini.icon,
i.mini.icons {
line-height: 1;
font-size: @mini;
}
i.tiny.icon,
i.tiny.icons {
line-height: 1;
font-size: @tiny;
}
i.small.icon,
i.small.icons {
line-height: 1;
font-size: @small;
}
i.icon,
i.icons {
font-size: @medium;
}
i.large.icon,
i.large.icons {
line-height: 1;
vertical-align: middle;
font-size: @large;
}
i.big.icon,
i.big.icons {
line-height: 1;
vertical-align: middle;
font-size: @big;
}
i.huge.icon,
i.huge.icons {
line-height: 1;
vertical-align: middle;
font-size: @huge;
}
i.massive.icon,
i.massive.icons {
line-height: 1;
vertical-align: middle;
font-size: @massive;
}
/*******************************
Groups
*******************************/
i.icons {
display: inline-block;
position: relative;
line-height: 1;
}
i.icons .icon {
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
margin: 0em;
margin: 0;
}
i.icons .icon:first-child {
position: static;
width: auto;
height: auto;
vertical-align: top;
transform: none;
margin-right: @distanceFromText;
}
/* Corner Icon */
i.icons .corner.icon {
top: auto;
left: auto;
right: 0;
bottom: 0;
transform: none;
font-size: @cornerIconSize;
text-shadow: @cornerIconShadow;
}
i.icons .top.right.corner.icon {
top: 0;
left: auto;
right: 0;
bottom: auto;
}
i.icons .top.left.corner.icon {
top: 0;
left: 0;
right: auto;
bottom: auto;
}
i.icons .bottom.left.corner.icon {
top: auto;
left: 0;
right: auto;
bottom: 0;
}
i.icons .bottom.right.corner.icon {
top: auto;
left: auto;
right: 0;
bottom: 0;
}
i.icons .inverted.corner.icon {
text-shadow: @cornerIconInvertedShadow;
}
.loadUIOverrides();

Просмотреть файл

@ -0,0 +1,328 @@
/*!
* # Semantic UI - Image
* http://github.com/semantic-org/semantic-ui/
*
*
* Released under the MIT license
* http://opensource.org/licenses/MIT
*
*/
/*******************************
Theme
*******************************/
@type : 'element';
@element : 'image';
@import (multiple) '../../theme.config';
/*******************************
Image
*******************************/
.ui.image {
position: relative;
display: inline-block;
vertical-align: middle;
max-width: 100%;
background-color: @placeholderColor;
}
img.ui.image {
display: block;
}
.ui.image svg,
.ui.image img {
display: block;
max-width: 100%;
height: auto;
}
/*******************************
States
*******************************/
.ui.hidden.images,
.ui.hidden.image {
display: none;
}
.ui.hidden.transition.images,
.ui.hidden.transition.image {
display: block;
visibility: hidden;
}
.ui.images > .hidden.transition {
display: inline-block;
visibility: hidden;
}
.ui.disabled.images,
.ui.disabled.image {
cursor: default;
opacity: @disabledOpacity;
}
/*******************************
Variations
*******************************/
/*--------------
Inline
---------------*/
.ui.inline.image,
.ui.inline.image svg,
.ui.inline.image img {
display: inline-block;
}
/*------------------
Vertical Aligned
-------------------*/
.ui.top.aligned.images .image,
.ui.top.aligned.image,
.ui.top.aligned.image svg,
.ui.top.aligned.image img {
display: inline-block;
vertical-align: top;
}
.ui.middle.aligned.images .image,
.ui.middle.aligned.image,
.ui.middle.aligned.image svg,
.ui.middle.aligned.image img {
display: inline-block;
vertical-align: middle;
}
.ui.bottom.aligned.images .image,
.ui.bottom.aligned.image,
.ui.bottom.aligned.image svg,
.ui.bottom.aligned.image img {
display: inline-block;
vertical-align: bottom;
}
/*--------------
Rounded
---------------*/
.ui.rounded.images .image,
.ui.rounded.image,
.ui.rounded.images .image > *,
.ui.rounded.image > * {
border-radius: @roundedBorderRadius;
}
/*--------------
Bordered
---------------*/
.ui.bordered.images .image,
.ui.bordered.images img,
.ui.bordered.images svg,
.ui.bordered.image img,
.ui.bordered.image svg,
img.ui.bordered.image {
border: @imageBorder;
}
/*--------------
Circular
---------------*/
.ui.circular.images,
.ui.circular.image {
overflow: hidden;
}
.ui.circular.images .image,
.ui.circular.image,
.ui.circular.images .image > *,
.ui.circular.image > * {
-webkit-border-radius: @circularRadius;
-moz-border-radius: @circularRadius;
border-radius: @circularRadius;
}
/*--------------
Fluid
---------------*/
.ui.fluid.images,
.ui.fluid.image,
.ui.fluid.images img,
.ui.fluid.images svg,
.ui.fluid.image svg,
.ui.fluid.image img {
display: block;
width: 100%;
height: auto;
}
/*--------------
Avatar
---------------*/
.ui.avatar.images .image,
.ui.avatar.images img,
.ui.avatar.images svg,
.ui.avatar.image img,
.ui.avatar.image svg,
.ui.avatar.image {
margin-right: @avatarMargin;
display: inline-block;
width: @avatarSize;
height: @avatarSize;
-webkit-border-radius: @circularRadius;
-moz-border-radius: @circularRadius;
border-radius: @circularRadius;
}
/*-------------------
Spaced
--------------------*/
.ui.spaced.image {
display: inline-block !important;
margin-left: @spacedDistance;
margin-right: @spacedDistance;
}
.ui[class*="left spaced"].image {
margin-left: @spacedDistance;
margin-right: 0em;
}
.ui[class*="right spaced"].image {
margin-left: 0em;
margin-right: @spacedDistance;
}
/*-------------------
Floated
--------------------*/
.ui.floated.image,
.ui.floated.images {
float: left;
margin-right: @floatedHorizontalMargin;
margin-bottom: @floatedVerticalMargin;
}
.ui.right.floated.images,
.ui.right.floated.image {
float: right;
margin-right: 0em;
margin-bottom: @floatedVerticalMargin;
margin-left: @floatedHorizontalMargin;
}
.ui.floated.images:last-child,
.ui.floated.image:last-child {
margin-bottom: 0em;
}
.ui.centered.images,
.ui.centered.image {
margin-left: auto;
margin-right: auto;
}
/*--------------
Sizes
---------------*/
.ui.mini.images .image,
.ui.mini.images img,
.ui.mini.images svg,
.ui.mini.image {
width: @miniWidth;
height: auto;
font-size: @mini;
}
.ui.tiny.images .image,
.ui.tiny.images img,
.ui.tiny.images svg,
.ui.tiny.image {
width: @tinyWidth;
height: auto;
font-size: @tiny;
}
.ui.small.images .image,
.ui.small.images img,
.ui.small.images svg,
.ui.small.image {
width: @smallWidth;
height: auto;
font-size: @small;
}
.ui.medium.images .image,
.ui.medium.images img,
.ui.medium.images svg,
.ui.medium.image {
width: @mediumWidth;
height: auto;
font-size: @medium;
}
.ui.large.images .image,
.ui.large.images img,
.ui.large.images svg,
.ui.large.image {
width: @largeWidth;
height: auto;
font-size: @large;
}
.ui.big.images .image,
.ui.big.images img,
.ui.big.images svg,
.ui.big.image {
width: @bigWidth;
height: auto;
font-size: @big;
}
.ui.huge.images .image,
.ui.huge.images img,
.ui.huge.images svg,
.ui.huge.image {
width: @hugeWidth;
height: auto;
font-size: @huge;
}
.ui.massive.images .image,
.ui.massive.images img,
.ui.massive.images svg,
.ui.massive.image {
width: @massiveWidth;
height: auto;
font-size: @massive;
}
/*******************************
Groups
*******************************/
.ui.images {
font-size: 0em;
margin: 0em -@imageHorizontalMargin 0rem;
}
.ui.images .image,
.ui.images > img,
.ui.images > svg {
display: inline-block;
margin: 0em @imageHorizontalMargin @imageVerticalMargin;
}
.loadUIOverrides();

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше