From 765589015cb0d069883021d35c26c8048beacd3d Mon Sep 17 00:00:00 2001 From: Ryan Gregg Date: Wed, 1 Aug 2018 16:45:37 -0700 Subject: [PATCH 01/36] Remove space (#305) --- serving/outbound-network-access.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serving/outbound-network-access.md b/serving/outbound-network-access.md index f7588d974..ff8b197a0 100644 --- a/serving/outbound-network-access.md +++ b/serving/outbound-network-access.md @@ -14,7 +14,7 @@ depending on your platform: * For Google Container Engine (GKE) run the following command to determine the scope. Make sure to replace the variables or export these values first. ```shell - gcloud container clusters describe ${CLUSTER_ID} \ + gcloud container clusters describe ${CLUSTER_ID} \ --zone=${GCP_ZONE} | grep -e clusterIpv4Cidr -e servicesIpv4Cidr ``` * For IBM Cloud Private run the following command: From 90b273c7e40eca0cd456c8693d8adb3b5d6f1171 Mon Sep 17 00:00:00 2001 From: Evan Anderson Date: Fri, 3 Aug 2018 11:23:31 -0700 Subject: [PATCH 02/36] Add knative-users as as access option for Team Drive (#313) * Add knative-users as as access option for Team Drive * Un-prettify to make diff reading easier. * Even less pretty. --- community/CONTRIBUTING.md | 15 +++++++++------ community/ROLES.md | 6 ++++-- community/WORKING-GROUPS.md | 7 ++++--- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/community/CONTRIBUTING.md b/community/CONTRIBUTING.md index df07aae0d..056485ed7 100644 --- a/community/CONTRIBUTING.md +++ b/community/CONTRIBUTING.md @@ -58,12 +58,16 @@ to be a [member](ROLES.md#member) of the Knative organization. We do not yet have a common design document template(TODO). The team drive is shared with the +[knative-users@](https://groups.google.com/forum/#!forum/knative-users) and [knative-dev@](https://groups.google.com/forum/#!forum/knative-dev) Google -group for editing and commenting. If you're not part of that group, the -first time you try to access the team drive or a specific doc, you'll be -asked to request permission. This permission will always be granted and we -do our best to grant access as fast as we can, but there is a human involved -there, so please forgive any delays. +groups for reading and editing, respectively. Access to +[knative-users@](https://groups.google.com/forum/#!forum/knative-users) is +unlimited, while +[knative-dev@](https://groups.google.com/forum/#!forum/knative-dev) requires +human review. If you're not part of one of those groups, the first time you try +to access the team drive or a specific doc, you'll be asked to request +permission. Please join one of the above groups (you can join knative-users and +later join knative-dev if you want immediate access). ## Contributing a feature @@ -100,7 +104,6 @@ following steps: * Submit PRs to knative/serving with user documentation for your feature, including usage examples when possible. Add documentation to [knative/docs/serving](https://github.com/knative/docs/tree/master/serving). - *Note that we prefer bite-sized PRs instead of giant monster PRs. It's therefore preferable if you can introduce large features in small, individually-reviewable diff --git a/community/ROLES.md b/community/ROLES.md index d96d1826f..7059fb3c5 100644 --- a/community/ROLES.md +++ b/community/ROLES.md @@ -34,7 +34,7 @@ table describes: Collaborator Casual contributor to the project - n/a + Join [knative-users@](https://groups.google.com/forum/#!forum/knative-users) to get access to the team drive.

Can submit PRs

Commenting permission on the Knative Team drive

@@ -115,7 +115,9 @@ the PR bot. * Working on some contribution to the project that would benefit from the ability to have PRs or Issues to be assigned to the contributor -* Sponsored by 1 member +* Join [knative-users@](https://groups.google.com/forum/#!forum/knative-users) + unrestricted join permissions; this grants read access to documents in the + Team Drive ## Member diff --git a/community/WORKING-GROUPS.md b/community/WORKING-GROUPS.md index 1d59853b4..aa1c349e9 100644 --- a/community/WORKING-GROUPS.md +++ b/community/WORKING-GROUPS.md @@ -13,9 +13,10 @@ procedures. The working groups generate design docs which are kept in a [shared drive](https://drive.google.com/corp/drive/folders/0APnJ_hRs30R2Uk9PVA) and are available for anyone to read and comment on. The shared drive -currently grants edit and comment access to the -[knative-dev@](https://groups.google.com/forum/#!forum/knative-dev) -Google group. +currently grants read access to +[knative-users@](https://groups.google.com/forum/#!forum/knative-users) and edit +and comment access to the +[knative-dev@](https://groups.google.com/forum/#!forum/knative-dev) Google group. The current working groups are: From 9f25f317595aede3548fa8b3fb2df364a621b452 Mon Sep 17 00:00:00 2001 From: Paul Morie Date: Sat, 4 Aug 2018 01:55:10 -0400 Subject: [PATCH 03/36] Add instructions for OpenShift (#310) --- install/Knative-with-OpenShift.md | 212 ++++++++++++++++++++++ install/README.md | 3 +- install/scripts/knative-with-openshift.sh | 94 ++++++++++ 3 files changed, 308 insertions(+), 1 deletion(-) create mode 100644 install/Knative-with-OpenShift.md create mode 100755 install/scripts/knative-with-openshift.sh diff --git a/install/Knative-with-OpenShift.md b/install/Knative-with-OpenShift.md new file mode 100644 index 000000000..db9eaea75 --- /dev/null +++ b/install/Knative-with-OpenShift.md @@ -0,0 +1,212 @@ +# Knative Install on OpenShift + +This guide walks you through the installation of the latest version of [Knative +Serving](https://github.com/knative/serving) on an +[OpenShift](https://github.com/openshift/origin) using pre-built images and +demonstrates creating and deploying an image of a sample "hello world" app onto +the newly created Knative cluster. + +You can find [guides for other platforms here](README.md). + +## Before you begin + +These instructions will run an OpenShift 3.10 (Kubernetes 1.10) cluster on your +local machine using [`oc cluster up`](https://docs.openshift.org/latest/getting_started/administrators.html#running-in-a-docker-container) +to test-drive knative. + +## Install `oc` (openshift cli) + +You can install the latest version of `oc`, the openshift CLI into your local +directory by downloading the right release tarball for your OS from the +[releases page](https://github.com/openshift/origin/releases/tag/v3.10.0). + +```shell +export OS= +curl https://github.com/openshift/origin/releases/download/v3.10.0/openshift-origin-client-tools-v3.10.0-dd10d17-$OS-64bit.tar.gz -o oc.tar.gz +tar zvf oc.tar.gz -x openshift-origin-client-tools-v3.10.0-dd10d17-$OS-64bit/oc --strip=1 + +# You will now have the oc binary in your local directory +``` + +## Scripted cluster setup and installation + +For Linux and Mac, you can optionally run a +[script](scripts/knative-with-openshift.sh) that automates the steps on this +page. + +Once you have `oc` present on your machine and in your `PATH`, you can simply +run [this script](scripts/knative-with-openshift.sh); it will: + +- Create a new OpenShift cluster on your local machine with `oc cluster up` +- Install Istio and Knative serving +- Log you in as the cluster administrator +- Set up the default namespace for istio autoinjection + +Once the script completes, you'll be ready to test out Knative! + +## Creating a new OpenShift cluster + +Create a new OpenShift cluster on your local machine using `oc cluster up`: + +```shell +oc cluster up --write-config + +# Enable admission webhooks +sed -i -e 's/"admissionConfig":{"pluginConfig":null}/"admissionConfig": {\ + "pluginConfig": {\ + "ValidatingAdmissionWebhook": {\ + "configuration": {\ + "apiVersion": "v1",\ + "kind": "DefaultAdmissionConfig",\ + "disable": false\ + }\ + },\ + "MutatingAdmissionWebhook": {\ + "configuration": {\ + "apiVersion": "v1",\ + "kind": "DefaultAdmissionConfig",\ + "disable": false\ + }\ + }\ + }\ +}/' openshift.local.clusterup/kube-apiserver/master-config.yaml + +oc cluster up --server-loglevel=5 +``` + +Once the cluster is up, login as the cluster administrator: + +```shell +oc login -u system:admin +``` + +Now, we'll set up the default project for use with Knative. + +```shell +oc project default + +# SCCs (Security Context Constraints) are the precursor to the PSP (Pod +# Security Policy) mechanism in Kubernetes. +oc adm policy add-scc-to-user privileged -z default -n default + +oc label namespace default istio-injection=enabled +``` + +## Installing Istio + +Knative depends on Istio. First, run the following to grant the necessary +privileges to the service accounts istio will use: + +```shell +oc adm policy add-scc-to-user anyuid -z istio-ingress-service-account -n istio-system +oc adm policy add-scc-to-user anyuid -z default -n istio-system +oc adm policy add-scc-to-user anyuid -z prometheus -n istio-system +oc adm policy add-scc-to-user anyuid -z istio-egressgateway-service-account -n istio-system +oc adm policy add-scc-to-user anyuid -z istio-citadel-service-account -n istio-system +oc adm policy add-scc-to-user anyuid -z istio-ingressgateway-service-account -n istio-system +oc adm policy add-scc-to-user anyuid -z istio-cleanup-old-ca-service-account -n istio-system +oc adm policy add-scc-to-user anyuid -z istio-mixer-post-install-account -n istio-system +oc adm policy add-scc-to-user anyuid -z istio-mixer-service-account -n istio-system +oc adm policy add-scc-to-user anyuid -z istio-pilot-service-account -n istio-system +oc adm policy add-scc-to-user anyuid -z istio-sidecar-injector-service-account -n istio-system +oc adm policy add-cluster-role-to-user cluster-admin -z istio-galley-service-account -n istio-system +``` + +Run the following to install Istio: + +```shell +curl -L https://storage.googleapis.com/knative-releases/serving/latest/istio.yaml \ + | sed 's/LoadBalancer/NodePort/' \ + | oc apply -f - +``` + +Monitor the Istio components until all of the components show a `STATUS` of +`Running` or `Completed`: + +```shell +oc get pods -n istio-system +``` + +It will take a few minutes for all the components to be up and running; you can +rerun the command to see the current status. + +> Note: Instead of rerunning the command, you can add `--watch` to the above + command to view the component's status updates in real time. Use CTRL+C to exit watch mode. + +## Installing Knative Serving + +Next, we'll install [Knative Serving](https://github.com/knative/serving). + +First, run the following to grant the necessary privileges to the service +accounts istio will use: + +```shell +oc adm policy add-scc-to-user anyuid -z build-controller -n knative-build +oc adm policy add-scc-to-user anyuid -z controller -n knative-serving +oc adm policy add-scc-to-user anyuid -z autoscaler -n knative-serving +oc adm policy add-scc-to-user anyuid -z kube-state-metrics -n monitoring +oc adm policy add-scc-to-user anyuid -z node-exporter -n monitoring +oc adm policy add-scc-to-user anyuid -z prometheus-system -n monitoring +oc adm policy add-cluster-role-to-user cluster-admin -z build-controller -n knative-build +oc adm policy add-cluster-role-to-user cluster-admin -z controller -n knative-serving +``` + +Next, install Knative: + +```shell +curl -L https://storage.googleapis.com/knative-releases/serving/latest/release-lite.yaml \ + | sed 's/LoadBalancer/NodePort/' \ + | oc apply -f - +``` + +Monitor the Knative components until all of the components show a `STATUS` of +`Running`: + +```shell +oc get pods -n knative-serving +``` + +Just as with the Istio components, it will take a few seconds for the Knative +components to be up and running; you can rerun the command to see the current status. + +> Note: Instead of rerunning the command, you can add `--watch` to the above + command to view the component's status updates in real time. Use CTRL+C to exit watch mode. + +Now you can deploy an app to your newly created Knative cluster. + +## Deploying an app + +Now that your cluster has Knative installed, you're ready to deploy an app. + +If you'd like to follow a step-by-step guide for deploying your first app on +Knative, check out the +[Getting Started with Knative App Deployment](getting-started-knative-app.md) +guide. + +If you'd like to view the available sample apps and deploy one of your choosing, +head to the [sample apps](../serving/samples/README.md) repo. + +> Note: When looking up the IP address to use for accessing your app, you need to look up + the NodePort for the `knative-ingressgateway` as well as the IP address used for OpenShift. + You can use the following command to look up the value to use for the {IP_ADDRESS} placeholder + used in the samples: + + ```shell + export IP_ADDRESS=$(oc get node -o 'jsonpath={.items[0].status.addresses[0].address}'):$(oc get svc knative-ingressgateway -n istio-system -o 'jsonpath={.spec.ports[?(@.port==80)].nodePort}') + ``` + +## Cleaning up + +Delete your test cluster by running: + +```shell +oc cluster down +rm -rf openshift.local.clusterup +``` + +--- + +Except as otherwise noted, the content of this page is licensed under the +[Creative Commons Attribution 4.0 License](https://creativecommons.org/licenses/by/4.0/), +and code samples are licensed under the +[Apache 2.0 License](https://www.apache.org/licenses/LICENSE-2.0). diff --git a/install/README.md b/install/README.md index 8b4218bdd..8a3c0a53f 100644 --- a/install/README.md +++ b/install/README.md @@ -9,7 +9,7 @@ sure which Kubernetes platform is right for you, see [Picking the Right Solution](https://kubernetes.io/docs/setup/pick-right-solution/). We provide information for installing Knative on -[Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine/docs/), [IBM Cloud Kubernetes Service](https://www.ibm.com/cloud/container-service), [Azure Kubernetes Service](https://docs.microsoft.com/en-us/azure/aks/), [Minikube](https://kubernetes.io/docs/setup/minikube/) and [Pivotal Container Service](https://pivotal.io/platform/pivotal-container-service) clusters. +[Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine/docs/), [IBM Cloud Kubernetes Service](https://www.ibm.com/cloud/container-service), [Azure Kubernetes Service](https://docs.microsoft.com/en-us/azure/aks/), [Minikube](https://kubernetes.io/docs/setup/minikube/), [OpenShift](https://github.com/openshift/origin) and [Pivotal Container Service](https://pivotal.io/platform/pivotal-container-service) clusters. ## Installing Knative @@ -21,6 +21,7 @@ Knative components on the following platforms: * [Knative Install on Google Kubernetes Engine](Knative-with-GKE.md) * [Knative Install on IBM Cloud Kubernetes Service](Knative-with-IKS.md) * [Knative Install on Minikube](Knative-with-Minikube.md) +* [Knative Install on OpenShift](Knative-with-OpenShift.md) * [Knative Install on Pivotal Container Service](Knative-with-PKS.md) If you already have a Kubernetes cluster you're comfortable installing diff --git a/install/scripts/knative-with-openshift.sh b/install/scripts/knative-with-openshift.sh new file mode 100755 index 000000000..7bacbad70 --- /dev/null +++ b/install/scripts/knative-with-openshift.sh @@ -0,0 +1,94 @@ +#!/usr/bin/env bash + +# Turn colors in this script off by setting the NO_COLOR variable in your +# environment to any value: +# +# $ NO_COLOR=1 test.sh +NO_COLOR=${NO_COLOR:-""} +if [ -z "$NO_COLOR" ]; then + header=$'\e[1;33m' + reset=$'\e[0m' +else + header='' + reset='' +fi + +function header_text { + echo "$header$*$reset" +} + +header_text "Starting Knative test-drive on OpenShift!" + +echo "Using oc version:" +oc version + +header_text "Writing config" +oc cluster up --write-config +sed -i -e 's/"admissionConfig":{"pluginConfig":null}/"admissionConfig": {\ + "pluginConfig": {\ + "ValidatingAdmissionWebhook": {\ + "configuration": {\ + "apiVersion": "v1",\ + "kind": "DefaultAdmissionConfig",\ + "disable": false\ + }\ + },\ + "MutatingAdmissionWebhook": {\ + "configuration": {\ + "apiVersion": "v1",\ + "kind": "DefaultAdmissionConfig",\ + "disable": false\ + }\ + }\ + }\ +}/' openshift.local.clusterup/kube-apiserver/master-config.yaml + +header_text "Starting OpenShift with 'oc cluster up'" +oc cluster up --server-loglevel=5 + +header_text "Logging in as system:admin and setting up default namespace" +oc login -u system:admin +oc project default +oc adm policy add-scc-to-user privileged -z default -n default +oc label namespace default istio-injection=enabled + +header_text "Setting up security policy for istio" +oc adm policy add-scc-to-user anyuid -z istio-ingress-service-account -n istio-system +oc adm policy add-scc-to-user anyuid -z default -n istio-system +oc adm policy add-scc-to-user anyuid -z prometheus -n istio-system +oc adm policy add-scc-to-user anyuid -z istio-egressgateway-service-account -n istio-system +oc adm policy add-scc-to-user anyuid -z istio-citadel-service-account -n istio-system +oc adm policy add-scc-to-user anyuid -z istio-ingressgateway-service-account -n istio-system +oc adm policy add-scc-to-user anyuid -z istio-cleanup-old-ca-service-account -n istio-system +oc adm policy add-scc-to-user anyuid -z istio-mixer-post-install-account -n istio-system +oc adm policy add-scc-to-user anyuid -z istio-mixer-service-account -n istio-system +oc adm policy add-scc-to-user anyuid -z istio-pilot-service-account -n istio-system +oc adm policy add-scc-to-user anyuid -z istio-sidecar-injector-service-account -n istio-system +oc adm policy add-cluster-role-to-user cluster-admin -z istio-galley-service-account -n istio-system + +header_text "Installing istio" +curl -L https://storage.googleapis.com/knative-releases/serving/latest/istio.yaml \ + | sed 's/LoadBalancer/NodePort/' \ + | oc apply -f - + +header_text "Waiting for istio to become ready" +sleep 5; while echo && oc get pods -n istio-system | grep -v -E "(Running|Completed|STATUS)"; do sleep 5; done + +header_text "Setting up security policy for knative" +oc adm policy add-scc-to-user anyuid -z build-controller -n knative-build +oc adm policy add-scc-to-user anyuid -z controller -n knative-serving +oc adm policy add-scc-to-user anyuid -z autoscaler -n knative-serving +oc adm policy add-scc-to-user anyuid -z kube-state-metrics -n monitoring +oc adm policy add-scc-to-user anyuid -z node-exporter -n monitoring +oc adm policy add-scc-to-user anyuid -z prometheus-system -n monitoring +oc adm policy add-cluster-role-to-user cluster-admin -z build-controller -n knative-build +oc adm policy add-cluster-role-to-user cluster-admin -z controller -n knative-serving + +header_text "Installing Knative" +curl -L https://storage.googleapis.com/knative-releases/serving/latest/release-lite.yaml \ + | sed 's/LoadBalancer/NodePort/' \ + | oc apply -f - + +header_text "Waiting for Knative to become ready" +sleep 5; while echo && oc get pods -n knative-serving | grep -v -E "(Running|Completed|STATUS)"; do sleep 5; done + From 7a6b5aa2e7fba7da89d89ffea5ea18d6398ad415 Mon Sep 17 00:00:00 2001 From: jonjohnsonjr Date: Mon, 6 Aug 2018 15:36:11 -0700 Subject: [PATCH 04/36] Fix broken link (#317) --- build/builds.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/builds.md b/build/builds.md index 7fbf2eb3b..573b10884 100644 --- a/build/builds.md +++ b/build/builds.md @@ -156,7 +156,7 @@ complement the volumes that are implicitly For example, use volumes to accomplish one of the following common tasks: - * [Mount a Kubernetes secrets(./auth.md). + * [Mount a Kubernetes secret](./auth.md). * Creat an `emptyDir` volume to act as a cache for use across multiple build steps. Consider using a persistent volume for inter-build caching. From cdd8e1a3c18dc3e76add7e84a39e962110d0b206 Mon Sep 17 00:00:00 2001 From: Adriano Cunha <35786489+adrcunha@users.noreply.github.com> Date: Tue, 7 Aug 2018 14:33:12 -0700 Subject: [PATCH 05/36] Remove instructions for checking Prow logs from Google Cloud Console (#314) Now that our Prow instance is public, links to test results work out-of-the-box. --- community/REVIEWING.md | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/community/REVIEWING.md b/community/REVIEWING.md index ec2118aa7..7915a1c8c 100644 --- a/community/REVIEWING.md +++ b/community/REVIEWING.md @@ -92,34 +92,13 @@ A PR can be merged only after the following criteria are met: This project uses [Prow](https://github.com/kubernetes/test-infra/tree/master/prow) to -automatically run tests for every PR. PRs with failing tests might not b -e merged. If necessary, you can rerun the tests by simply adding the comment +automatically run tests for every PR. PRs with failing tests might not be +merged. If necessary, you can rerun the tests by simply adding the comment `/retest` to your PR. Prow has several other features that make PR management easier, like running the go linter or assigning labels. For a full list of commands understood by Prow, -see the [command help -page](https://prow-internal.gcpnode.com/command-help?repo=knative%2Fknative). - -### Viewing test logs - -The Prow instance is internal to Google, which means that only Google -employees can access the "Details" link of the test job (provided by -Prow in the PR thread). However, if you're a Knative team member outside -Google, and you are a member of the -[knative-dev@](https://groups.google.com/forum/#!forum/knative-dev) -Google group, you can see the test logs by following these instructions: - -1. Wait for Prow to finish the test execution. Note the PR number. - -2. Open the URL http://gcsweb.k8s.io/gcs/knative-prow/pr-logs/pull/knative_serving/###/pull-knative-serving-@@@-tests/ -where ### is the PR number and @@@ is the test type (_build_, _unit_ or _integration_). - -3. You'll see one or more numbered directories. The highest number is the latest -test execution (called "build" by Prow). - -4. The raw test log is the text file named `build-log.txt` inside each numbered -directory. +see the [command help page](https://prow.knative.dev/command-help). --- From 8c2b7f60d81b585b7dd5e86d6fbdec37c6b32669 Mon Sep 17 00:00:00 2001 From: Mike Helmick Date: Wed, 8 Aug 2018 09:53:12 -0700 Subject: [PATCH 06/36] =?UTF-8?q?Add=20an=20elixir=20language=20sample=20u?= =?UTF-8?q?sing=20the=20phoenix=20framework=20to=20the=20knat=E2=80=A6=20(?= =?UTF-8?q?#298)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add an elixir language sample using the phoenix framework to the knative serving samples. * Add links to Elixir and Phoenix Web sites. * remove giant package-lock.json * change -go to -elixir in readme. --- serving/samples/helloworld-elixir/.gitignore | 28 ++ serving/samples/helloworld-elixir/Dockerfile | 27 ++ serving/samples/helloworld-elixir/README.md | 295 ++++++++++++++++++ .../helloworld-elixir/assets/brunch-config.js | 62 ++++ .../helloworld-elixir/assets/css/app.css | 1 + .../helloworld-elixir/assets/css/phoenix.css | 77 +++++ .../helloworld-elixir/assets/js/app.js | 21 ++ .../helloworld-elixir/assets/js/socket.js | 62 ++++ .../helloworld-elixir/assets/package.json | 18 ++ .../assets/static/favicon.ico | Bin 0 -> 1258 bytes .../assets/static/images/phoenix.png | Bin 0 -> 13900 bytes .../assets/static/robots.txt | 5 + .../helloworld-elixir/config/config.exs | 23 ++ .../samples/helloworld-elixir/config/dev.exs | 49 +++ .../samples/helloworld-elixir/config/prod.exs | 67 ++++ .../config/prod.secret.exs.sample | 12 + .../samples/helloworld-elixir/config/test.exs | 10 + .../samples/helloworld-elixir/lib/hello.ex | 9 + .../lib/hello/application.ex | 31 ++ .../helloworld-elixir/lib/hello_web.ex | 67 ++++ .../lib/hello_web/channels/user_socket.ex | 38 +++ .../hello_web/controllers/page_controller.ex | 14 + .../lib/hello_web/endpoint.ex | 57 ++++ .../lib/hello_web/gettext.ex | 24 ++ .../helloworld-elixir/lib/hello_web/router.ex | 27 ++ .../hello_web/templates/layout/app.html.eex | 32 ++ .../hello_web/templates/page/index.html.eex | 12 + .../lib/hello_web/views/error_helpers.ex | 44 +++ .../lib/hello_web/views/error_view.ex | 16 + .../lib/hello_web/views/hello_view.ex | 3 + .../lib/hello_web/views/layout_view.ex | 3 + .../lib/hello_web/views/page_view.ex | 3 + serving/samples/helloworld-elixir/mix.exs | 44 +++ serving/samples/helloworld-elixir/mix.lock | 15 + .../priv/gettext/en/LC_MESSAGES/errors.po | 11 + .../helloworld-elixir/priv/gettext/errors.pot | 10 + .../samples/helloworld-elixir/rel/config.exs | 53 ++++ .../samples/helloworld-elixir/service.yaml | 15 + .../controllers/page_controller_test.exs | 8 + .../test/hello_web/views/error_view_test.exs | 16 + .../test/hello_web/views/layout_view_test.exs | 3 + .../test/hello_web/views/page_view_test.exs | 3 + .../test/support/channel_case.ex | 33 ++ .../test/support/conn_case.ex | 34 ++ .../helloworld-elixir/test/test_helper.exs | 2 + 45 files changed, 1384 insertions(+) create mode 100644 serving/samples/helloworld-elixir/.gitignore create mode 100644 serving/samples/helloworld-elixir/Dockerfile create mode 100644 serving/samples/helloworld-elixir/README.md create mode 100644 serving/samples/helloworld-elixir/assets/brunch-config.js create mode 100644 serving/samples/helloworld-elixir/assets/css/app.css create mode 100644 serving/samples/helloworld-elixir/assets/css/phoenix.css create mode 100644 serving/samples/helloworld-elixir/assets/js/app.js create mode 100644 serving/samples/helloworld-elixir/assets/js/socket.js create mode 100644 serving/samples/helloworld-elixir/assets/package.json create mode 100644 serving/samples/helloworld-elixir/assets/static/favicon.ico create mode 100644 serving/samples/helloworld-elixir/assets/static/images/phoenix.png create mode 100644 serving/samples/helloworld-elixir/assets/static/robots.txt create mode 100644 serving/samples/helloworld-elixir/config/config.exs create mode 100644 serving/samples/helloworld-elixir/config/dev.exs create mode 100644 serving/samples/helloworld-elixir/config/prod.exs create mode 100644 serving/samples/helloworld-elixir/config/prod.secret.exs.sample create mode 100644 serving/samples/helloworld-elixir/config/test.exs create mode 100644 serving/samples/helloworld-elixir/lib/hello.ex create mode 100644 serving/samples/helloworld-elixir/lib/hello/application.ex create mode 100644 serving/samples/helloworld-elixir/lib/hello_web.ex create mode 100644 serving/samples/helloworld-elixir/lib/hello_web/channels/user_socket.ex create mode 100644 serving/samples/helloworld-elixir/lib/hello_web/controllers/page_controller.ex create mode 100644 serving/samples/helloworld-elixir/lib/hello_web/endpoint.ex create mode 100644 serving/samples/helloworld-elixir/lib/hello_web/gettext.ex create mode 100644 serving/samples/helloworld-elixir/lib/hello_web/router.ex create mode 100644 serving/samples/helloworld-elixir/lib/hello_web/templates/layout/app.html.eex create mode 100644 serving/samples/helloworld-elixir/lib/hello_web/templates/page/index.html.eex create mode 100644 serving/samples/helloworld-elixir/lib/hello_web/views/error_helpers.ex create mode 100644 serving/samples/helloworld-elixir/lib/hello_web/views/error_view.ex create mode 100644 serving/samples/helloworld-elixir/lib/hello_web/views/hello_view.ex create mode 100644 serving/samples/helloworld-elixir/lib/hello_web/views/layout_view.ex create mode 100644 serving/samples/helloworld-elixir/lib/hello_web/views/page_view.ex create mode 100644 serving/samples/helloworld-elixir/mix.exs create mode 100644 serving/samples/helloworld-elixir/mix.lock create mode 100644 serving/samples/helloworld-elixir/priv/gettext/en/LC_MESSAGES/errors.po create mode 100644 serving/samples/helloworld-elixir/priv/gettext/errors.pot create mode 100644 serving/samples/helloworld-elixir/rel/config.exs create mode 100644 serving/samples/helloworld-elixir/service.yaml create mode 100644 serving/samples/helloworld-elixir/test/hello_web/controllers/page_controller_test.exs create mode 100644 serving/samples/helloworld-elixir/test/hello_web/views/error_view_test.exs create mode 100644 serving/samples/helloworld-elixir/test/hello_web/views/layout_view_test.exs create mode 100644 serving/samples/helloworld-elixir/test/hello_web/views/page_view_test.exs create mode 100644 serving/samples/helloworld-elixir/test/support/channel_case.ex create mode 100644 serving/samples/helloworld-elixir/test/support/conn_case.ex create mode 100644 serving/samples/helloworld-elixir/test/test_helper.exs diff --git a/serving/samples/helloworld-elixir/.gitignore b/serving/samples/helloworld-elixir/.gitignore new file mode 100644 index 000000000..3064370c9 --- /dev/null +++ b/serving/samples/helloworld-elixir/.gitignore @@ -0,0 +1,28 @@ +# App artifacts +/_build +/db +/deps +/*.ez + +# Generated on crash by the VM +erl_crash.dump + +# Generated on crash by NPM +npm-debug.log +/assets/package-lock.json + +# Static artifacts +/assets/node_modules + +# Since we are building assets from assets/, +# we ignore priv/static. You may want to comment +# this depending on your deployment strategy. +/priv/static/ + +# Files matching config/*.secret.exs pattern contain sensitive +# data and you should not commit them into version control. +# +# Alternatively, you may comment the line below and commit the +# secrets files as long as you replace their contents by environment +# variables. +/config/*.secret.exs diff --git a/serving/samples/helloworld-elixir/Dockerfile b/serving/samples/helloworld-elixir/Dockerfile new file mode 100644 index 000000000..20f684162 --- /dev/null +++ b/serving/samples/helloworld-elixir/Dockerfile @@ -0,0 +1,27 @@ +FROM elixir:alpine +ARG APP_NAME=hello +ARG PHOENIX_SUBDIR=. +ENV MIX_ENV=prod REPLACE_OS_VARS=true TERM=xterm +WORKDIR /opt/app +RUN apk update \ + && apk --no-cache --update add nodejs nodejs-npm \ + && mix local.rebar --force \ + && mix local.hex --force +COPY . . +RUN mix do deps.get, deps.compile, compile +RUN cd ${PHOENIX_SUBDIR}/assets \ + && npm install \ + && ./node_modules/brunch/bin/brunch build -p \ + && cd .. \ + && mix phx.digest +RUN mix release --env=prod --verbose \ + && mv _build/prod/rel/${APP_NAME} /opt/release \ + && mv /opt/release/bin/${APP_NAME} /opt/release/bin/start_server +FROM alpine:latest +RUN apk update && apk --no-cache --update add bash openssl-dev +ENV PORT=8080 MIX_ENV=prod REPLACE_OS_VARS=true +WORKDIR /opt/app +EXPOSE 8080 +COPY --from=0 /opt/release . +ENV RUNNER_LOG_DIR /var/log +CMD ["/opt/app/bin/start_server", "foreground", "boot_var=/tmp"] diff --git a/serving/samples/helloworld-elixir/README.md b/serving/samples/helloworld-elixir/README.md new file mode 100644 index 000000000..a2bd34424 --- /dev/null +++ b/serving/samples/helloworld-elixir/README.md @@ -0,0 +1,295 @@ +# Hello World - Elixir Sample + +A simple web application written in [Elixir](https://elixir-lang.org/) using the +[Phoenix Framework](https://phoenixframework.org/). +The application prints all environment variables to the main page. + +# Set up Elixir and Phoenix Locally + +Following the [Phoenix Installation Guide](https://hexdocs.pm/phoenix/installation.html) +is the best way to get your computer set up for developing, +building, running, and packaging Elixir Web applications. + +# Running Locally + +To start your Phoenix server: + + * Install dependencies with `mix deps.get` + * Install Node.js dependencies with `cd assets && npm install` + * Start Phoenix endpoint with `mix phx.server` + +Now you can visit [`localhost:4000`](http://localhost:4000) from your browser. + +# Recreating the sample code + +1. Generate a new project. + + ```shell + mix phoenix.new helloelixir + ``` + + When asked, if you want to `Fetch and install dependencies? [Yn]` select `y` + +1. Follow the direction in the output to change directories into + start your local server with `mix phoenix.server` + +1. In the new directory, create a new Dockerfile for packaging + your application for deployment + + ```docker + # Start from a base image for elixir + FROM elixir:alpine + + # Set up Elixir and Phoenix + ARG APP_NAME=hello + ARG PHOENIX_SUBDIR=. + ENV MIX_ENV=prod REPLACE_OS_VARS=true TERM=xterm + WORKDIR /opt/app + + # Compile assets. + RUN apk update \ + && apk --no-cache --update add nodejs nodejs-npm \ + && mix local.rebar --force \ + && mix local.hex --force + COPY . . + + # Download and compile dependencies, then compile Web app. + RUN mix do deps.get, deps.compile, compile + RUN cd ${PHOENIX_SUBDIR}/assets \ + && npm install \ + && ./node_modules/brunch/bin/brunch build -p \ + && cd .. \ + && mix phx.digest + + # Create a release version of the application + RUN mix release --env=prod --verbose \ + && mv _build/prod/rel/${APP_NAME} /opt/release \ + && mv /opt/release/bin/${APP_NAME} /opt/release/bin/start_server + + # Prepare final layer + FROM alpine:latest + RUN apk update && apk --no-cache --update add bash openssl-dev + ENV PORT=8080 MIX_ENV=prod REPLACE_OS_VARS=true + WORKDIR /opt/app + + # Document that the service listens on port 8080. + EXPOSE 8080 + COPY --from=0 /opt/release . + ENV RUNNER_LOG_DIR /var/log + + # Command to execute the application. + CMD ["/opt/app/bin/start_server", "foreground", "boot_var=/tmp"] + ``` + +1. Create a new file, `service.yaml` and copy the following Service + definition into the file. Make sure to replace `{username}` with + your Docker Hub username. + + ```yaml + apiVersion: serving.knative.dev/v1alpha1 + kind: Service + metadata: + name: helloworld-elixir + namespace: default + spec: + runLatest: + configuration: + revisionTemplate: + spec: + container: + image: docker.io/{username}/helloworld-elixir + env: + - name: TARGET + value: "elixir Sample v1" + ``` + +# Building and deploying the sample + +The sample in this directory is ready to build and deploy without changes. +You can deploy the sample as is, or use you created version following the +directions above. + +1. Generate a new `secret_key_base` in the `config/prod.secret.exs` file. + Phoenix applications use a secrets file on production deployments and, by + default, that file is not checked into source control. We have provides + shell of an example on `config/prod.secret.exs.sample` and you can use the + following command to generate a new prod secrets file. + + ```shell + SECRET_KEY_BASE=$(elixir -e ":crypto.strong_rand_bytes(48) |> Base.encode64 |> IO.puts") + sed "s|SECRET+KEY+BASE|$SECRET_KEY_BASE|" config/prod.secret.exs.sample >config/prod.secret.exs + ``` + +1. Use Docker to build the sample code into a container. To build and push + with Docker Hub, run these commands replacing `{username}` with your Docker + Hub username: + + ```shell + # Build the container on your local machine + docker build -t {username}/helloworld-elixir . + + # Push the container to docker registry + docker push {username}/helloworld-elixir + ``` + +1. After the build has completed and the container is pushed to docker hub, you + can deploy the app into your cluster. Ensure that the container image value + in `service.yaml` matches the container you built in + the previous step. Apply the configuration using `kubectl`: + + ```shell + kubectl apply -f service.yaml + ``` + +1. Now that your service is created, Knative will perform the following steps: + * Create a new immutable revision for this version of the app. + * Network programming to create a route, ingress, service, and load balance for your app. + * Automatically scale your pods up and down (including to zero active pods). + +1. To find the IP address for your service, use + `kubectl get svc knative-ingressgateway -n istio-system` to get the ingress IP for your + cluster. If your cluster is new, it may take sometime for the service to get asssigned + an external IP address. + + ``` + kubectl get svc knative-ingressgateway -n istio-system + + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +knative-ingressgateway LoadBalancer 10.35.254.218 35.225.171.32 80:32380/TCP,443:32390/TCP,32400:32400/TCP 1h + ``` + +1. To find the URL for your service, use + + ``` + kubectl get services.serving.knative.dev helloworld-elixir -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain + + NAME DOMAIN + helloworld-elixir helloworld-elixir.default.example.com + ``` + + +1. Now you can make a request to your app to see the results. Replace + `{IP_ADDRESS}` with the address you see returned in the previous step. + + ```shell + curl -H "Host: helloworld-elixir.default.example.com" http://{IP_ADDRESS} + + ... + # HTML from your application is returned. + ``` + + Here is the HTML returned from our deployed sample application: + + ```HTML + + + + + + + + + + Hello Knative + + + + +
+
+ +
+ + + + +
+
+

Welcome to Knative and Elixir

+ +

$TARGET = elixir Sample v1

+
+ +

Environment

+
    +
  • BINDIR = /opt/app/erts-9.3.2/bin
  • +
  • DEST_SYS_CONFIG_PATH = /opt/app/var/sys.config
  • +
  • DEST_VMARGS_PATH = /opt/app/var/vm.args
  • +
  • DISTILLERY_TASK = foreground
  • +
  • EMU = beam
  • +
  • ERL_LIBS = /opt/app/lib
  • +
  • ERL_OPTS =
  • +
  • ERTS_DIR = /opt/app/erts-9.3.2
  • +
  • ERTS_LIB_DIR = /opt/app/erts-9.3.2/../lib
  • +
  • ERTS_VSN = 9.3.2
  • +
  • HELLOWORLD_ELIXIR_00001_SERVICE_PORT = tcp://10.35.241.50:80
  • +
  • HELLOWORLD_ELIXIR_00001_SERVICE_PORT_80_TCP = tcp://10.35.241.50:80
  • +
  • HELLOWORLD_ELIXIR_00001_SERVICE_PORT_80_TCP_ADDR = 10.35.241.50
  • +
  • HELLOWORLD_ELIXIR_00001_SERVICE_PORT_80_TCP_PORT = 80
  • +
  • HELLOWORLD_ELIXIR_00001_SERVICE_PORT_80_TCP_PROTO = tcp
  • +
  • HELLOWORLD_ELIXIR_00001_SERVICE_SERVICE_HOST = 10.35.241.50
  • +
  • HELLOWORLD_ELIXIR_00001_SERVICE_SERVICE_PORT = 80
  • +
  • HELLOWORLD_ELIXIR_00001_SERVICE_SERVICE_PORT_HTTP = 80
  • +
  • HELLOWORLD_ELIXIR_PORT = tcp://10.35.253.90:80
  • +
  • HELLOWORLD_ELIXIR_PORT_80_TCP = tcp://10.35.253.90:80
  • +
  • HELLOWORLD_ELIXIR_PORT_80_TCP_ADDR = 10.35.253.90
  • +
  • HELLOWORLD_ELIXIR_PORT_80_TCP_PORT = 80
  • +
  • HELLOWORLD_ELIXIR_PORT_80_TCP_PROTO = tcp
  • +
  • HELLOWORLD_ELIXIR_SERVICE_HOST = 10.35.253.90
  • +
  • HELLOWORLD_ELIXIR_SERVICE_PORT = 80
  • +
  • HELLOWORLD_ELIXIR_SERVICE_PORT_HTTP = 80
  • +
  • HOME = /root
  • +
  • HOSTNAME = helloworld-elixir-00001-deployment-84f68946b4-76hcv
  • +
  • KUBERNETES_PORT = tcp://10.35.240.1:443
  • +
  • KUBERNETES_PORT_443_TCP = tcp://10.35.240.1:443
  • +
  • KUBERNETES_PORT_443_TCP_ADDR = 10.35.240.1
  • +
  • KUBERNETES_PORT_443_TCP_PORT = 443
  • +
  • KUBERNETES_PORT_443_TCP_PROTO = tcp
  • +
  • KUBERNETES_SERVICE_HOST = 10.35.240.1
  • +
  • KUBERNETES_SERVICE_PORT = 443
  • +
  • KUBERNETES_SERVICE_PORT_HTTPS = 443
  • +
  • LD_LIBRARY_PATH = /opt/app/erts-9.3.2/lib:
  • +
  • MIX_ENV = prod
  • +
  • NAME = hello@127.0.0.1
  • +
  • NAME_ARG = -name hello@127.0.0.1
  • +
  • NAME_TYPE = -name
  • +
  • OLDPWD = /opt/app
  • +
  • OTP_VER = 20
  • +
  • PATH = /opt/app/erts-9.3.2/bin:/opt/app/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
  • +
  • PORT = 8080
  • +
  • PROGNAME = opt/app/releases/0.0.1/hello.sh
  • +
  • PWD = /opt/app
  • +
  • RELEASES_DIR = /opt/app/releases
  • +
  • RELEASE_CONFIG_DIR = /opt/app
  • +
  • RELEASE_ROOT_DIR = /opt/app
  • +
  • REL_NAME = hello
  • +
  • REL_VSN = 0.0.1
  • +
  • REPLACE_OS_VARS = true
  • +
  • ROOTDIR = /opt/app
  • +
  • RUNNER_LOG_DIR = /var/log
  • +
  • RUN_ERL_ENV =
  • +
  • SHLVL = 1
  • +
  • SRC_SYS_CONFIG_PATH = /opt/app/releases/0.0.1/sys.config
  • +
  • SRC_VMARGS_PATH = /opt/app/releases/0.0.1/vm.args
  • +
  • SYS_CONFIG_PATH = /opt/app/var/sys.config
  • +
  • TARGET = elixir Sample v1
  • +
  • TERM = xterm
  • +
  • VMARGS_PATH = /opt/app/var/vm.args
  • +
+
+ +
+ + + + ``` + +## Removing the sample app deployment + +To remove the sample app from your cluster, delete the service record: + +```shell +kubectl delete -f service.yaml +``` diff --git a/serving/samples/helloworld-elixir/assets/brunch-config.js b/serving/samples/helloworld-elixir/assets/brunch-config.js new file mode 100644 index 000000000..b15df4600 --- /dev/null +++ b/serving/samples/helloworld-elixir/assets/brunch-config.js @@ -0,0 +1,62 @@ +exports.config = { + // See http://brunch.io/#documentation for docs. + files: { + javascripts: { + joinTo: "js/app.js" + + // To use a separate vendor.js bundle, specify two files path + // http://brunch.io/docs/config#-files- + // joinTo: { + // "js/app.js": /^js/, + // "js/vendor.js": /^(?!js)/ + // } + // + // To change the order of concatenation of files, explicitly mention here + // order: { + // before: [ + // "vendor/js/jquery-2.1.1.js", + // "vendor/js/bootstrap.min.js" + // ] + // } + }, + stylesheets: { + joinTo: "css/app.css" + }, + templates: { + joinTo: "js/app.js" + } + }, + + conventions: { + // This option sets where we should place non-css and non-js assets in. + // By default, we set this to "/assets/static". Files in this directory + // will be copied to `paths.public`, which is "priv/static" by default. + assets: /^(static)/ + }, + + // Phoenix paths configuration + paths: { + // Dependencies and current project directories to watch + watched: ["static", "css", "js", "vendor"], + // Where to compile files to + public: "../priv/static" + }, + + // Configure your plugins + plugins: { + babel: { + // Do not use ES6 compiler in vendor code + ignore: [/vendor/] + } + }, + + modules: { + autoRequire: { + "js/app.js": ["js/app"] + } + }, + + npm: { + enabled: true + } +}; diff --git a/serving/samples/helloworld-elixir/assets/css/app.css b/serving/samples/helloworld-elixir/assets/css/app.css new file mode 100644 index 000000000..5314c34d2 --- /dev/null +++ b/serving/samples/helloworld-elixir/assets/css/app.css @@ -0,0 +1 @@ +/* This file is for your main application css. */ \ No newline at end of file diff --git a/serving/samples/helloworld-elixir/assets/css/phoenix.css b/serving/samples/helloworld-elixir/assets/css/phoenix.css new file mode 100644 index 000000000..0b406d712 --- /dev/null +++ b/serving/samples/helloworld-elixir/assets/css/phoenix.css @@ -0,0 +1,77 @@ +/* Includes Bootstrap as well as some default style for the starter + * application. This can be safely deleted to start fresh. + */ + +/*! + * Bootstrap v3.3.5 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.33px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:3;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:2;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{min-height:16.43px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} + +/* Space out content a bit */ +body, form, ul, table { + margin-top: 20px; + margin-bottom: 20px; +} + +/* Phoenix flash messages */ +.alert:empty { display: none; } + +/* Custom page header */ +.header { + border-bottom: 1px solid #e5e5e5; +} +.logo { + width: 519px; + height: 71px; + display: inline-block; + margin-bottom: 1em; + background-image: url("/images/phoenix.png"); + background-size: 519px 71px; +} + +/* Everything but the jumbotron gets side spacing for mobile first views */ +.header, +.marketing { + padding-right: 15px; + padding-left: 15px; +} + +/* Customize container */ +@media (min-width: 768px) { + .container { + max-width: 730px; + } +} +.container-narrow > hr { + margin: 30px 0; +} + +/* Main marketing message */ +.jumbotron { + text-align: center; + border-bottom: 1px solid #e5e5e5; +} + +/* Supporting marketing content */ +.marketing { + margin: 35px 0; +} + +/* Responsive: Portrait tablets and up */ +@media screen and (min-width: 768px) { + /* Remove the padding we set earlier */ + .header, + .marketing { + padding-right: 0; + padding-left: 0; + } + /* Space out the masthead */ + .header { + margin-bottom: 30px; + } + /* Remove the bottom border on the jumbotron for visual effect */ + .jumbotron { + border-bottom: 0; + } +} \ No newline at end of file diff --git a/serving/samples/helloworld-elixir/assets/js/app.js b/serving/samples/helloworld-elixir/assets/js/app.js new file mode 100644 index 000000000..e7549b9db --- /dev/null +++ b/serving/samples/helloworld-elixir/assets/js/app.js @@ -0,0 +1,21 @@ +// Brunch automatically concatenates all files in your +// watched paths. Those paths can be configured at +// config.paths.watched in "brunch-config.js". +// +// However, those files will only be executed if +// explicitly imported. The only exception are files +// in vendor, which are never wrapped in imports and +// therefore are always executed. + +// Import dependencies +// +// If you no longer want to use a dependency, remember +// to also remove its path from "config.paths.watched". +import "phoenix_html" + +// Import local files +// +// Local files can be imported directly using relative +// paths "./socket" or full ones "web/static/js/socket". + +// import socket from "./socket" diff --git a/serving/samples/helloworld-elixir/assets/js/socket.js b/serving/samples/helloworld-elixir/assets/js/socket.js new file mode 100644 index 000000000..5c23a67f7 --- /dev/null +++ b/serving/samples/helloworld-elixir/assets/js/socket.js @@ -0,0 +1,62 @@ +// NOTE: The contents of this file will only be executed if +// you uncomment its entry in "assets/js/app.js". + +// To use Phoenix channels, the first step is to import Socket +// and connect at the socket path in "lib/web/endpoint.ex": +import {Socket} from "phoenix" + +let socket = new Socket("/socket", {params: {token: window.userToken}}) + +// When you connect, you'll often need to authenticate the client. +// For example, imagine you have an authentication plug, `MyAuth`, +// which authenticates the session and assigns a `:current_user`. +// If the current user exists you can assign the user's token in +// the connection for use in the layout. +// +// In your "lib/web/router.ex": +// +// pipeline :browser do +// ... +// plug MyAuth +// plug :put_user_token +// end +// +// defp put_user_token(conn, _) do +// if current_user = conn.assigns[:current_user] do +// token = Phoenix.Token.sign(conn, "user socket", current_user.id) +// assign(conn, :user_token, token) +// else +// conn +// end +// end +// +// Now you need to pass this token to JavaScript. You can do so +// inside a script tag in "lib/web/templates/layout/app.html.eex": +// +// +// +// You will need to verify the user token in the "connect/2" function +// in "lib/web/channels/user_socket.ex": +// +// def connect(%{"token" => token}, socket) do +// # max_age: 1209600 is equivalent to two weeks in seconds +// case Phoenix.Token.verify(socket, "user socket", token, max_age: 1209600) do +// {:ok, user_id} -> +// {:ok, assign(socket, :user, user_id)} +// {:error, reason} -> +// :error +// end +// end +// +// Finally, pass the token on connect as below. Or remove it +// from connect if you don't care about authentication. + +socket.connect() + +// Now that you are connected, you can join channels with a topic: +let channel = socket.channel("topic:subtopic", {}) +channel.join() + .receive("ok", resp => { console.log("Joined successfully", resp) }) + .receive("error", resp => { console.log("Unable to join", resp) }) + +export default socket diff --git a/serving/samples/helloworld-elixir/assets/package.json b/serving/samples/helloworld-elixir/assets/package.json new file mode 100644 index 000000000..4cc398697 --- /dev/null +++ b/serving/samples/helloworld-elixir/assets/package.json @@ -0,0 +1,18 @@ +{ + "repository": {}, + "license": "MIT", + "scripts": { + "deploy": "brunch build --production", + "watch": "brunch watch --stdin" + }, + "dependencies": { + "phoenix": "file:../deps/phoenix", + "phoenix_html": "file:../deps/phoenix_html" + }, + "devDependencies": { + "babel-brunch": "6.1.1", + "brunch": "2.10.9", + "clean-css-brunch": "2.10.0", + "uglify-js-brunch": "2.10.0" + } +} diff --git a/serving/samples/helloworld-elixir/assets/static/favicon.ico b/serving/samples/helloworld-elixir/assets/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..73de524aaadcf60fbe9d32881db0aa86b58b5cb9 GIT binary patch literal 1258 zcmbtUO>fgM7{=qN=;Mz_82;lvPEdVaxv-<-&=sZLwab?3I zBP>U*&(Hv<5n@9ZQ$vhg#|u$Zmtq8BV;+W*7(?jOx-{r?#TE&$Sdq77MbdJjD5`-q zMm_z(jLv3t>5NhzK{%aG(Yudfpjd3AFdKe2U7&zdepTe>^s(@!&0X8TJ`h+-I?84Ml# literal 0 HcmV?d00001 diff --git a/serving/samples/helloworld-elixir/assets/static/images/phoenix.png b/serving/samples/helloworld-elixir/assets/static/images/phoenix.png new file mode 100644 index 0000000000000000000000000000000000000000..9c81075f63d2151e6f40e9aa66f665749a87cc6a GIT binary patch literal 13900 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 UWxWXg`G1#+f~I_}taaG`2PLnS&Hw-a literal 0 HcmV?d00001 diff --git a/serving/samples/helloworld-elixir/assets/static/robots.txt b/serving/samples/helloworld-elixir/assets/static/robots.txt new file mode 100644 index 000000000..3c9c7c01f --- /dev/null +++ b/serving/samples/helloworld-elixir/assets/static/robots.txt @@ -0,0 +1,5 @@ +# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file +# +# To ban all spiders from the entire site uncomment the next two lines: +# User-agent: * +# Disallow: / diff --git a/serving/samples/helloworld-elixir/config/config.exs b/serving/samples/helloworld-elixir/config/config.exs new file mode 100644 index 000000000..ab1e7af70 --- /dev/null +++ b/serving/samples/helloworld-elixir/config/config.exs @@ -0,0 +1,23 @@ +# This file is responsible for configuring your application +# and its dependencies with the aid of the Mix.Config module. +# +# This configuration file is loaded before any dependency and +# is restricted to this project. +use Mix.Config + +# Configures the endpoint +config :hello, HelloWeb.Endpoint, + url: [host: "localhost"], + secret_key_base: "P0fv0U47j6mdL40sn3f3BIuvEyIdbxUq+yKc8Mcbwig5105brf2Dzio5ANjTVRUo", + render_errors: [view: HelloWeb.ErrorView, accepts: ~w(html json)] + #pubsub: [name: Hello.PubSub, + # adapter: Phoenix.PubSub.PG2] + +# Configures Elixir's Logger +config :logger, :console, + format: "$time $metadata[$level] $message\n", + metadata: [:user_id] + +# Import environment specific config. This must remain at the bottom +# of this file so it overrides the configuration defined above. +import_config "#{Mix.env}.exs" diff --git a/serving/samples/helloworld-elixir/config/dev.exs b/serving/samples/helloworld-elixir/config/dev.exs new file mode 100644 index 000000000..4e166ca92 --- /dev/null +++ b/serving/samples/helloworld-elixir/config/dev.exs @@ -0,0 +1,49 @@ +use Mix.Config + +# For development, we disable any cache and enable +# debugging and code reloading. +# +# The watchers configuration can be used to run external +# watchers to your application. For example, we use it +# with brunch.io to recompile .js and .css sources. +config :hello, HelloWeb.Endpoint, + http: [port: 4000], + debug_errors: true, + code_reloader: true, + check_origin: false, + watchers: [node: ["node_modules/brunch/bin/brunch", "watch", "--stdin", + cd: Path.expand("../assets", __DIR__)]] + +# ## SSL Support +# +# In order to use HTTPS in development, a self-signed +# certificate can be generated by running the following +# command from your terminal: +# +# openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=www.example.com" -keyout priv/server.key -out priv/server.pem +# +# The `http:` config above can be replaced with: +# +# https: [port: 4000, keyfile: "priv/server.key", certfile: "priv/server.pem"], +# +# If desired, both `http:` and `https:` keys can be +# configured to run both http and https servers on +# different ports. + +# Watch static and templates for browser reloading. +config :hello, HelloWeb.Endpoint, + live_reload: [ + patterns: [ + ~r{priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$}, + ~r{priv/gettext/.*(po)$}, + ~r{lib/hello_web/views/.*(ex)$}, + ~r{lib/hello_web/templates/.*(eex)$} + ] + ] + +# Do not include metadata nor timestamps in development logs +config :logger, :console, format: "[$level] $message\n" + +# Set a higher stacktrace during development. Avoid configuring such +# in production as building large stacktraces may be expensive. +config :phoenix, :stacktrace_depth, 20 diff --git a/serving/samples/helloworld-elixir/config/prod.exs b/serving/samples/helloworld-elixir/config/prod.exs new file mode 100644 index 000000000..3ee2c7d5c --- /dev/null +++ b/serving/samples/helloworld-elixir/config/prod.exs @@ -0,0 +1,67 @@ +use Mix.Config + +# For production, we often load configuration from external +# sources, such as your system environment. For this reason, +# you won't find the :http configuration below, but set inside +# HelloWeb.Endpoint.init/2 when load_from_system_env is +# true. Any dynamic configuration should be done there. +# +# Don't forget to configure the url host to something meaningful, +# Phoenix uses this information when generating URLs. +# +# Finally, we also include the path to a cache manifest +# containing the digested version of static files. This +# manifest is generated by the mix phx.digest task +# which you typically run after static files are built. +config :hello, HelloWeb.Endpoint, + load_from_system_env: false, + http: [port: 8080], + check_origin: false, + server: true, + root: ".", + cache_static_manifest: "priv/static/cache_manifest.json" + +# Do not print debug messages in production +config :logger, level: :info + +# ## SSL Support +# +# To get SSL working, you will need to add the `https` key +# to the previous section and set your `:url` port to 443: +# +# config :hello, HelloWeb.Endpoint, +# ... +# url: [host: "example.com", port: 443], +# https: [:inet6, +# port: 443, +# keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"), +# certfile: System.get_env("SOME_APP_SSL_CERT_PATH")] +# +# Where those two env variables return an absolute path to +# the key and cert in disk or a relative path inside priv, +# for example "priv/ssl/server.key". +# +# We also recommend setting `force_ssl`, ensuring no data is +# ever sent via http, always redirecting to https: +# +# config :hello, HelloWeb.Endpoint, +# force_ssl: [hsts: true] +# +# Check `Plug.SSL` for all available options in `force_ssl`. + +# ## Using releases +# +# If you are doing OTP releases, you need to instruct Phoenix +# to start the server for all endpoints: +# +# config :phoenix, :serve_endpoints, true +# +# Alternatively, you can configure exactly which server to +# start per endpoint: +# +# config :hello, HelloWeb.Endpoint, server: true +# + +# Finally import the config/prod.secret.exs +# which should be versioned separately. +import_config "prod.secret.exs" diff --git a/serving/samples/helloworld-elixir/config/prod.secret.exs.sample b/serving/samples/helloworld-elixir/config/prod.secret.exs.sample new file mode 100644 index 000000000..1092ddd7d --- /dev/null +++ b/serving/samples/helloworld-elixir/config/prod.secret.exs.sample @@ -0,0 +1,12 @@ +use Mix.Config + +# In this file, we keep production configuration that +# you'll likely want to automate and keep away from +# your version control system. +# +# You should document the content of this +# file or create a script for recreating it, since it's +# kept out of version control and might be hard to recover +# or recreate for your teammates (or yourself later on). +config :hello, HelloWeb.Endpoint, + secret_key_base: "SECRET+KEY+BASE" diff --git a/serving/samples/helloworld-elixir/config/test.exs b/serving/samples/helloworld-elixir/config/test.exs new file mode 100644 index 000000000..5ca3a7e46 --- /dev/null +++ b/serving/samples/helloworld-elixir/config/test.exs @@ -0,0 +1,10 @@ +use Mix.Config + +# We don't run a server during test. If one is required, +# you can enable the server option below. +config :hello, HelloWeb.Endpoint, + http: [port: 4001], + server: false + +# Print only warnings and errors during test +config :logger, level: :warn diff --git a/serving/samples/helloworld-elixir/lib/hello.ex b/serving/samples/helloworld-elixir/lib/hello.ex new file mode 100644 index 000000000..44d3ddecc --- /dev/null +++ b/serving/samples/helloworld-elixir/lib/hello.ex @@ -0,0 +1,9 @@ +defmodule Hello do + @moduledoc """ + Hello keeps the contexts that define your domain + and business logic. + + Contexts are also responsible for managing your data, regardless + if it comes from the database, an external API or others. + """ +end diff --git a/serving/samples/helloworld-elixir/lib/hello/application.ex b/serving/samples/helloworld-elixir/lib/hello/application.ex new file mode 100644 index 000000000..736b48637 --- /dev/null +++ b/serving/samples/helloworld-elixir/lib/hello/application.ex @@ -0,0 +1,31 @@ +defmodule Hello.Application do + use Application + + # See https://hexdocs.pm/elixir/Application.html + # for more information on OTP Applications + def start(_type, _args) do + IO.puts :stderr, "Application starting up" + import Supervisor.Spec + + # Define workers and child supervisors to be supervised + children = [ + # Start the endpoint when the application starts + supervisor(HelloWeb.Endpoint, []), + # Start your own worker by calling: Hello.Worker.start_link(arg1, arg2, arg3) + # worker(Hello.Worker, [arg1, arg2, arg3]), + ] + + # See https://hexdocs.pm/elixir/Supervisor.html + # for other strategies and supported options + opts = [strategy: :one_for_one, name: Hello.Supervisor] + Supervisor.start_link(children, opts) + end + + # Tell Phoenix to update the endpoint configuration + # whenever the application is updated. + def config_change(changed, _new, removed) do + IO.puts :stderr, "Config changed" + HelloWeb.Endpoint.config_change(changed, removed) + :ok + end +end diff --git a/serving/samples/helloworld-elixir/lib/hello_web.ex b/serving/samples/helloworld-elixir/lib/hello_web.ex new file mode 100644 index 000000000..4573268fb --- /dev/null +++ b/serving/samples/helloworld-elixir/lib/hello_web.ex @@ -0,0 +1,67 @@ +defmodule HelloWeb do + @moduledoc """ + The entrypoint for defining your web interface, such + as controllers, views, channels and so on. + + This can be used in your application as: + + use HelloWeb, :controller + use HelloWeb, :view + + The definitions below will be executed for every view, + controller, etc, so keep them short and clean, focused + on imports, uses and aliases. + + Do NOT define functions inside the quoted expressions + below. Instead, define any helper function in modules + and import those modules here. + """ + + def controller do + quote do + use Phoenix.Controller, namespace: HelloWeb + import Plug.Conn + import HelloWeb.Router.Helpers + import HelloWeb.Gettext + end + end + + def view do + quote do + use Phoenix.View, root: "lib/hello_web/templates", + namespace: HelloWeb + + # Import convenience functions from controllers + import Phoenix.Controller, only: [get_flash: 2, view_module: 1] + + # Use all HTML functionality (forms, tags, etc) + use Phoenix.HTML + + import HelloWeb.Router.Helpers + import HelloWeb.ErrorHelpers + import HelloWeb.Gettext + end + end + + def router do + quote do + use Phoenix.Router + import Plug.Conn + import Phoenix.Controller + end + end + + def channel do + quote do + use Phoenix.Channel + import HelloWeb.Gettext + end + end + + @doc """ + When used, dispatch to the appropriate controller/view/etc. + """ + defmacro __using__(which) when is_atom(which) do + apply(__MODULE__, which, []) + end +end diff --git a/serving/samples/helloworld-elixir/lib/hello_web/channels/user_socket.ex b/serving/samples/helloworld-elixir/lib/hello_web/channels/user_socket.ex new file mode 100644 index 000000000..4e7f20813 --- /dev/null +++ b/serving/samples/helloworld-elixir/lib/hello_web/channels/user_socket.ex @@ -0,0 +1,38 @@ +defmodule HelloWeb.UserSocket do + use Phoenix.Socket + + ## Channels + # channel "room:*", HelloWeb.RoomChannel + + ## Transports + transport :longpoll, Phoenix.Transports.LongPoll + # transport :longpoll, Phoenix.Transports.LongPoll + + # Socket params are passed from the client and can + # be used to verify and authenticate a user. After + # verification, you can put default assigns into + # the socket that will be set for all channels, ie + # + # {:ok, assign(socket, :user_id, verified_user_id)} + # + # To deny connection, return `:error`. + # + # See `Phoenix.Token` documentation for examples in + # performing token verification on connect. + def connect(_params, socket) do + IO.puts :stderr, "UserSocket.connect called" + {:ok, socket} + end + + # Socket id's are topics that allow you to identify all sockets for a given user: + # + # def id(socket), do: "user_socket:#{socket.assigns.user_id}" + # + # Would allow you to broadcast a "disconnect" event and terminate + # all active sockets and channels for a given user: + # + # HelloWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{}) + # + # Returning `nil` makes this socket anonymous. + def id(_socket), do: nil +end diff --git a/serving/samples/helloworld-elixir/lib/hello_web/controllers/page_controller.ex b/serving/samples/helloworld-elixir/lib/hello_web/controllers/page_controller.ex new file mode 100644 index 000000000..7eda062a9 --- /dev/null +++ b/serving/samples/helloworld-elixir/lib/hello_web/controllers/page_controller.ex @@ -0,0 +1,14 @@ +defmodule HelloWeb.PageController do + use HelloWeb, :controller + + def index(conn, params) do + env = System.get_env() + target = Map.get(env, "TARGET") + + render conn, "index.html", + title: "Hello Knative", + greeting: "Welcome to Knative and Elixir", + target: target, + env: env + end +end diff --git a/serving/samples/helloworld-elixir/lib/hello_web/endpoint.ex b/serving/samples/helloworld-elixir/lib/hello_web/endpoint.ex new file mode 100644 index 000000000..a3cc10adb --- /dev/null +++ b/serving/samples/helloworld-elixir/lib/hello_web/endpoint.ex @@ -0,0 +1,57 @@ +defmodule HelloWeb.Endpoint do + use Phoenix.Endpoint, otp_app: :hello + + socket "/socket", HelloWeb.UserSocket + + # Serve at "/" the static files from "priv/static" directory. + # + # You should set gzip to true if you are running phoenix.digest + # when deploying your static files in production. + plug Plug.Static, + at: "/", from: :hello, gzip: false, + only: ~w(css fonts images js favicon.ico robots.txt) + + # Code reloading can be explicitly enabled under the + # :code_reloader configuration of your endpoint. + if code_reloading? do + socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket + plug Phoenix.LiveReloader + plug Phoenix.CodeReloader + end + + plug Plug.Logger + + plug Plug.Parsers, + parsers: [:urlencoded, :multipart, :json], + pass: ["*/*"], + json_decoder: Poison + + plug Plug.MethodOverride + plug Plug.Head + + # The session will be stored in the cookie and signed, + # this means its contents can be read but not tampered with. + # Set :encryption_salt if you would also like to encrypt it. + plug Plug.Session, + store: :cookie, + key: "_hello_key", + signing_salt: "M0cGJtXU" + + plug HelloWeb.Router + + @doc """ + Callback invoked for dynamically configuring the endpoint. + + It receives the endpoint configuration and checks if + configuration should be loaded from the system environment. + """ + def init(_key, config) do + IO.puts :stderr, "called HelloWeb.Endpoint.init" + if config[:load_from_system_env] do + port = System.get_env("PORT") || raise "expected the PORT environment variable to be set" + {:ok, Keyword.put(config, :http, [:inet6, port: port])} + else + {:ok, config} + end + end +end diff --git a/serving/samples/helloworld-elixir/lib/hello_web/gettext.ex b/serving/samples/helloworld-elixir/lib/hello_web/gettext.ex new file mode 100644 index 000000000..bf7a9325d --- /dev/null +++ b/serving/samples/helloworld-elixir/lib/hello_web/gettext.ex @@ -0,0 +1,24 @@ +defmodule HelloWeb.Gettext do + @moduledoc """ + A module providing Internationalization with a gettext-based API. + + By using [Gettext](https://hexdocs.pm/gettext), + your module gains a set of macros for translations, for example: + + import HelloWeb.Gettext + + # Simple translation + gettext "Here is the string to translate" + + # Plural translation + ngettext "Here is the string to translate", + "Here are the strings to translate", + 3 + + # Domain-based translation + dgettext "errors", "Here is the error message to translate" + + See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage. + """ + use Gettext, otp_app: :hello +end diff --git a/serving/samples/helloworld-elixir/lib/hello_web/router.ex b/serving/samples/helloworld-elixir/lib/hello_web/router.ex new file mode 100644 index 000000000..2b074823c --- /dev/null +++ b/serving/samples/helloworld-elixir/lib/hello_web/router.ex @@ -0,0 +1,27 @@ +defmodule HelloWeb.Router do + use HelloWeb, :router + + pipeline :browser do + plug :accepts, ["html"] + plug :fetch_session + plug :fetch_flash + plug :protect_from_forgery + plug :put_secure_browser_headers + end + + pipeline :api do + plug :accepts, ["json"] + end + + scope "/", HelloWeb do + pipe_through :browser # Use the default browser stack + + get "/", PageController, :index + get "/:name", PageController, :show + end + + # Other scopes may use custom stacks. + # scope "/api", HelloWeb do + # pipe_through :api + # end +end diff --git a/serving/samples/helloworld-elixir/lib/hello_web/templates/layout/app.html.eex b/serving/samples/helloworld-elixir/lib/hello_web/templates/layout/app.html.eex new file mode 100644 index 000000000..a3592f383 --- /dev/null +++ b/serving/samples/helloworld-elixir/lib/hello_web/templates/layout/app.html.eex @@ -0,0 +1,32 @@ + + + + + + + + + + <%= @title %> + "> + + + +
+
+ +
+ + + + +
+ <%= render @view_module, @view_template, assigns %> +
+ +
+ + + diff --git a/serving/samples/helloworld-elixir/lib/hello_web/templates/page/index.html.eex b/serving/samples/helloworld-elixir/lib/hello_web/templates/page/index.html.eex new file mode 100644 index 000000000..2f5ad5ae4 --- /dev/null +++ b/serving/samples/helloworld-elixir/lib/hello_web/templates/page/index.html.eex @@ -0,0 +1,12 @@ +
+

<%= @greeting %>

+ +

$TARGET = <%= @target %>

+
+ +

Environment

+
    + <%= for key <- Enum.sort(Map.keys(@env)) do %> +
  • <%= key %> = <%= Map.get(@env, key) %>
  • + <% end %> +
diff --git a/serving/samples/helloworld-elixir/lib/hello_web/views/error_helpers.ex b/serving/samples/helloworld-elixir/lib/hello_web/views/error_helpers.ex new file mode 100644 index 000000000..fa06eae03 --- /dev/null +++ b/serving/samples/helloworld-elixir/lib/hello_web/views/error_helpers.ex @@ -0,0 +1,44 @@ +defmodule HelloWeb.ErrorHelpers do + @moduledoc """ + Conveniences for translating and building error messages. + """ + + use Phoenix.HTML + + @doc """ + Generates tag for inlined form input errors. + """ + def error_tag(form, field) do + Enum.map(Keyword.get_values(form.errors, field), fn (error) -> + content_tag :span, translate_error(error), class: "help-block" + end) + end + + @doc """ + Translates an error message using gettext. + """ + def translate_error({msg, opts}) do + # When using gettext, we typically pass the strings we want + # to translate as a static argument: + # + # # Translate "is invalid" in the "errors" domain + # dgettext "errors", "is invalid" + # + # # Translate the number of files with plural rules + # dngettext "errors", "1 file", "%{count} files", count + # + # Because the error messages we show in our forms and APIs + # are defined inside Ecto, we need to translate them dynamically. + # This requires us to call the Gettext module passing our gettext + # backend as first argument. + # + # Note we use the "errors" domain, which means translations + # should be written to the errors.po file. The :count option is + # set by Ecto and indicates we should also apply plural rules. + if count = opts[:count] do + Gettext.dngettext(HelloWeb.Gettext, "errors", msg, msg, count, opts) + else + Gettext.dgettext(HelloWeb.Gettext, "errors", msg, opts) + end + end +end diff --git a/serving/samples/helloworld-elixir/lib/hello_web/views/error_view.ex b/serving/samples/helloworld-elixir/lib/hello_web/views/error_view.ex new file mode 100644 index 000000000..90f183947 --- /dev/null +++ b/serving/samples/helloworld-elixir/lib/hello_web/views/error_view.ex @@ -0,0 +1,16 @@ +defmodule HelloWeb.ErrorView do + use HelloWeb, :view + + # If you want to customize a particular status code + # for a certain format, you may uncomment below. + # def render("500.html", _assigns) do + # "Internal Server Error" + # end + + # By default, Phoenix returns the status message from + # the template name. For example, "404.html" becomes + # "Not Found". + def template_not_found(template, _assigns) do + Phoenix.Controller.status_message_from_template(template) + end +end diff --git a/serving/samples/helloworld-elixir/lib/hello_web/views/hello_view.ex b/serving/samples/helloworld-elixir/lib/hello_web/views/hello_view.ex new file mode 100644 index 000000000..dc29df264 --- /dev/null +++ b/serving/samples/helloworld-elixir/lib/hello_web/views/hello_view.ex @@ -0,0 +1,3 @@ +defmodule HelloWeb.HelloView do + use HelloWeb, :view +end diff --git a/serving/samples/helloworld-elixir/lib/hello_web/views/layout_view.ex b/serving/samples/helloworld-elixir/lib/hello_web/views/layout_view.ex new file mode 100644 index 000000000..59c874284 --- /dev/null +++ b/serving/samples/helloworld-elixir/lib/hello_web/views/layout_view.ex @@ -0,0 +1,3 @@ +defmodule HelloWeb.LayoutView do + use HelloWeb, :view +end diff --git a/serving/samples/helloworld-elixir/lib/hello_web/views/page_view.ex b/serving/samples/helloworld-elixir/lib/hello_web/views/page_view.ex new file mode 100644 index 000000000..9a271179a --- /dev/null +++ b/serving/samples/helloworld-elixir/lib/hello_web/views/page_view.ex @@ -0,0 +1,3 @@ +defmodule HelloWeb.PageView do + use HelloWeb, :view +end diff --git a/serving/samples/helloworld-elixir/mix.exs b/serving/samples/helloworld-elixir/mix.exs new file mode 100644 index 000000000..6127c4c80 --- /dev/null +++ b/serving/samples/helloworld-elixir/mix.exs @@ -0,0 +1,44 @@ +defmodule Hello.Mixfile do + use Mix.Project + + def project do + [ + app: :hello, + version: "0.0.1", + elixir: "~> 1.4", + elixirc_paths: elixirc_paths(Mix.env), + compilers: [:phoenix, :gettext] ++ Mix.compilers, + start_permanent: Mix.env == :prod, + deps: deps() + ] + end + + # Configuration for the OTP application. + # + # Type `mix help compile.app` for more information. + def application do + [ + mod: {Hello.Application, []}, + extra_applications: [:logger, :runtime_tools] + ] + end + + # Specifies which paths to compile per environment. + defp elixirc_paths(:test), do: ["lib", "test/support"] + defp elixirc_paths(_), do: ["lib"] + + # Specifies your project dependencies. + # + # Type `mix help deps` for examples and options. + defp deps do + [ + {:phoenix, "~> 1.3.2"}, + {:phoenix_pubsub, "~> 1.0"}, + {:phoenix_html, "~> 2.10"}, + {:phoenix_live_reload, "~> 1.0", only: :dev}, + {:gettext, "~> 0.11"}, + {:cowboy, "~> 1.0"}, + {:distillery, "~> 1.5"} + ] + end +end diff --git a/serving/samples/helloworld-elixir/mix.lock b/serving/samples/helloworld-elixir/mix.lock new file mode 100644 index 000000000..f87e0b7e0 --- /dev/null +++ b/serving/samples/helloworld-elixir/mix.lock @@ -0,0 +1,15 @@ +%{ + "cowboy": {:hex, :cowboy, "1.1.2", "61ac29ea970389a88eca5a65601460162d370a70018afe6f949a29dca91f3bb0", [:rebar3], [{:cowlib, "~> 1.0.2", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3.2", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"}, + "cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], [], "hexpm"}, + "distillery": {:hex, :distillery, "1.5.2", "eec18b2d37b55b0bcb670cf2bcf64228ed38ce8b046bb30a9b636a6f5a4c0080", [:mix], [], "hexpm"}, + "file_system": {:hex, :file_system, "0.2.5", "a3060f063b116daf56c044c273f65202e36f75ec42e678dc10653056d3366054", [:mix], [], "hexpm"}, + "gettext": {:hex, :gettext, "0.15.0", "40a2b8ce33a80ced7727e36768499fc9286881c43ebafccae6bab731e2b2b8ce", [:mix], [], "hexpm"}, + "mime": {:hex, :mime, "1.3.0", "5e8d45a39e95c650900d03f897fbf99ae04f60ab1daa4a34c7a20a5151b7a5fe", [:mix], [], "hexpm"}, + "phoenix": {:hex, :phoenix, "1.3.2", "2a00d751f51670ea6bc3f2ba4e6eb27ecb8a2c71e7978d9cd3e5de5ccf7378bd", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.3.3 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"}, + "phoenix_html": {:hex, :phoenix_html, "2.11.2", "86ebd768258ba60a27f5578bec83095bdb93485d646fc4111db8844c316602d6", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"}, + "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.1.5", "8d4c9b1ef9ca82deee6deb5a038d6d8d7b34b9bb909d99784a49332e0d15b3dc", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.0 or ~> 1.2 or ~> 1.3", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm"}, + "phoenix_pubsub": {:hex, :phoenix_pubsub, "1.0.2", "bfa7fd52788b5eaa09cb51ff9fcad1d9edfeb68251add458523f839392f034c1", [:mix], [], "hexpm"}, + "plug": {:hex, :plug, "1.5.1", "1ff35bdecfb616f1a2b1c935ab5e4c47303f866cb929d2a76f0541e553a58165", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.3", [hex: :cowboy, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}], "hexpm"}, + "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"}, + "ranch": {:hex, :ranch, "1.3.2", "e4965a144dc9fbe70e5c077c65e73c57165416a901bd02ea899cfd95aa890986", [:rebar3], [], "hexpm"}, +} diff --git a/serving/samples/helloworld-elixir/priv/gettext/en/LC_MESSAGES/errors.po b/serving/samples/helloworld-elixir/priv/gettext/en/LC_MESSAGES/errors.po new file mode 100644 index 000000000..cdec3a113 --- /dev/null +++ b/serving/samples/helloworld-elixir/priv/gettext/en/LC_MESSAGES/errors.po @@ -0,0 +1,11 @@ +## `msgid`s in this file come from POT (.pot) files. +## +## Do not add, change, or remove `msgid`s manually here as +## they're tied to the ones in the corresponding POT file +## (with the same domain). +## +## Use `mix gettext.extract --merge` or `mix gettext.merge` +## to merge POT files into PO files. +msgid "" +msgstr "" +"Language: en\n" diff --git a/serving/samples/helloworld-elixir/priv/gettext/errors.pot b/serving/samples/helloworld-elixir/priv/gettext/errors.pot new file mode 100644 index 000000000..6988141a6 --- /dev/null +++ b/serving/samples/helloworld-elixir/priv/gettext/errors.pot @@ -0,0 +1,10 @@ +## This file is a PO Template file. +## +## `msgid`s here are often extracted from source code. +## Add new translations manually only if they're dynamic +## translations that can't be statically extracted. +## +## Run `mix gettext.extract` to bring this file up to +## date. Leave `msgstr`s empty as changing them here as no +## effect: edit them in PO (`.po`) files instead. + diff --git a/serving/samples/helloworld-elixir/rel/config.exs b/serving/samples/helloworld-elixir/rel/config.exs new file mode 100644 index 000000000..7452b3f5f --- /dev/null +++ b/serving/samples/helloworld-elixir/rel/config.exs @@ -0,0 +1,53 @@ +# Import all plugins from `rel/plugins` +# They can then be used by adding `plugin MyPlugin` to +# either an environment, or release definition, where +# `MyPlugin` is the name of the plugin module. +Path.join(["rel", "plugins", "*.exs"]) +|> Path.wildcard() +|> Enum.map(&Code.eval_file(&1)) + +use Mix.Releases.Config, + # This sets the default release built by `mix release` + default_release: :default, + # This sets the default environment used by `mix release` + default_environment: Mix.env() + +# For a full list of config options for both releases +# and environments, visit https://hexdocs.pm/distillery/configuration.html + + +# You may define one or more environments in this file, +# an environment's settings will override those of a release +# when building in that environment, this combination of release +# and environment configuration is called a profile + +environment :dev do + # If you are running Phoenix, you should make sure that + # server: true is set and the code reloader is disabled, + # even in dev mode. + # It is recommended that you build with MIX_ENV=prod and pass + # the --env flag to Distillery explicitly if you want to use + # dev mode. + set dev_mode: true + set include_erts: false + set cookie: :"Bps5@RVvPgL9c~C~D(DCQ5*Iu! Date: Wed, 8 Aug 2018 11:28:12 -0700 Subject: [PATCH 07/36] Split serving into two separate work groups: observability and networking. (#322) This is a continuation of https://github.com/knative/docs/pull/220 with merge conflicts fixed while Mustafa is out. --- community/WORKING-GROUPS.md | 57 ++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/community/WORKING-GROUPS.md b/community/WORKING-GROUPS.md index aa1c349e9..41f5dbe54 100644 --- a/community/WORKING-GROUPS.md +++ b/community/WORKING-GROUPS.md @@ -23,8 +23,9 @@ The current working groups are: * [API Core](#api-core) * [Build](#build) * [Events](#events) +* [Networking](#networking) +* [Observability](#observability) * [Scaling](#scaling) -* [Serving](#serving) ## API Core @@ -79,6 +80,42 @@ Slack Channel | [#eventing](https://knative.slack.com/messages/C9JP ------------------------------------------------------------- | ----------- | ------- | ------- | Ville Aikas | Google | [vaikas-google](https://github.com/vaikas-google) +## Networking + +Inbound and outbound network connectivity for [serving](https://github.com/knative/serving) workloads. +Specific areas of interest include: load balancing, routing, DNS configuration and TLS support. + +Artifact | Link +-------------------------- | ---- +Forum | [knative-dev@](https://groups.google.com/forum/#!forum/knative-dev) +Community Meeting VC | Coming soon +Community Meeting Calendar | Coming soon +Meeting Notes | [Notes](https://drive.google.com/open?id=1EE1t5mTfnTir2lEasdTMRNtuPEYuPqQCZbU3NC9mHOI) +Document Folder | [Folder](https://drive.google.com/corp/drive/folders/1oVDYbcEDdQ9EpUmkK6gE4C7aZ8u6ujsN) +Slack Channel | [#networking](https://knative.slack.com) + +  | Leads | Company | Profile +--------------------------------------------------------- | ---------------- | ------- | ------- + | Nghia Tran | Google | [tcnghia](https://github.com/tcnghia) + | Mustafa Demirhan | Google | [mdemirhan](https://github.com/mdemirhan) + +## Observability + +Logging, monitoring & tracing infrastructure + +Artifact | Link +-------------------------- | ---- +Forum | [knative-dev@](https://groups.google.com/forum/#!forum/knative-dev) +Community Meeting VC | https://meet.google.com/kik-btis-sqz
Or dial in:
(US) +1 515-705-3725
PIN: 704 774# +Community Meeting Calendar | [Calendar Invitation](https://calendar.google.com/event?action=TEMPLATE&tmeid=MDc4ZnRkZjFtbzZhZzBmdDMxYXBrM3B1YTVfMjAxODA4MDJUMTczMDAwWiBtZGVtaXJoYW5AZ29vZ2xlLmNvbQ&tmsrc=mdemirhan%40google.com&scp=ALL) +Meeting Notes | [Notes](https://drive.google.com/open?id=1vWEpjf093Jsih3mKkpIvmWWbUQPxFkcyDxzNH15rQgE) +Document Folder | [Folder](https://drive.google.com/corp/drive/folders/10HcpZlI1PbFyzinO6HjfHbzCkBXrqXMy) +Slack Channel | [#observability](https://knative.slack.com) + +  | Leads | Company | Profile +--------------------------------------------------------- | ---------------- | ------- | ------- + | Mustafa Demirhan | Google | [mdemirhan](https://github.com/mdemirhan) + ## Scaling Autoscaling @@ -96,24 +133,6 @@ Slack Channel | [#autoscaling](https://knative.slack.com) ------------------------------------------------------------- | -------------- | ------- | ------- | Joseph Burnett | Google | [josephburnett](https://github.com/josephburnett) -## Serving - -Logging infra, Monitoring infra, Trace, Load balancing/Istio, Domain names, -Routing, Observability - -Artifact | Link --------------------------- | ---- -Forum | [knative-dev@](https://groups.google.com/forum/#!forum/knative-dev) -Community Meeting VC | [TODO](TODO) -Community Meeting Calendar | [Calendar Invitation](TODO) -Meeting Notes | [Notes](TODO) -Document Folder | [Folder](https://drive.google.com/corp/drive/folders/1pfcc6z8oQl6S7bOl1MnfZJ2o32FtgvRB) -Slack Channel | [#metrics](https://knative.slack.com) - -  | Leads | Company | Profile ---------------------------------------------------------- | ---------------- | ------- | ------- - | Mustafa Demirhan | Google | [mdemirhan](https://github.com/mdemirhan) - --- Except as otherwise noted, the content of this page is licensed under the From 1f07a3da2244b7158ea3d20eabc449e8924e2a7e Mon Sep 17 00:00:00 2001 From: Jason Hall Date: Wed, 8 Aug 2018 15:15:12 -0400 Subject: [PATCH 08/36] Add glossary.md (#285) * Add glossary.md * Change to resouces.md, adding knctl, alphabetized --- resources.md | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 resources.md diff --git a/resources.md b/resources.md new file mode 100644 index 000000000..754959908 --- /dev/null +++ b/resources.md @@ -0,0 +1,132 @@ +# Resources + +This page contains informations about various tools and technologies +that are useful to anyone developing on Knative. + +## Community Resources + +This section contains tools and technologies developed by members of the +Knative community specifically for use with Knative. + +### [`knctl`](https://github.com/cppforlife/knctl) + +`knctl` is an under-development command line tool for working with +Knative. + +## Other Resources + +This section contains other tools and technologies that are useful when +working with Knative. + +### [`go-containerregistry`](https://github.com/google/go-containerregistry/) + +`go-containerregistry` is a Go library used by `ko`, `kaniko`, `skaffold` and +others, which enables support for pushing, pulling and managing images in a +container image registry, without requiring Docker to be installed. + +It also provides packages to interact with images in a local Docker daemon, +which does require that Docker be installed. + +This library also provides a CLI tool called +[`crane`](https://github.com/google/go-containerregistry/blob/master/cmd/crane/doc/crane.md), +which can be used to interact with and inspect images in a registry. + +### [`jib`](https://github.com/GoogleContainerTools/jib) + +`jib` is a tool, packaged as a Maven plugin and a Gradle plugin, that +efficiently builds container images from Java source, without a Dockerfile, +without requiring access to the Docker daemon. + +Like `ko`, when `jib` is invoked, it builds your Java source and pushes an +image with that built source atop a +[distroless](https://github.com/GoogleContainerTools/distroless) base image to +produce small images that support fast incremental image builds. + +There are `BuildTemplate`s that wraps `jib` for use with Maven and Gradle, at +https://github.com/knative/build-templates/blob/master/jib/. It expects that +your `pom.xml` or `build.gradle` describes to `jib` where to push your image. +The build templates take no parameters. + +### [`kaniko`](https://github.com/GoogleContainerTools/kaniko) + +`kaniko` is a tool that enables building a container image from source using +the Dockerfile format, without requiring access to a Docker daemon. Removing +this requirement means that `kaniko` is [safe to run on a Kubernetes +cluster](https://github.com/kubernetes/kubernetes/issues/1806). + +By contrast, building an image using `docker build` necessarily requires the +Docker daemon, which would give the build complete access to your entire +cluster. So that's a very bad idea. + +`kaniko` expects to run inside a container, so it's a natural fit for the Build +CRD [builder contract](...). `kaniko` is available as a builder at +`gcr.io/kaniko-project/executor:latest`, and there's a `BuildTemplate` that +wraps it at +https://github.com/knative/build-templates/blob/master/kaniko/kaniko.yaml. It +exposes one required parameter, `IMAGE`, which describes the name of the image +to push to. + +More information here: +https://github.com/knative/build-templates/tree/master/kaniko + +`kaniko` is unrelated to `ko`. + +### [`ko`](https://github.com/google/go-containerregistry/tree/master/cmd/ko) + +`ko` is a tool designed to make development of Go apps on Kubernetes easier, by +abstracting away the container image being used, and instead referring to Go +packages by their [import paths](https://golang.org/doc/code.html#ImportPaths) +(e.g., `github.com/kaniko/serving/cmd/controller`) + +The typical usage is `ko apply -f config.yaml`, which reads in the config YAML, +and looks for Go import paths representing runnable commands (i.e., `package +main`). When it finds a matching import path, `ko` builds the package using `go +build` then pushes a container image containing that binary on top of a base +image (by default, `gcr.io/distroless/base`) to +`$KO_DOCKER_REPO/unique-string`. After pushing those images, `ko` replaces +instances of matched import paths with fully-qualified references to the images +it pushed. + +So if `ko apply` was passed this config: + +```yaml +... +image: github.com/my/repo/cmd/foo +... +``` + +...it would produce YAML like: + +```yaml +... +image: gcr.io/my-docker-repo/foo-zyxwvut@sha256:abcdef # image by digest +... +``` + +(This assumes that you have set the environment variable +`KO_DOCKER_REPO=gcr.io/my-docker-repo`) + +`ko apply` then passes this generated YAML config to `kubectl apply`. + +`ko` also supports: +* `ko publish` to simply push images and not produce configs. +* `ko resolve` to push images and output the generated configs, but not +`kubectl apply` them. +* `ko delete` to simply passthrough to `kubectl delete` for convenience. + +`ko` is used during development and release of Knative components, but is not +intended to be required for _users_ of Knative -- they should only need to +`kubectl apply` released configs generated by `ko`. + +### [`skaffold`](https://github.com/GoogleContainerTools/skaffold) + +`skaffold` is a CLI tool to aid in iterative development for Kubernetes. +Typically, you would write a [YAML +config](https://github.com/GoogleContainerTools/skaffold/blob/master/examples/annotated-skaffold.yaml) +describing to Skaffold how to build and deploy your app, then run `skaffold +dev`, which will watch your local source tree for changes and continuously +builds and deploys based on your config when changes are detected. + +Skaffold supports many pluggable implementations for building and deploying. +Skaffold contributors are working on support for Knative Build as a build +plugin, and could support Knative Serving as a deployment plugin. From 435dfd7c87245ac274406ab5ccc052500469d6fd Mon Sep 17 00:00:00 2001 From: Sam O'Dell <31352624+samodell@users.noreply.github.com> Date: Wed, 8 Aug 2018 12:24:13 -0700 Subject: [PATCH 09/36] typo fix (#323) --- resources.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/resources.md b/resources.md index 754959908..ff0955fa9 100644 --- a/resources.md +++ b/resources.md @@ -1,6 +1,6 @@ # Resources -This page contains informations about various tools and technologies +This page contains information about various tools and technologies that are useful to anyone developing on Knative. ## Community Resources @@ -10,8 +10,7 @@ Knative community specifically for use with Knative. ### [`knctl`](https://github.com/cppforlife/knctl) -`knctl` is an under-development command line tool for working with -Knative. +`knctl` is an under-development CLI for working with Knative. ## Other Resources From 1a6bffa74209c19b05f9624531e7535d5d9fd8e2 Mon Sep 17 00:00:00 2001 From: Sam O'Dell <31352624+samodell@users.noreply.github.com> Date: Wed, 8 Aug 2018 16:41:05 -0700 Subject: [PATCH 10/36] Updates to clarify install instructions (#318) --- install/Knative-with-GKE.md | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/install/Knative-with-GKE.md b/install/Knative-with-GKE.md index 25ffbb6ae..c8ee136e8 100644 --- a/install/Knative-with-GKE.md +++ b/install/Knative-with-GKE.md @@ -14,12 +14,14 @@ specifications for Knative on Google Cloud Platform. This guide assumes you are using bash in a Mac or Linux environment; some commands will need to be adjusted for use in a Windows environment. -### Installing the Google Cloud SDK +### Installing the Google Cloud SDK and `kubectl` -1. If you already have `kubectl`, run `kubectl version` to check your client version. - -1. If you already have `gcloud` installed with the `kubectl` component later than - v1.10, you can skip these steps. +1. If you already have `gcloud` installed with `kubectl` version 1.10 or newer, + you can skip these steps. + > Tip: To check which version of `kubectl` you have installed, enter: + ``` + kubectl version + ``` 1. Download and install the `gcloud` command line tool: https://cloud.google.com/sdk/install @@ -137,22 +139,19 @@ rerun the command to see the current status. ## Installing Knative components -You have the option to install and use only the Knative components that you -want. You can install only the component of Knative if you need that -functionality, for example Knative serving is not required to create and run -builds. +You can install the Knative Serving and Build components together, or Build on its own. -### Installing Knative Serving +### Installing Knative Serving and Build components -1. Run the `kubectl apply` command to install - [Knative Serving](https://github.com/knative/serving) and its dependencies: +1. Run the `kubectl apply` command to install Knative and its dependencies: ```bash kubectl apply -f https://github.com/knative/serving/releases/download/v0.1.0/release.yaml ``` -1. Monitor the Knative serving components until all of the components show a +1. Monitor the Knative components until all of the components show a `STATUS` of `Running`: ```bash kubectl get pods -n knative-serving + kubectl get pods -n knative-build ``` ### Installing Knative Build @@ -178,7 +177,7 @@ the current status. You are now ready to deploy an app or create a build in your new Knative cluster. -## Deploying apps or builds +## What's next Now that your cluster has Knative installed, you're ready to deploy an app or create a build. @@ -193,8 +192,8 @@ for getting started: * You can view the available [sample apps](../serving/samples/README.md) and deploy one of your choosing. -* To get started by creating a build, see - [Creating a simple Knative Build](../build/creating-builds.md) +* You can follow the step-by-step + [Creating a simple Knative Build](../build/creating-builds.md) guide. ## Cleaning up From f912a204d689487db7d95b45a35d4d26fad84062 Mon Sep 17 00:00:00 2001 From: Sam O'Dell <31352624+samodell@users.noreply.github.com> Date: Wed, 8 Aug 2018 16:50:02 -0700 Subject: [PATCH 11/36] Updating app deployment guide (#320) * Updating app deployment guide Adds back manual options for figuring out the host URL and IP address, since all users should know how to see that information without having to export it into a variable. * Update getting-started-knative-app.md * Moving up note of delay of IP address assignment --- install/getting-started-knative-app.md | 46 ++++++++++++++++++++------ 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/install/getting-started-knative-app.md b/install/getting-started-knative-app.md index dd91fb7cd..012d7c32f 100644 --- a/install/getting-started-knative-app.md +++ b/install/getting-started-knative-app.md @@ -77,16 +77,26 @@ Now that your service is created, Knative will perform the following steps: To see if your app has been deployed succesfully, you need the host URL and IP address created by Knative. -1. To find the IP address for your service, enter - `kubectl get svc knative-ingressgateway -n istio-system`. If your cluster is - new, it can take sometime for the service to get asssigned an external IP address. +Note: If your cluster is new, it can take some time before the service is +asssigned an external IP address. + +1. To find the IP address for your service, enter: + + ```shell + kubectl get svc knative-ingressgateway -n istio-system + + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + knative-ingressgateway LoadBalancer 10.23.247.74 35.203.155.229 80:32380/TCP,443:32390/TCP,32400:32400/TCP 2d + + ``` + Take note of the `EXTERNAL-IP` address. + + You can also export the IP address as a variable with the following command: ```shell export IP_ADDRESS=$(kubectl get svc knative-ingressgateway -n istio-system -o 'jsonpath={.status.loadBalancer.ingress[0].ip}') ``` - - > Note: if you use minikube or a baremetal cluster that has no external load balancer, the `EXTERNAL-IP` field is shown as ``. You need to use `NodeIP` and `NodePort` to interact your app instead. To get your app's `NodeIP` and `NodePort`, enter the following command: @@ -96,26 +106,42 @@ IP address created by Knative. 1. To find the host URL for your service, enter: + ```shell + kubectl get services.serving.knative.dev helloworld-go -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain + NAME DOMAIN + helloworld-go helloworld-go.default.example.com + ``` + + You can also export the host URL as a variable using the following command: + ```shell export HOST_URL=$(kubectl get services.serving.knative.dev helloworld-go -o jsonpath='{.status.domain}') ``` If you changed the name from `helloworld-go` to something else when creating - the the `.yaml` file, replace `helloworld-go` in the above command with the + the `.yaml` file, replace `helloworld-go` in the above commands with the name you entered. -1. Now you can make a request to your app to see the results. Replace +1. Now you can make a request to your app and see the results. Replace `IP_ADDRESS` with the `EXTERNAL-IP` you wrote down, and replace `helloworld-go.default.example.com` with the domain returned in the previous step. - - If you deployed your own app, you may want to customize this cURL - request to interact with your application. + + ```shell + curl -H "Host: helloworld-go.default.example.com" http://IP_ADDRESS + Hello World: Go Sample v1! + ``` + + If you exported the host URL And IP address as variables in the previous steps, you + can use those variables to simplify your cURL request: ```shell curl -H "Host: ${HOST_URL}" http://${IP_ADDRESS} Hello World: Go Sample v1! ``` + + If you deployed your own app, you might want to customize this cURL + request to interact with your application. It can take a few seconds for Knative to scale up your application and return a response. From 42afa05d245d750f3b20f77c0dacd48976a7f347 Mon Sep 17 00:00:00 2001 From: Paul Morie Date: Wed, 8 Aug 2018 20:12:23 -0400 Subject: [PATCH 12/36] Correct typos in OpenShift instructions (#315) --- install/Knative-with-OpenShift.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/Knative-with-OpenShift.md b/install/Knative-with-OpenShift.md index db9eaea75..da45eb504 100644 --- a/install/Knative-with-OpenShift.md +++ b/install/Knative-with-OpenShift.md @@ -16,7 +16,7 @@ to test-drive knative. ## Install `oc` (openshift cli) -You can install the latest version of `oc`, the openshift CLI into your local +You can install the latest version of `oc`, the OpenShift CLI, into your local directory by downloading the right release tarball for your OS from the [releases page](https://github.com/openshift/origin/releases/tag/v3.10.0). From 581f9062df759b95a4235039075fba762b27f518 Mon Sep 17 00:00:00 2001 From: Eli Aleyner Date: Fri, 10 Aug 2018 12:33:55 -0400 Subject: [PATCH 13/36] Making a change to default azure location to reflect the correct Azure (#301) naming convention. --- install/Knative-with-AKS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/Knative-with-AKS.md b/install/Knative-with-AKS.md index 5c72d22d8..eb9c460eb 100644 --- a/install/Knative-with-AKS.md +++ b/install/Knative-with-AKS.md @@ -69,7 +69,7 @@ environment variables. First determine which region you'd like to run AKS in, al 1. Set `RESOURCE_GROUP` and `LOCATION` variables: ```bash - export LOCATION=east-us + export LOCATION=eastus export RESOURCE_GROUP=knative-group export CLUSTER_NAME=knative-cluster ``` From b8ceb247587a996e1207587c88f2a96f0a56f424 Mon Sep 17 00:00:00 2001 From: Justin Grayston Date: Fri, 10 Aug 2018 19:37:56 +0100 Subject: [PATCH 14/36] Add applying the knative route and config (#307) Closes #306 --- serving/samples/thumbnailer-go/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/serving/samples/thumbnailer-go/README.md b/serving/samples/thumbnailer-go/README.md index 6fce3399d..95a0b95ac 100644 --- a/serving/samples/thumbnailer-go/README.md +++ b/serving/samples/thumbnailer-go/README.md @@ -109,8 +109,12 @@ perl -pi -e "s@DOCKER_REPO_OVERRIDE@$REPO@g" sample.yaml # Install the Kaniko build template used to build this sample (in the # build-templates repo). kubectl apply -f https://raw.githubusercontent.com/knative/build-templates/master/kaniko/kaniko.yaml + +# Create the Knative route and configuration for the application +kubectl apply -f sample.yaml ``` + Now, if you look at the `status` of the revision, you will see that a build is in progress: ```shell From fb82eebfb498079922e95b27a150cc2c5ea8ba96 Mon Sep 17 00:00:00 2001 From: Sam O'Dell <31352624+samodell@users.noreply.github.com> Date: Fri, 10 Aug 2018 15:53:26 -0700 Subject: [PATCH 15/36] Sync install instructions with GKE version (#326) --- install/Knative-with-AKS.md | 35 +++++++++++++++++++------ install/Knative-with-GKE.md | 2 +- install/Knative-with-Gardener.md | 44 ++++++++++++++++++++++++-------- install/Knative-with-IKS.md | 39 ++++++++++++++++++++-------- install/Knative-with-PKS.md | 35 +++++++++++++++++++------ install/Knative-with-any-k8s.md | 37 +++++++++++++++++++-------- 6 files changed, 143 insertions(+), 49 deletions(-) diff --git a/install/Knative-with-AKS.md b/install/Knative-with-AKS.md index eb9c460eb..321fb6517 100644 --- a/install/Knative-with-AKS.md +++ b/install/Knative-with-AKS.md @@ -142,26 +142,45 @@ rerun the command to see the current status. > Note: Instead of rerunning the command, you can add `--watch` to the above command to view the component's status updates in real time. Use CTRL + C to exit watch mode. -## Installing Knative Serving +## Installing Knative components -1. Next, we will install [Knative Serving](https://github.com/knative/serving) -and its dependencies: +You can install the Knative Serving and Build components together, or Build on its own. + +### Installing Knative Serving and Build components + +1. Run the `kubectl apply` command to install Knative and its dependencies: ```bash kubectl apply -f https://github.com/knative/serving/releases/download/v0.1.0/release.yaml ``` -1. Monitor the Knative components, until all of the components show a `STATUS` of -`Running`: +1. Monitor the Knative components until all of the components show a + `STATUS` of `Running`: ```bash kubectl get pods -n knative-serving + kubectl get pods -n knative-build ``` +### Installing Knative Build only + +1. Run the `kubectl apply` command to install + [Knative Build](https://github.com/knative/build) and its dependencies: + ```bash + kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.0/third_party/config/build/release.yaml + ``` +1. Monitor the Knative Build components until all of the components show a + `STATUS` of `Running`: + ```bash + kubectl get pods -n knative-build + Just as with the Istio components, it will take a few seconds for the Knative -components to be up and running; you can rerun the command to see the current status. +components to be up and running; you can rerun the `kubectl get` command to see +the current status. > Note: Instead of rerunning the command, you can add `--watch` to the above - command to view the component's status updates in real time. Use CTRL + C to exit watch mode. + command to view the component's status updates in real time. Use CTRL + C to + exit watch mode. -You are now ready to deploy an app to your new Knative cluster. +You are now ready to deploy an app or create a build in your new Knative +cluster. ## Deploying an app diff --git a/install/Knative-with-GKE.md b/install/Knative-with-GKE.md index c8ee136e8..b21d1e90b 100644 --- a/install/Knative-with-GKE.md +++ b/install/Knative-with-GKE.md @@ -154,7 +154,7 @@ You can install the Knative Serving and Build components together, or Build on i kubectl get pods -n knative-build ``` -### Installing Knative Build +### Installing Knative Build only 1. Run the `kubectl apply` command to install [Knative Build](https://github.com/knative/build) and its dependencies: diff --git a/install/Knative-with-Gardener.md b/install/Knative-with-Gardener.md index 68790b3ea..c0f920466 100644 --- a/install/Knative-with-Gardener.md +++ b/install/Knative-with-Gardener.md @@ -87,23 +87,45 @@ rerun the command to see the current status. > command to view the component's status updates in real time. Use CTRL + C to > exit watch mode. -## Installing Knative Serving +## Installing Knative components -1. Next, we will install [Knative Serving](https://github.com/knative/serving) - and its dependencies: - `bash kubectl apply -f https://github.com/knative/serving/releases/download/v0.1.0/release.yaml` -1. Monitor the Knative components, until all of the components show a `STATUS` - of `Running`: `bash kubectl get pods -n knative-serving` +You can install the Knative Serving and Build components together, or Build on its own. + +### Installing Knative Serving and Build components + +1. Run the `kubectl apply` command to install Knative and its dependencies: + ```bash + kubectl apply -f https://github.com/knative/serving/releases/download/v0.1.0/release.yaml + ``` +1. Monitor the Knative components until all of the components show a + `STATUS` of `Running`: + ```bash + kubectl get pods -n knative-serving + kubectl get pods -n knative-build + ``` + +### Installing Knative Build only + +1. Run the `kubectl apply` command to install + [Knative Build](https://github.com/knative/build) and its dependencies: + ```bash + kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.0/third_party/config/build/release.yaml + ``` +1. Monitor the Knative Build components until all of the components show a + `STATUS` of `Running`: + ```bash + kubectl get pods -n knative-build Just as with the Istio components, it will take a few seconds for the Knative -components to be up and running; you can rerun the command to see the current -status. +components to be up and running; you can rerun the `kubectl get` command to see +the current status. > Note: Instead of rerunning the command, you can add `--watch` to the above -> command to view the component's status updates in real time. Use CTRL + C to -> exit watch mode. + command to view the component's status updates in real time. Use CTRL + C to + exit watch mode. -You are now ready to deploy an app to your new Knative cluster. +You are now ready to deploy an app or create a build in your new Knative +cluster. ## Alternative way to enable Knative with Gardener diff --git a/install/Knative-with-IKS.md b/install/Knative-with-IKS.md index fe76404ea..4433ced89 100644 --- a/install/Knative-with-IKS.md +++ b/install/Knative-with-IKS.md @@ -145,28 +145,45 @@ rerun the command to see the current status. > command to view the component's status updates in real time. Use CTRL+C to > exit watch mode. -## Installing Knative Serving +## Installing Knative components -1. Next, we will install [Knative Serving](https://github.com/knative/serving) - and its dependencies: +You can install the Knative Serving and Build components together, or Build on its own. + +### Installing Knative Serving and Build components + +1. Run the `kubectl apply` command to install Knative and its dependencies: ```bash kubectl apply -f https://github.com/knative/serving/releases/download/v0.1.0/release.yaml ``` -1. Monitor the Knative components until all of the components show a `STATUS` - of `Running`: +1. Monitor the Knative components until all of the components show a + `STATUS` of `Running`: ```bash kubectl get pods -n knative-serving + kubectl get pods -n knative-build ``` +### Installing Knative Build only + +1. Run the `kubectl apply` command to install + [Knative Build](https://github.com/knative/build) and its dependencies: + ```bash + kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.0/third_party/config/build/release.yaml + ``` +1. Monitor the Knative Build components until all of the components show a + `STATUS` of `Running`: + ```bash + kubectl get pods -n knative-build + Just as with the Istio components, it will take a few seconds for the Knative -components to be up and running; you can rerun the command to see the current -status. +components to be up and running; you can rerun the `kubectl get` command to see +the current status. -> Note: Instead of re-running the command, you can add `--watch` to the above -> command to view the component's status updates in real time. Use CTRL+C to -> exit watch mode. +> Note: Instead of rerunning the command, you can add `--watch` to the above + command to view the component's status updates in real time. Use CTRL + C to + exit watch mode. -You are now ready to deploy an app to your new Knative cluster. +You are now ready to deploy an app or create a build in your new Knative +cluster. ## Deploying an app diff --git a/install/Knative-with-PKS.md b/install/Knative-with-PKS.md index 11eb219eb..e60332dc4 100644 --- a/install/Knative-with-PKS.md +++ b/install/Knative-with-PKS.md @@ -50,26 +50,45 @@ rerun the command to see the current status. > Note: Instead of rerunning the command, you can add `--watch` to the above command to view the component's status updates in real time. Use CTRL + C to exit watch mode. -## Installing Knative Serving +## Installing Knative components -1. Next, we will install [Knative Serving](https://github.com/knative/serving) -and its dependencies: +You can install the Knative Serving and Build components together, or Build on its own. + +### Installing Knative Serving and Build components + +1. Run the `kubectl apply` command to install Knative and its dependencies: ```bash kubectl apply -f https://github.com/knative/serving/releases/download/v0.1.0/release.yaml ``` -1. Monitor the Knative components, until all of the components show a `STATUS` of -`Running`: +1. Monitor the Knative components until all of the components show a + `STATUS` of `Running`: ```bash kubectl get pods -n knative-serving + kubectl get pods -n knative-build ``` +### Installing Knative Build only + +1. Run the `kubectl apply` command to install + [Knative Build](https://github.com/knative/build) and its dependencies: + ```bash + kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.0/third_party/config/build/release.yaml + ``` +1. Monitor the Knative Build components until all of the components show a + `STATUS` of `Running`: + ```bash + kubectl get pods -n knative-build + Just as with the Istio components, it will take a few seconds for the Knative -components to be up and running; you can rerun the command to see the current status. +components to be up and running; you can rerun the `kubectl get` command to see +the current status. > Note: Instead of rerunning the command, you can add `--watch` to the above - command to view the component's status updates in real time. Use CTRL + C to exit watch mode. + command to view the component's status updates in real time. Use CTRL + C to + exit watch mode. -You are now ready to deploy an app to your new Knative cluster. +You are now ready to deploy an app or create a build in your new Knative +cluster. ## Deploying an app diff --git a/install/Knative-with-any-k8s.md b/install/Knative-with-any-k8s.md index fbcf20678..7f79ca022 100644 --- a/install/Knative-with-any-k8s.md +++ b/install/Knative-with-any-k8s.md @@ -35,28 +35,45 @@ rerun the command to see the current status. > command to view the component's status updates in real time. Use CTRL + C to > exit watch mode. -## Installing Knative Serving +## Installing Knative components -1. Next, we will install [Knative Serving](https://github.com/knative/serving) - and its dependencies: +You can install the Knative Serving and Build components together, or Build on its own. + +### Installing Knative Serving and Build components + +1. Run the `kubectl apply` command to install Knative and its dependencies: ```bash kubectl apply -f https://github.com/knative/serving/releases/download/v0.1.0/release.yaml ``` -1. Monitor the Knative components, until all of the components show a `STATUS` - of `Running`: +1. Monitor the Knative components until all of the components show a + `STATUS` of `Running`: ```bash kubectl get pods -n knative-serving + kubectl get pods -n knative-build ``` +### Installing Knative Build only + +1. Run the `kubectl apply` command to install + [Knative Build](https://github.com/knative/build) and its dependencies: + ```bash + kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.0/third_party/config/build/release.yaml + ``` +1. Monitor the Knative Build components until all of the components show a + `STATUS` of `Running`: + ```bash + kubectl get pods -n knative-build + Just as with the Istio components, it will take a few seconds for the Knative -components to be up and running; you can rerun the command to see the current -status. +components to be up and running; you can rerun the `kubectl get` command to see +the current status. > Note: Instead of rerunning the command, you can add `--watch` to the above -> command to view the component's status updates in real time. Use CTRL + C to -> exit watch mode. + command to view the component's status updates in real time. Use CTRL + C to + exit watch mode. -You are now ready to deploy an app to your new Knative cluster. +You are now ready to deploy an app or create a build in your new Knative +cluster. ## Deploying an app From 8a96ccc39fcb048752d798656b9b87e4db15096d Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Mon, 13 Aug 2018 03:34:55 -0700 Subject: [PATCH 16/36] Update Telemetry readmes (#248) * telemetry draft * style updates to logging pages * moved elasticsearch instructions * telemetry draft * style updates to logging pages * moved elasticsearch instructions * move elastic search instructions back to installation page * Add more details to specific steps * fix markdown --- serving/accessing-logs.md | 146 ++++++++------- serving/accessing-metrics.md | 33 ++-- serving/installing-logging-metrics-traces.md | 132 ++++++++----- serving/samples/telemetry-go/README.md | 175 ++++++++++++------ .../{configuration.yaml => sample.yaml} | 0 5 files changed, 298 insertions(+), 188 deletions(-) rename serving/samples/telemetry-go/{configuration.yaml => sample.yaml} (100%) diff --git a/serving/accessing-logs.md b/serving/accessing-logs.md index 2575ee10e..4115ff2a5 100644 --- a/serving/accessing-logs.md +++ b/serving/accessing-logs.md @@ -1,110 +1,116 @@ # Accessing logs -If you have not yet installed the logging and monitoring components, go through the -[installation instructions](./installing-logging-metrics-traces.md) to set up the +If you have not yet installed the logging and monitoring components, go through the +[installation instructions](./installing-logging-metrics-traces.md) to set up the necessary components first. ## Kibana and Elasticsearch -To open the Kibana UI (the visualization tool for [Elasticsearch](https://info.elastic.co), -enter the following command: +* To open the Kibana UI (the visualization tool for [Elasticsearch](https://info.elastic.co)), +start a local proxy with the following command: + ```shell + kubectl proxy + ``` -```shell -kubectl proxy -``` + This command starts a local proxy of Kibana on port 8001. For security reasons, + the Kibana UI is exposed only within the cluster. -This command starts a local proxy of Kibana on port 8001. For security reasons, the -Kibana UI is exposed only within the cluster. +* Navigate to the +[Kibana UI](http://localhost:8001/api/v1/namespaces/monitoring/services/kibana-logging/proxy/app/kibana). +*It might take a couple of minutes for the proxy to work*. -Navigate to the -[Kibana UI](http://localhost:8001/api/v1/namespaces/monitoring/services/kibana-logging/proxy/app/kibana) - (*It might take a couple of minutes for the proxy to work*). + The Discover tab of the Kibana UI looks like this: -The Discover tab of the Kibana UI looks like this: + ![Kibana UI Discover tab](./images/kibana-discover-tab-annotated.png) -![Kibana UI Discover tab](./images/kibana-discover-tab-annotated.png) + You can change the time frame of logs Kibana displays in the upper right corner + of the screen. The main search bar is across the top of the Discover page. -You can change the time frame of logs Kibana displays in the upper right corner -of the screen. The main search bar is across the top of the Discover page. - -As more logs are ingested, new fields will be discovered. To have them indexed, -go to Management > Index Patterns > Refresh button (on top right) > Refresh -fields. +* As more logs are ingested, new fields will be discovered. To have them indexed, +go to "Management" > "Index Patterns" > Refresh button (on top right) > "Refresh +fields". ### Accessing configuration and revision logs -To access the logs for a configuration, enter the following search query in Kibana: +To access the logs for a configuration: -```text -kubernetes.labels.serving_knative_dev\/configuration: "configuration-example" +* Find the configuration's name with the following command: ``` - -Replace `configuration-example` with your configuration's name. Enter the following -command to get your configuration's name: - -```shell kubectl get configurations ``` -To access logs for a revision, enter the following search query in Kibana: - -```text -kubernetes.labels.serving_knative_dev\/revision: "configuration-example-00001" +* Replace `` and enter the following search query in Kibana: +``` +kubernetes.labels.serving_knative_dev\/configuration: ``` -Replace `configuration-example-00001` with your revision's name. +To access logs for a revision: +* Find the revision's name with the following command: +``` +kubectl get revisions +``` + +* Replace `` and enter the following search query in Kibana: +``` +kubernetes.labels.serving_knative_dev\/revision: +``` ### Accessing build logs -To access the logs for a build, enter the following search query in Kibana: +To access logs for a [Knative Build](../build/README.md): -```text -kubernetes.labels.build\-name: "test-build" +* Find the build's name in the specified in the `.yaml` file: + ```yaml + apiVersion: build.knative.dev/v1alpha1 + kind: Build + metadata: + name: + ``` + Or find build names with the following command: + ``` + kubectl get builds + ``` + +* Replace `` and enter the following search query in Kibana: ``` - -Replace `test-build` with your build's name. The build name is specified in the `.yaml` file as follows: - -```yaml -apiVersion: build.knative.dev/v1alpha1 -kind: Build -metadata: - name: test-build +kubernetes.labels.build\-name: ``` ### Accessing request logs -To access to request logs, enter the following search in Kibana: - -```text +To access to request logs: +* Enter the following search in Kibana: +``` tag: "requestlog.logentry.istio-system" ``` -Request logs contain details about requests served by the revision. Below is a sample request log: + Request logs contain details about requests served by the revision. Below is + a sample request log: -```text -@timestamp July 10th 2018, 10:09:28.000 -destinationConfiguration configuration-example -destinationNamespace default -destinationRevision configuration-example-00001 -destinationService configuration-example-00001-service.default.svc.cluster.local -latency 1.232902ms -method GET -protocol http -referer unknown -requestHost route-example.default.example.com -requestSize 0 -responseCode 200 -responseSize 36 -severity Info -sourceNamespace istio-system -sourceService unknown -tag requestlog.logentry.istio-system -traceId 986d6faa02d49533 -url / -userAgent curl/7.60.0 -``` + ```text + @timestamp July 10th 2018, 10:09:28.000 + destinationConfiguration configuration-example + destinationNamespace default + destinationRevision configuration-example-00001 + destinationService configuration-example-00001-service.default.svc.cluster.local + latency 1.232902ms + method GET + protocol http + referer unknown + requestHost route-example.default.example.com + requestSize 0 + responseCode 200 + responseSize 36 + severity Info + sourceNamespace istio-system + sourceService unknown + tag requestlog.logentry.istio-system + traceId 986d6faa02d49533 + url / + userAgent curl/7.60.0 + ``` ### Accessing end to end request traces diff --git a/serving/accessing-metrics.md b/serving/accessing-metrics.md index f1a1f86aa..374977e24 100644 --- a/serving/accessing-metrics.md +++ b/serving/accessing-metrics.md @@ -1,30 +1,31 @@ # Accessing metrics -You access metrics through the [Grafana](https://grafana.com/) UI. Grafana is the visualization tool -for [Prometheus](https://prometheus.io/). To open Grafana, enter the following command: +You access metrics through the [Grafana](https://grafana.com/) UI. Grafana is +the visualization tool for [Prometheus](https://prometheus.io/). -```shell +1. To open Grafana, enter the following command: +``` kubectl port-forward -n monitoring $(kubectl get pods -n monitoring --selector=app=grafana --output=jsonpath="{.items..metadata.name}") 3000 ``` -This starts a local proxy of Grafana on port 3000. For security reasons, the Grafana UI is exposed only within -the cluster. + * This starts a local proxy of Grafana on port 3000. For security reasons, the Grafana UI is exposed only within the cluster. -Navigate to the Grafana UI at [http://localhost:3000](http://localhost:3000). -Select the **Home** button on the top of the page to see the list of pre-installed dashboards (screenshot below): +2. Navigate to the Grafana UI at [http://localhost:3000](http://localhost:3000). + +3. Select the **Home** button on the top of the page to see the list of pre-installed dashboards (screenshot below): ![Knative Dashboards](./images/grafana1.png) -The following dashboards are pre-installed with Knative Serving: + The following dashboards are pre-installed with Knative Serving: -* **Revision HTTP Requests:** HTTP request count, latency, and size metrics per revision and per configuration -* **Nodes:** CPU, memory, network, and disk metrics at node level -* **Pods:** CPU, memory, and network metrics at pod level -* **Deployment:** CPU, memory, and network metrics aggregated at deployment level -* **Istio, Mixer and Pilot:** Detailed Istio mesh, Mixer, and Pilot metrics -* **Kubernetes:** Dashboards giving insights into cluster health, deployments, and capacity usage + * **Revision HTTP Requests:** HTTP request count, latency, and size metrics per revision and per configuration + * **Nodes:** CPU, memory, network, and disk metrics at node level + * **Pods:** CPU, memory, and network metrics at pod level + * **Deployment:** CPU, memory, and network metrics aggregated at deployment level + * **Istio, Mixer and Pilot:** Detailed Istio mesh, Mixer, and Pilot metrics + * **Kubernetes:** Dashboards giving insights into cluster health, deployments, and capacity usage -To sign in as an administrator and modify or add dashboards, sign in with username `admin` and password `admin`. -Before you expose the Grafana UI outside the cluster, make sure to change the password. +4. Set up an administrator account to modify or add dashboards by signing in with username: `admin` and password: `admin`. + * Before you expose the Grafana UI outside the cluster, make sure to change the password. --- diff --git a/serving/installing-logging-metrics-traces.md b/serving/installing-logging-metrics-traces.md index 18f22c0b3..1b930943c 100644 --- a/serving/installing-logging-metrics-traces.md +++ b/serving/installing-logging-metrics-traces.md @@ -1,72 +1,112 @@ # Monitoring, Logging and Tracing Installation -Knative Serving offers two different monitoring setups: -One that uses Elasticsearch, Kibana, Prometheus and Grafana and -another that uses Stackdriver, Prometheus and Grafana. See below -for installation instructions for these two setups. You can install -only one of these two setups and side-by-side installation of these two are not supported. +Knative Serving offers two different monitoring setups: +[Elasticsearch, Kibana, Prometheus and Grafana](#Elasticsearch,-Kibana,-Prometheus-&-Grafana-Setup) +or +[Stackdriver, Prometheus and Grafana](#Stackdriver,-Prometheus-&-Grafana-Setup). +You can install only one of these two setups and side-by-side installation of +these two are not supported. ## Elasticsearch, Kibana, Prometheus & Grafana Setup -*If you installed Knative Serving using [Easy Install](../install/README.md#Installing-Knative) guide, -skip this step and continue to [Create Elasticsearch Indices](#Create-Elasticsearch-Indices)* +If you installed the +[full Knative release](../install/README.md#Installing-Knative), +skip this step and continue to +[Create Elasticsearch Indices](#Create-Elasticsearch-Indices) +- Install Knative monitoring components: -Run: + ```shell + kubectl apply -R -f config/monitoring/100-common \ + -f config/monitoring/150-elasticsearch \ + -f third_party/config/monitoring/common \ + -f third_party/config/monitoring/elasticsearch \ + -f config/monitoring/200-common \ + -f config/monitoring/200-common/100-istio.yaml + ``` -```shell -kubectl apply -R -f config/monitoring/100-common \ - -f config/monitoring/150-elasticsearch \ - -f third_party/config/monitoring/common \ - -f third_party/config/monitoring/elasticsearch \ - -f config/monitoring/200-common \ - -f config/monitoring/200-common/100-istio.yaml -``` +- The installation is complete when logging & monitoring components are all + reported `Running` or `Completed`: -Monitor logging & monitoring components, until all of the components report Running or Completed: + ```shell + kubectl get pods -n monitoring --watch + ``` -```shell -kubectl get pods -n monitoring --watch -``` + ``` + NAME READY STATUS RESTARTS AGE + elasticsearch-logging-0 1/1 Running 0 2d + elasticsearch-logging-1 1/1 Running 0 2d + fluentd-ds-5kc85 1/1 Running 0 2d + fluentd-ds-vhrcq 1/1 Running 0 2d + fluentd-ds-xghk9 1/1 Running 0 2d + grafana-798cf569ff-v4q74 1/1 Running 0 2d + kibana-logging-7d474fbb45-6qb8x 1/1 Running 0 2d + kube-state-metrics-75bd4f5b8b-8t2h2 4/4 Running 0 2d + node-exporter-cr6bh 2/2 Running 0 2d + node-exporter-mf6k7 2/2 Running 0 2d + node-exporter-rhzr7 2/2 Running 0 2d + prometheus-system-0 1/1 Running 0 2d + prometheus-system-1 1/1 Running 0 2d + ``` -CTRL+C when it's done. + CTRL+C to exit watch. ### Create Elasticsearch Indices -We will create two indexes in ElasticSearch - one for application logs and one for request traces. -To create the indexes, open Kibana Index Management UI at this [link](http://localhost:8001/api/v1/namespaces/monitoring/services/kibana-logging/proxy/app/kibana#/management/kibana/index) -(*it might take a couple of minutes for the proxy to work the first time after the installation*). -Within the "Configure an index pattern" page, enter `logstash-*` to `Index pattern` and select `@timestamp` -from `Time Filter field name` and click on `Create` button. See below for a screenshot: +To visualize logs with Kibana, you need to set which Elasticsearch indices to explore. We will create two indices in Elasticsearch using `Logstash` for application logs and `Zipkin` +for request traces. + +- To open the Kibana UI (the visualization tool for + [Elasticsearch](https://info.elastic.co)), start a local proxy with the + following command: + + ```shell + kubectl proxy + ``` + + This command starts a local proxy of Kibana on port 8001. For security + reasons, the Kibana UI is exposed only within the cluster. + +- Navigate to the + [Kibana UI](http://localhost:8001/api/v1/namespaces/monitoring/services/kibana-logging/proxy/app/kibana). + _It might take a couple of minutes for the proxy to work_. + +- Within the "Configure an index pattern" page, enter `logstash-*` to + `Index pattern` and select `@timestamp` from `Time Filter field name` and + click on `Create` button. ![Create logstash-* index](images/kibana-landing-page-configure-index.png) -To create the second index, select `Create Index Pattern` button on top left of the page. -Enter `zipkin*` to `Index pattern` and select `timestamp_millis` from `Time Filter field name` -and click on `Create` button. +- To create the second index, select `Create Index Pattern` button on top left + of the page. Enter `zipkin*` to `Index pattern` and select `timestamp_millis` + from `Time Filter field name` and click on `Create` button. -Next, visit instructions below to access to logs, metrics and traces: -* [Accessing Logs](./accessing-logs.md) -* [Accessing Metrics](./accessing-metrics.md) -* [Accessing Traces](./accessing-traces.md) +## Stackdriver, Prometheus & Grafana Setup -## Stackdriver(logs), Prometheus & Grafana Setup +If your Knative Serving is not built on a Google Cloud Platform (GCP) based +cluster or you want to send logs to another GCP project, you need to build your +own Fluentd image and modify the configuration first. See -If your Knative Serving is not built on a GCP based cluster or you want to send logs to -another GCP project, you need to build your own Fluentd image and modify the -configuration first. See +1. Install + [Fluentd image on Knative Serving](https://github.com/knative/serving/blob/master/image/fluentd/README.md). +2. [Set up a logging plugin](setting-up-a-logging-plugin.md). +3. Install Knative monitoring components: -1. [Fluentd image on Knative Serving](/image/fluentd/README.md) -2. [Setting up a logging plugin](setting-up-a-logging-plugin.md) + ```shell + kubectl apply -R -f config/monitoring/100-common \ + -f config/monitoring/150-stackdriver-prod \ + -f third_party/config/monitoring/common \ + -f config/monitoring/200-common \ + -f config/monitoring/200-common/100-istio.yaml + ``` -```shell -kubectl apply -R -f config/monitoring/100-common \ - -f config/monitoring/150-stackdriver \ - -f third_party/config/monitoring/common \ - -f config/monitoring/200-common \ - -f config/monitoring/200-common/100-istio.yaml -``` +## Learn More + +- Learn more about accessing logs, metrics, and traces: + - [Accessing Logs](./accessing-logs.md) + - [Accessing Metrics](./accessing-metrics.md) + - [Accessing Traces](./accessing-traces.md) --- diff --git a/serving/samples/telemetry-go/README.md b/serving/samples/telemetry-go/README.md index f904c0e1c..aee717105 100644 --- a/serving/samples/telemetry-go/README.md +++ b/serving/samples/telemetry-go/README.md @@ -2,100 +2,163 @@ This sample runs a simple web server that makes calls to other in-cluster services and responds to requests with "Hello World!". -The purpose of this sample is to show generating metrics, logs and distributed traces -(see [Logs](../../accessing-logs.md), [Metrics](../../accessing-metrics.md), and [Traces](../../accessing-traces.md) for more information). -This sample also creates a dedicated Prometheus instances rather than using the one -that is installed by default as a showcase of installing dedicated Prometheus instances. +The purpose of this sample is to show generating [metrics](../../accessing-metrics.md), +[logs](../../accessing-logs.md) and distributed [traces](../../accessing-traces.md). +This sample also shows how to create a dedicated Prometheus instance rather than +using the default installation. ## Prerequisites -1. [Install Knative Serving](https://github.com/knative/docs/blob/master/install/README.md) -2. [Install Knative monitoring component](../../installing-logging-metrics-traces.md) -3. Install [docker](https://www.docker.com/) - +1. A Kubernetes cluster with [Knative Serving](https://github.com/knative/docs/blob/master/install/README.md) +installed. +2. Check if Knative monitoring components are installed: +``` +kubectl get pods -n monitoring +``` + * If pods aren't found, install [Knative monitoring component](../../installing-logging-metrics-traces.md). +3. Install [Docker](https://docs.docker.com/get-started/#prepare-your-docker-environment). +4. Check out the code: +``` +go get -d github.com/knative/docs/serving/samples/telemetry-go +``` ## Setup -Build the app container and publish it to your registry of choice: +Build the application container and publish it to a container registry: -```shell -REPO="gcr.io/" +1. Move into the sample directory: +``` +cd $GOPATH/src/github.com/knative/docs +``` -# Build and publish the container, run from the root directory. +2. Set your preferred container registry: +``` +export REPO="gcr.io/" +``` + This example shows how to use Google Container Registry (GCR). You will need + a Google Cloud Project and to enable the [Google Container Registry +API](https://console.cloud.google.com/apis/library/containerregistry.googleapis.com). + +3. Use Docker to build your application container: +``` docker build \ --tag "${REPO}/serving/samples/telemetry-go" \ --file=serving/samples/telemetry-go/Dockerfile . +``` + +4. Push your container to a container registry: +``` docker push "${REPO}/serving/samples/telemetry-go" +``` -# Replace the image reference with our published image. -perl -pi -e "s@github.com/knative/docs/serving/samples/telemetry-go@${REPO}/serving/samples/telemetry-go@g" serving/samples/telemetry-go/*.yaml +5. Replace the image reference path with our published image path in the +configuration file (`serving/samples/telemetry-go/sample.yaml`): + * Manually replace: + `image: github.com/knative/docs/serving/samples/telemetry-go` with + `image: /serving/samples/telemetry-go` -# Deploy the Knative Serving sample + Or + + * Use run this command: + ``` + perl -pi -e "s@github.com/knative/docs@${REPO}@g" serving/samples/telemetry-go/sample.yaml + ``` + +## Deploy the Service + +Deploy this application to Knative Serving: +``` kubectl apply -f serving/samples/telemetry-go/ ``` -## Exploring +## Explore the Service -Once deployed, you can inspect the created resources with `kubectl` commands: +Inspect the created resources with the `kubectl` commands: -```shell -# This will show the route that we created: -kubectl get route -o yaml + * View the created Route resource: + ``` + kubectl get route -o yaml + ``` -# This will show the configuration that we created: -kubectl get configurations -o yaml + * View the created Configuration resource: + ``` + kubectl get configurations -o yaml + ``` -# This will show the Revision that was created by our configuration: -kubectl get revisions -o yaml + * View the Revision that was created by the Configuration: + ``` + kubectl get revisions -o yaml + ``` + +## Access the Service + +To access this service via `curl`, you need to determine its ingress address. + +1. To determine if your service is ready: + Check the status of your Knative gateway: + ``` + kubectl get svc knative-ingressgateway -n istio-system --watch + ``` + + When the service is ready, you'll see an IP address in the `EXTERNAL-IP` field: + ``` + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + knative-ingressgateway LoadBalancer 10.23.247.74 35.203.155.229 80:32380/TCP,443:32390/TCP,32400:32400/TCP 2d + ``` + CTRL+C to end watch. + + Check the status of your route: + ``` + kubectl get route -o yaml + ``` + When the route is ready, you'll see the following fields reported as: + ```YAML + status: + conditions: + ... + status: "True" + type: Ready + domain: telemetrysample-route.default.example.com + ``` + +2. Export the ingress hostname and IP as environment +variables: ``` - -To access this service via `curl`, we first need to determine its ingress address: -```shell -watch kubectl get svc knative-ingressgateway -n istio-system -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -knative-ingressgateway LoadBalancer 10.23.247.74 35.203.155.229 80:32380/TCP,443:32390/TCP,32400:32400/TCP 2d -``` - -Once the `EXTERNAL-IP` gets assigned to the cluster, you can run: - -```shell -# Put the Host name into an environment variable. export SERVICE_HOST=`kubectl get route telemetrysample-route -o jsonpath="{.status.domain}"` - -# Put the ingress IP into an environment variable. export SERVICE_IP=`kubectl get svc knative-ingressgateway -n istio-system -o jsonpath="{.status.loadBalancer.ingress[*].ip}"` +``` -# Curl the ingress IP "as-if" DNS were properly configured. +3. Make a request to the service to see the `Hello World!` message: +``` curl --header "Host:$SERVICE_HOST" http://${SERVICE_IP} -Hello World! ``` -Generate some logs to STDOUT and files under `/var/log` in `Json` or plain text formats. - -```shell +4. Make a request to the `/log` endpoint to generate logs to the `stdout` file +and generate files under `/var/log` in both `JSON` and plain text formats: +``` curl --header "Host:$SERVICE_HOST" http://${SERVICE_IP}/log -Sending logs done. ``` -## Accessing logs -You can access to the logs from Kibana UI - see [Logs](../../accessing-logs.md) for more information. +## Access Logs +You can access to the logs from Kibana UI - see [Logs](../../accessing-logs.md) +for more information. -## Accessing per request traces -You can access to per request traces from Zipkin UI - see [Traces](../../accessing-traces.md) for more information. +## Access per Request Traces +You can access to per request traces from Zipkin UI - see [Traces](../../accessing-traces.md) +for more information. -## Accessing custom metrics -You can see published metrics using Prometheus UI. To access to the UI, forward the Prometheus server to your machine: - -```bash +## Accessing Custom Metrics +You can see published metrics using Prometheus UI. To access to the UI, forward +the Prometheus server to your machine: +``` kubectl port-forward $(kubectl get pods --selector=app=prometheus,prometheus=test --output=jsonpath="{.items[0].metadata.name}") 9090 ``` Then browse to http://localhost:9090. -## Cleaning up +## Clean up To clean up the sample service: - -```shell -kubectl delete -f serving/samples/telemetrysample-go/ +``` +kubectl delete -f serving/samples/telemetry-go/ ``` diff --git a/serving/samples/telemetry-go/configuration.yaml b/serving/samples/telemetry-go/sample.yaml similarity index 100% rename from serving/samples/telemetry-go/configuration.yaml rename to serving/samples/telemetry-go/sample.yaml From c69898d06ab30611fec951c005c855924e158037 Mon Sep 17 00:00:00 2001 From: Babatunde Olu-Isa Date: Mon, 13 Aug 2018 10:40:55 -0500 Subject: [PATCH 17/36] Update accessing-logs.md (#327) removed typo from document. --- serving/accessing-logs.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/serving/accessing-logs.md b/serving/accessing-logs.md index 4115ff2a5..9a7f4473e 100644 --- a/serving/accessing-logs.md +++ b/serving/accessing-logs.md @@ -80,9 +80,9 @@ kubernetes.labels.build\-name: ### Accessing request logs -To access to request logs: -* Enter the following search in Kibana: -``` +To access the request logs, enter the following search in Kibana: + +```text tag: "requestlog.logentry.istio-system" ``` From 258d5c040c3052d3b83f4a48873b28da38fe5fd4 Mon Sep 17 00:00:00 2001 From: doddatpivotal <37634387+doddatpivotal@users.noreply.github.com> Date: Mon, 13 Aug 2018 14:25:55 -0400 Subject: [PATCH 18/36] Clarifies working directory to run command (#329) * Clarifies working directory to run command * Add link to Serving --- serving/installing-logging-metrics-traces.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serving/installing-logging-metrics-traces.md b/serving/installing-logging-metrics-traces.md index 1b930943c..1568c3936 100644 --- a/serving/installing-logging-metrics-traces.md +++ b/serving/installing-logging-metrics-traces.md @@ -14,7 +14,7 @@ If you installed the skip this step and continue to [Create Elasticsearch Indices](#Create-Elasticsearch-Indices) -- Install Knative monitoring components: +- Install Knative monitoring components from the root of the [Serving repository](https://github.com/knative/serving): ```shell kubectl apply -R -f config/monitoring/100-common \ From b45eee13da2d499ab4d49f7a5a5eb0a31700ae23 Mon Sep 17 00:00:00 2001 From: Sam O'Dell <31352624+samodell@users.noreply.github.com> Date: Mon, 13 Aug 2018 11:28:56 -0700 Subject: [PATCH 19/36] Correct name of .yaml file (#330) --- serving/samples/thumbnailer-go/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serving/samples/thumbnailer-go/README.md b/serving/samples/thumbnailer-go/README.md index 95a0b95ac..8f1c27bcd 100644 --- a/serving/samples/thumbnailer-go/README.md +++ b/serving/samples/thumbnailer-go/README.md @@ -205,4 +205,4 @@ curl -H "Host: $SERVICE_HOST" \ Although this demo uses an external application, the Knative Serving deployment steps would be similar for any 'dockerized' app you may already have. -Just copy the `thumbnailer.yaml` and change a few variables. +Just copy the `sample.yaml` and change a few variables. From b14552673a431e55cbe364c84226e4785d84087c Mon Sep 17 00:00:00 2001 From: Mark Chmarny Date: Tue, 14 Aug 2018 17:20:56 +0100 Subject: [PATCH 20/36] Added Slack URL #257 (#333) * Added Slack URL #257 Added URL to enrol and access Knative Slack instance * Moving link up to top --- community/SLACK-GUIDELINES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/community/SLACK-GUIDELINES.md b/community/SLACK-GUIDELINES.md index 84b6744e4..637e7f350 100644 --- a/community/SLACK-GUIDELINES.md +++ b/community/SLACK-GUIDELINES.md @@ -12,6 +12,9 @@ video recording or in another public space. Please be courteous to others. from these commands and we are a global project - please be kind. Note: `@all` is only to be used by admins. +You can join the [Knative Slack](https://slack.knative.dev) instance at +https://slack.knative.dev. + ## Code of Conduct The Knative [Code of Conduct](./CODE-OF-CONDUCT.md) applies throughout the project, and includes all communication mediums. From f0f79880416a9d2de08f7ddfc47c27979c59556e Mon Sep 17 00:00:00 2001 From: Matt Moore Date: Tue, 14 Aug 2018 10:42:56 -0700 Subject: [PATCH 21/36] Update our docs to document the 0.1.1 release. (#331) --- install/Knative-with-AKS.md | 6 +++--- install/Knative-with-GKE.md | 6 +++--- install/Knative-with-Gardener.md | 10 +++++----- install/Knative-with-IKS.md | 6 +++--- install/Knative-with-Minikube.md | 6 +++--- install/Knative-with-PKS.md | 6 +++--- install/Knative-with-any-k8s.md | 6 +++--- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/install/Knative-with-AKS.md b/install/Knative-with-AKS.md index 321fb6517..42e6fb392 100644 --- a/install/Knative-with-AKS.md +++ b/install/Knative-with-AKS.md @@ -123,7 +123,7 @@ Knative depends on Istio. 1. Install Istio: ```bash - kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.0/third_party/istio-0.8.0/istio.yaml + kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.1/third_party/istio-0.8.0/istio.yaml ``` 1. Label the default namespace with `istio-injection=enabled`: ```bash @@ -150,7 +150,7 @@ You can install the Knative Serving and Build components together, or Build on i 1. Run the `kubectl apply` command to install Knative and its dependencies: ```bash - kubectl apply -f https://github.com/knative/serving/releases/download/v0.1.0/release.yaml + kubectl apply -f https://github.com/knative/serving/releases/download/v0.1.1/release.yaml ``` 1. Monitor the Knative components until all of the components show a `STATUS` of `Running`: @@ -164,7 +164,7 @@ You can install the Knative Serving and Build components together, or Build on i 1. Run the `kubectl apply` command to install [Knative Build](https://github.com/knative/build) and its dependencies: ```bash - kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.0/third_party/config/build/release.yaml + kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.1/third_party/config/build/release.yaml ``` 1. Monitor the Knative Build components until all of the components show a `STATUS` of `Running`: diff --git a/install/Knative-with-GKE.md b/install/Knative-with-GKE.md index b21d1e90b..24abd4656 100644 --- a/install/Knative-with-GKE.md +++ b/install/Knative-with-GKE.md @@ -119,7 +119,7 @@ Knative depends on Istio. 1. Install Istio: ```bash - kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.0/third_party/istio-0.8.0/istio.yaml + kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.1/third_party/istio-0.8.0/istio.yaml ``` 1. Label the default namespace with `istio-injection=enabled`: ```bash @@ -145,7 +145,7 @@ You can install the Knative Serving and Build components together, or Build on i 1. Run the `kubectl apply` command to install Knative and its dependencies: ```bash - kubectl apply -f https://github.com/knative/serving/releases/download/v0.1.0/release.yaml + kubectl apply -f https://github.com/knative/serving/releases/download/v0.1.1/release.yaml ``` 1. Monitor the Knative components until all of the components show a `STATUS` of `Running`: @@ -159,7 +159,7 @@ You can install the Knative Serving and Build components together, or Build on i 1. Run the `kubectl apply` command to install [Knative Build](https://github.com/knative/build) and its dependencies: ```bash - kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.0/third_party/config/build/release.yaml + kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.1/third_party/config/build/release.yaml ``` 1. Monitor the Knative Build components until all of the components show a `STATUS` of `Running`: diff --git a/install/Knative-with-Gardener.md b/install/Knative-with-Gardener.md index c0f920466..84d76852a 100644 --- a/install/Knative-with-Gardener.md +++ b/install/Knative-with-Gardener.md @@ -71,7 +71,7 @@ Knative depends on Istio. 1. Install Istio: ```bash - kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.0/third_party/istio-0.8.0/istio.yaml + kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.1/third_party/istio-0.8.0/istio.yaml ``` 2. Label the default namespace with `istio-injection=enabled`: ```bash @@ -95,7 +95,7 @@ You can install the Knative Serving and Build components together, or Build on i 1. Run the `kubectl apply` command to install Knative and its dependencies: ```bash - kubectl apply -f https://github.com/knative/serving/releases/download/v0.1.0/release.yaml + kubectl apply -f https://github.com/knative/serving/releases/download/v0.1.1/release.yaml ``` 1. Monitor the Knative components until all of the components show a `STATUS` of `Running`: @@ -109,7 +109,7 @@ You can install the Knative Serving and Build components together, or Build on i 1. Run the `kubectl apply` command to install [Knative Build](https://github.com/knative/build) and its dependencies: ```bash - kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.0/third_party/config/build/release.yaml + kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.1/third_party/config/build/release.yaml ``` 1. Monitor the Knative Build components until all of the components show a `STATUS` of `Running`: @@ -159,10 +159,10 @@ spec: And of course create the respectve `ConfigMaps`: ``` -curl https://raw.githubusercontent.com/knative/serving/v0.1.0/third_party/istio-0.8.0/istio.yaml +curl https://raw.githubusercontent.com/knative/serving/v0.1.1/third_party/istio-0.8.0/istio.yaml kubectl create configmap istio-chart-080 --from-file=istio.yaml -curl https://github.com/knative/serving/releases/download/v0.1.0/release.yaml +curl https://github.com/knative/serving/releases/download/v0.1.1/release.yaml kubectl create configmap knative-chart-001 --from-file=release.yaml ``` diff --git a/install/Knative-with-IKS.md b/install/Knative-with-IKS.md index 4433ced89..3d16c75ff 100644 --- a/install/Knative-with-IKS.md +++ b/install/Knative-with-IKS.md @@ -126,7 +126,7 @@ Knative depends on Istio. 1. Install Istio: ```bash - kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.0/third_party/istio-0.8.0/istio.yaml + kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.1/third_party/istio-0.8.0/istio.yaml ``` 1. Label the default namespace with `istio-injection=enabled`: ```bash @@ -153,7 +153,7 @@ You can install the Knative Serving and Build components together, or Build on i 1. Run the `kubectl apply` command to install Knative and its dependencies: ```bash - kubectl apply -f https://github.com/knative/serving/releases/download/v0.1.0/release.yaml + kubectl apply -f https://github.com/knative/serving/releases/download/v0.1.1/release.yaml ``` 1. Monitor the Knative components until all of the components show a `STATUS` of `Running`: @@ -167,7 +167,7 @@ You can install the Knative Serving and Build components together, or Build on i 1. Run the `kubectl apply` command to install [Knative Build](https://github.com/knative/build) and its dependencies: ```bash - kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.0/third_party/config/build/release.yaml + kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.1/third_party/config/build/release.yaml ``` 1. Monitor the Knative Build components until all of the components show a `STATUS` of `Running`: diff --git a/install/Knative-with-Minikube.md b/install/Knative-with-Minikube.md index 57a7b822c..45a5ee807 100644 --- a/install/Knative-with-Minikube.md +++ b/install/Knative-with-Minikube.md @@ -59,7 +59,7 @@ Knative depends on Istio. Run the following to install Istio. (We are changing `LoadBalancer` to `NodePort` for the `istio-ingress` service). ```shell -curl -L https://raw.githubusercontent.com/knative/serving/v0.1.0/third_party/istio-0.8.0/istio.yaml \ +curl -L https://raw.githubusercontent.com/knative/serving/v0.1.1/third_party/istio-0.8.0/istio.yaml \ | sed 's/LoadBalancer/NodePort/' \ | kubectl apply -f - @@ -85,12 +85,12 @@ rerun the command to see the current status. Next, install [Knative Serving](https://github.com/knative/serving): Because you have limited resources available, use the -`https://github.com/knative/serving/releases/download/v0.1.0/release-lite.yaml` +`https://github.com/knative/serving/releases/download/v0.1.1/release-lite.yaml` file, which omits some of the monitoring components to reduce the memory used by the Knative components. To use the provided `release-lite.yaml` release, run: ```shell -curl -L https://github.com/knative/serving/releases/download/v0.1.0/release-lite.yaml \ +curl -L https://github.com/knative/serving/releases/download/v0.1.1/release-lite.yaml \ | sed 's/LoadBalancer/NodePort/' \ | kubectl apply -f - ``` diff --git a/install/Knative-with-PKS.md b/install/Knative-with-PKS.md index e60332dc4..a78189710 100644 --- a/install/Knative-with-PKS.md +++ b/install/Knative-with-PKS.md @@ -32,7 +32,7 @@ Knative depends on Istio. Istio workloads require privileged mode for Init Conta 1. Install Istio: ```bash - kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.0/third_party/istio-0.8.0/istio.yaml + kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.1/third_party/istio-0.8.0/istio.yaml ``` 1. Label the default namespace with `istio-injection=enabled`: ```bash @@ -58,7 +58,7 @@ You can install the Knative Serving and Build components together, or Build on i 1. Run the `kubectl apply` command to install Knative and its dependencies: ```bash - kubectl apply -f https://github.com/knative/serving/releases/download/v0.1.0/release.yaml + kubectl apply -f https://github.com/knative/serving/releases/download/v0.1.1/release.yaml ``` 1. Monitor the Knative components until all of the components show a `STATUS` of `Running`: @@ -72,7 +72,7 @@ You can install the Knative Serving and Build components together, or Build on i 1. Run the `kubectl apply` command to install [Knative Build](https://github.com/knative/build) and its dependencies: ```bash - kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.0/third_party/config/build/release.yaml + kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.1/third_party/config/build/release.yaml ``` 1. Monitor the Knative Build components until all of the components show a `STATUS` of `Running`: diff --git a/install/Knative-with-any-k8s.md b/install/Knative-with-any-k8s.md index 7f79ca022..5c2ea6467 100644 --- a/install/Knative-with-any-k8s.md +++ b/install/Knative-with-any-k8s.md @@ -19,7 +19,7 @@ Containers 1. Install Istio: ```bash - kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.0/third_party/istio-0.8.0/istio.yaml + kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.1/third_party/istio-0.8.0/istio.yaml ``` 1. Label the default namespace with `istio-injection=enabled`: ```bash @@ -43,7 +43,7 @@ You can install the Knative Serving and Build components together, or Build on i 1. Run the `kubectl apply` command to install Knative and its dependencies: ```bash - kubectl apply -f https://github.com/knative/serving/releases/download/v0.1.0/release.yaml + kubectl apply -f https://github.com/knative/serving/releases/download/v0.1.1/release.yaml ``` 1. Monitor the Knative components until all of the components show a `STATUS` of `Running`: @@ -57,7 +57,7 @@ You can install the Knative Serving and Build components together, or Build on i 1. Run the `kubectl apply` command to install [Knative Build](https://github.com/knative/build) and its dependencies: ```bash - kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.0/third_party/config/build/release.yaml + kubectl apply -f https://raw.githubusercontent.com/knative/serving/v0.1.1/third_party/config/build/release.yaml ``` 1. Monitor the Knative Build components until all of the components show a `STATUS` of `Running`: From 90095973d8d6400b0d126bbabd206040a7acb49e Mon Sep 17 00:00:00 2001 From: Adam Harwayne Date: Wed, 15 Aug 2018 09:40:56 -0700 Subject: [PATCH 22/36] Fix a typo in the path so that ko can be used to deploy the sample. (#334) --- eventing/samples/k8s-events/function.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eventing/samples/k8s-events/function.yaml b/eventing/samples/k8s-events/function.yaml index 46383e64f..59c966b90 100644 --- a/eventing/samples/k8s-events/function.yaml +++ b/eventing/samples/k8s-events/function.yaml @@ -24,4 +24,4 @@ spec: spec: container: # Replace this image with your {username}/k8s-events container - image: github.com/knative/docs/eventing/sample/k8s-events + image: github.com/knative/docs/eventing/samples/k8s-events From 1a48e0bbe8f15d5239dec5be21511809b46598a3 Mon Sep 17 00:00:00 2001 From: Jason Hall Date: Thu, 16 Aug 2018 10:27:56 -0400 Subject: [PATCH 23/36] Update WORKING-GROUPS.md (#336) --- community/WORKING-GROUPS.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/community/WORKING-GROUPS.md b/community/WORKING-GROUPS.md index 41f5dbe54..a0365cee0 100644 --- a/community/WORKING-GROUPS.md +++ b/community/WORKING-GROUPS.md @@ -52,8 +52,8 @@ Slack Channel | [#api](https://knative.slack.com) Artifact | Link -------------------------- | ---- Forum | [knative-dev@](https://groups.google.com/forum/#!forum/knative-dev) -Community Meeting VC | [build-crd](https://hangouts.google.com/hangouts/_/google.com/build-crd) -Community Meeting Calendar | Wednesdays 10:00a-10:30a PST
[Calendar Invitation](https://calendar.google.com/event?action=TEMPLATE&tmeid=MTBkb3MwYnVrbDd0djE0a2kzcmpmbjZndm9fMjAxODA3MTFUMTcwMDAwWiBtYXR0bW9vckBnb29nbGUuY29t&tmsrc=mattmoor%40google.com) +Community Meeting VC | [meet.google.com/hau-nwak-tgm](https://meet.google.com/hau-nwak-tgm)
Or dial in:
(US) +1 219-778-6103‬ PIN: ‪573 000‬# +Community Meeting Calendar | Wednesdays 10:00a-10:30a PST
[Calendar Invitation](https://calendar.google.com/event?action=TEMPLATE&tmeid=MTBkb3MwYnVrbDd0djE0a2kzcmpmbjZndm9fMjAxODA4MTVUMTcwMDAwWiBqYXNvbmhhbGxAZ29vZ2xlLmNvbQ&tmsrc=jasonhall%40google.com&scp=ALL) Meeting Notes | [Notes](https://docs.google.com/document/d/1e7gMVFlJfkFdTcaWj2qETeRD9kSBG2Vh8mASPmQMYC0/edit) Document Folder | [Folder](https://drive.google.com/corp/drive/folders/1ov16HvPam-v_FXAGEaUdHok6_hUAoIoe) Slack Channel | [#build-crd](https://knative.slack.com) From 1b52510c44168a99efe6179c523cd68bdac1e07b Mon Sep 17 00:00:00 2001 From: Gaurav Abbi Date: Tue, 21 Aug 2018 18:07:58 +0200 Subject: [PATCH 24/36] Add a helloworld sample for haskell (#316) * Add a helloworld sample for haskell * Use stack as the build tool * Use scotty as a web framework * Use docker multi-stage build to create a smaller runtime image * Apply review comments on the README.md * Apply language review comments - Fix `service.yaml` indentation - Change heading for sample code recreation --- serving/samples/helloworld-haskell/.gitignore | 6 + serving/samples/helloworld-haskell/Dockerfile | 21 ++ serving/samples/helloworld-haskell/README.md | 198 ++++++++++++++++++ .../samples/helloworld-haskell/app/Main.hs | 20 ++ .../samples/helloworld-haskell/package.yaml | 15 ++ .../samples/helloworld-haskell/service.yaml | 15 ++ serving/samples/helloworld-haskell/stack.yaml | 5 + 7 files changed, 280 insertions(+) create mode 100644 serving/samples/helloworld-haskell/.gitignore create mode 100644 serving/samples/helloworld-haskell/Dockerfile create mode 100644 serving/samples/helloworld-haskell/README.md create mode 100644 serving/samples/helloworld-haskell/app/Main.hs create mode 100644 serving/samples/helloworld-haskell/package.yaml create mode 100644 serving/samples/helloworld-haskell/service.yaml create mode 100644 serving/samples/helloworld-haskell/stack.yaml diff --git a/serving/samples/helloworld-haskell/.gitignore b/serving/samples/helloworld-haskell/.gitignore new file mode 100644 index 000000000..9a6cf65ad --- /dev/null +++ b/serving/samples/helloworld-haskell/.gitignore @@ -0,0 +1,6 @@ +.stack-work/ +*.cabal +*~ +/.idea/ +/dist/ +/out/ diff --git a/serving/samples/helloworld-haskell/Dockerfile b/serving/samples/helloworld-haskell/Dockerfile new file mode 100644 index 000000000..8a9626b4c --- /dev/null +++ b/serving/samples/helloworld-haskell/Dockerfile @@ -0,0 +1,21 @@ +# Use the existing Haskell image as our base +FROM haskell:8.2.2 as builder + +# Checkout our code onto the Docker container +WORKDIR /app +ADD . /app + +# Build and test our code, then install the “helloworld-haskell-exe” executable +RUN stack setup +RUN stack build --copy-bins + +# Copy the "helloworld-haskell-exe" executable to the image using docker multi stage build +FROM fpco/haskell-scratch:integer-gmp +WORKDIR /root/ +COPY --from=builder /root/.local/bin/helloworld-haskell-exe . + +# Expose a port to run our application +EXPOSE 8080 + +# Run the server command +CMD ["./helloworld-haskell-exe"] diff --git a/serving/samples/helloworld-haskell/README.md b/serving/samples/helloworld-haskell/README.md new file mode 100644 index 000000000..7f9aebe89 --- /dev/null +++ b/serving/samples/helloworld-haskell/README.md @@ -0,0 +1,198 @@ +# Hello World - Haskell sample + +A simple web app written in Haskell that you can use for testing. +It reads in an env variable `TARGET` and prints "Hello World: ${TARGET}!". If +TARGET is not specified, it will use "NOT SPECIFIED" as the TARGET. + +## Prerequisites + +* A Kubernetes cluster with Knative installed. Follow the + [installation instructions](https://github.com/knative/docs/blob/master/install/README.md) if you need + to create one. +* [Docker](https://www.docker.com) installed and running on your local machine, + and a Docker Hub account configured (we'll use it for a container registry). + +## Recreating the sample code + +While you can clone all of the code from this directory, hello world +apps are generally more useful if you build them step-by-step. The +following instructions recreate the source files from this folder. + +1. Create a new file named `stack.yaml` and paste the following code: + + ```yaml + flags: {} + packages: + - . + extra-deps: [] + resolver: lts-10.7 + ``` +1. Create a new file named `package.yaml` and paste the following code + + ```yaml + name: helloworld-haskell + version: 0.1.0.0 + dependencies: + - base >= 4.7 && < 5 + - scotty + - text + + executables: + helloworld-haskell-exe: + main: Main.hs + source-dirs: app + ghc-options: + - -threaded + - -rtsopts + - -with-rtsopts=-N + ``` + +1. Create a `app` folder, then create a new file named `Main.hs` in that folder + and paste the following code. This code creates a basic web server which + listens on port 8080: + + ```haskell + {-# LANGUAGE OverloadedStrings #-} + + import Data.Maybe + import Data.Monoid ((<>)) + import Data.Text.Lazy (Text) + import Data.Text.Lazy + import System.Environment (lookupEnv) + import Web.Scotty (ActionM, ScottyM, scotty) + import Web.Scotty.Trans + + main :: IO () + main = do + t <- fromMaybe "NOT SPECIFIED" <$> lookupEnv "TARGET" + scotty 8080 (route t) + + route :: String -> ScottyM() + route t = get "/" $ hello t + + hello :: String -> ActionM() + hello t = text $ pack ("Hello world: " ++ t) + ``` + +1. In your project directory, create a file named `Dockerfile` and copy the code + block below into it. + + ```docker + # Use the existing Haskell image as our base + FROM haskell:8.2.2 as builder + + # Checkout our code onto the Docker container + WORKDIR /app + ADD . /app + + # Build and test our code, then install the “helloworld-haskell-exe” executable + RUN stack setup + RUN stack build --copy-bins + + # Copy the "helloworld-haskell-exe" executable to the image using docker multi stage build + FROM fpco/haskell-scratch:integer-gmp + WORKDIR /root/ + COPY --from=builder /root/.local/bin/helloworld-haskell-exe . + + # Expose a port to run our application + EXPOSE 8080 + + # Run the server command + CMD ["./helloworld-haskell-exe"] + ``` + +1. Create a new file, `service.yaml` and copy the following service definition + into the file. Make sure to replace `{username}` with your Docker Hub username. + +```yaml +apiVersion: serving.knative.dev/v1alpha1 +kind: Service +metadata: + name: helloworld-haskell + namespace: default +spec: + runLatest: + configuration: + revisionTemplate: + spec: + container: + image: docker.io/{username}/helloworld-haskell + env: + - name: TARGET + value: "Haskell Sample v1" +``` + +## Build and deploy this sample + +Once you have recreated the sample code files (or used the files in the sample +folder) you're ready to build and deploy the sample app. + +1. Use Docker to build the sample code into a container. To build and push with + Docker Hub, enter these commands replacing `{username}` with your + Docker Hub username: + + ```shell + # Build the container on your local machine + docker build -t {username}/helloworld-haskell . + + # Push the container to docker registry + docker push {username}/helloworld-haskell + ``` + +1. After the build has completed and the container is pushed to Docker Hub, you + can deploy the app into your cluster. Ensure that the container image value + in `service.yaml` matches the container you built in + the previous step. Apply the configuration using `kubectl`: + + ```shell + kubectl apply -f service.yaml + ``` + +1. Now that your service is created, Knative will perform the following steps: + * Create a new immutable revision for this version of the app. + * Network programming to create a route, ingress, service, and load balance for your app. + * Automatically scale your pods up and down (including to zero active pods). + +1. To find the IP address for your service, enter + `kubectl get svc knative-ingressgateway -n istio-system` to get the ingress IP for your + cluster. If your cluster is new, it may take some time for the service to get assigned + an external IP address. + + ```shell + kubectl get svc knative-ingressgateway -n istio-system + + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + knative-ingressgateway LoadBalancer 10.23.247.74 35.203.155.229 80:32380/TCP,443:32390/TCP,32400:32400/TCP 2d + + ``` + + For minikube or bare-metal, get IP_ADDRESS by running the following command + + ```shell + echo $(kubectl get node -o 'jsonpath={.items[0].status.addresses[0].address}'):$(kubectl get svc knative-ingressgateway -n istio-system -o 'jsonpath={.spec.ports[?(@.port==80)].nodePort}') + + ``` + +1. To find the URL for your service, enter: + ``` + kubectl get services.serving.knative.dev helloworld-haskell -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain + NAME DOMAIN + helloworld-haskell helloworld-haskell.default.example.com + ``` + +1. Now you can make a request to your app and see the result. Replace + `{IP_ADDRESS}` with the address you see returned in the previous step. + + ```shell + curl -H "Host: helloworld-haskell.default.example.com" http://{IP_ADDRESS} + Hello world: Haskell Sample v1 + ``` + +## Removing the sample app deployment + +To remove the sample app from your cluster, delete the service record: + +```shell +kubectl delete -f service.yaml +``` + diff --git a/serving/samples/helloworld-haskell/app/Main.hs b/serving/samples/helloworld-haskell/app/Main.hs new file mode 100644 index 000000000..6f69ab9ce --- /dev/null +++ b/serving/samples/helloworld-haskell/app/Main.hs @@ -0,0 +1,20 @@ +{-# LANGUAGE OverloadedStrings #-} + +import Data.Maybe +import Data.Monoid ((<>)) +import Data.Text.Lazy (Text) +import Data.Text.Lazy +import System.Environment (lookupEnv) +import Web.Scotty (ActionM, ScottyM, scotty) +import Web.Scotty.Trans + +main :: IO () +main = do + t <- fromMaybe "NOT SPECIFIED" <$> lookupEnv "TARGET" + scotty 8080 (route t) + +route :: String -> ScottyM() +route t = get "/" $ hello t + +hello :: String -> ActionM() +hello t = text $ pack ("Hello world: " ++ t) diff --git a/serving/samples/helloworld-haskell/package.yaml b/serving/samples/helloworld-haskell/package.yaml new file mode 100644 index 000000000..12178e943 --- /dev/null +++ b/serving/samples/helloworld-haskell/package.yaml @@ -0,0 +1,15 @@ +name: helloworld-haskell +version: 0.1.0.0 +dependencies: +- base >= 4.7 && < 5 +- scotty +- text + +executables: + helloworld-haskell-exe: + main: Main.hs + source-dirs: app + ghc-options: + - -threaded + - -rtsopts + - -with-rtsopts=-N diff --git a/serving/samples/helloworld-haskell/service.yaml b/serving/samples/helloworld-haskell/service.yaml new file mode 100644 index 000000000..07a7e0a83 --- /dev/null +++ b/serving/samples/helloworld-haskell/service.yaml @@ -0,0 +1,15 @@ +apiVersion: serving.knative.dev/v1alpha1 +kind: Service +metadata: + name: helloworld-haskell + namespace: default +spec: + runLatest: + configuration: + revisionTemplate: + spec: + container: + image: docker.io/{username}/helloworld-haskell + env: + - name: TARGET + value: "Haskell Sample v1" diff --git a/serving/samples/helloworld-haskell/stack.yaml b/serving/samples/helloworld-haskell/stack.yaml new file mode 100644 index 000000000..e63cd13e1 --- /dev/null +++ b/serving/samples/helloworld-haskell/stack.yaml @@ -0,0 +1,5 @@ +flags: {} +packages: +- . +extra-deps: [] +resolver: lts-10.7 From 26a432a20f08475307b77127a9feaf27d26cd79d Mon Sep 17 00:00:00 2001 From: Zhimin Xiang Date: Tue, 21 Aug 2018 13:42:58 -0700 Subject: [PATCH 25/36] Doc to introduce how to install ExternalDNS within Knative (#325) * doc to introduce how to install ExternalDNS * address comments * Wording edits * address comments * Wording update * adding Google Cloud DNS link --- serving/using-external-dns.md | 155 ++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 serving/using-external-dns.md diff --git a/serving/using-external-dns.md b/serving/using-external-dns.md new file mode 100644 index 000000000..ff6aac136 --- /dev/null +++ b/serving/using-external-dns.md @@ -0,0 +1,155 @@ +# Using ExternalDNS to automate DNS setup + +[ExternalDNS](https://github.com/kubernetes-incubator/external-dns) is a tool +that synchronizes exposed Kubernetes Services and Ingresses with DNS providers. + +This doc explains how to set up ExternalDNS within a Knative cluster using +[Google Cloud DNS](https://cloud.google.com/dns/) to automate the process +of publishing the Knative domain. + +## Prerequisite + +1. A Kubernetes cluster with [Knative Serving](https://github.com/knative/docs/blob/master/install/README.md) installed. +1. A public domain that will be used in Knative. +1. Configure Knative to use your custom domain. +```shell +kubectl edit cm config-domain -n knative-serving +``` +This command opens your default text editor and allows you to edit the config +map. +``` +apiVersion: v1 +data: + example.com: "" +kind: ConfigMap +[...] +``` +Edit the file to replace `example.com` with the domain you'd like to use and +save your changes. In this example, we use domain `external-dns-test.my-org.do` + for all routes: +``` +apiVersion: v1 +data: + external-dns-test.my-org.do: "" +kind: ConfigMap +[...] +``` + +## Setup steps + +This guide uses Google Cloud Platform as an example to show how to set up +ExternalDNS. You can find detailed instructions for other cloud providers in the +[ExternalDNS documentation](https://github.com/kubernetes-incubator/external-dns#deploying-to-a-cluster). + +### Choose a DNS provider + +Skip this step if you already have a DNS provider for your domain. + +Here is a [list](https://github.com/kubernetes-incubator/external-dns#the-latest-release-v05) +of DNS providers supported by ExternalDNS. Choose a DNS provider from the list. + +### Create a DNS zone for managing DNS records + +Skip this step if you already have a zone for managing the DNS records of your +custom domain. + +A DNS zone which will contain the managed DNS records needs to be created. +Assume your custom domain is `external-dns-test.my-org.do`. + +Use the following command to create a DNS zone with [Google Cloud DNS](https://cloud.google.com/dns/): +```shell +gcloud dns managed-zones create "external-dns-zone" \ + --dns-name "external-dns-test.my-org.do." \ + --description "Automatically managed zone by kubernetes.io/external-dns" +``` +Make a note of the nameservers that were assigned to your new zone. +```shell +gcloud dns record-sets list \ + --zone "external-dns-zone" \ + --name "external-dns-test.my-org.do." \ + --type NS +``` +You should see output similar to the following: +``` +NAME TYPE TTL DATA +external-dns-test.my-org.do. NS 21600 ns-cloud-e1.googledomains.com.,ns-cloud-e2.googledomains.com.,ns-cloud-e3.googledomains.com.,ns-cloud-e4.googledomains.com. +``` +In this case, the DNS nameservers are `ns-cloud-{e1-e4}.googledomains.com`. +Yours could differ slightly, e.g. {a1-a4}, {b1-b4} etc. + +If this zone has the parent zone, you need to add NS records of this zone into +the parent zone so that this zone can be found from the parent. +Assuming the parent zone is `my-org-do` and the parent domain is `my-org.do`, +and the parent zone is also hosted at Google Cloud DNS, you can follow these +steps to add the NS records of this zone into the parent zone: +```shell +gcloud dns record-sets transaction start --zone "my-org-do" +gcloud dns record-sets transaction add ns-cloud-e{1..4}.googledomains.com. \ + --name "external-dns-test.my-org.do." --ttl 300 --type NS --zone "my-org-do" +gcloud dns record-sets transaction execute --zone "my-org-do" +``` + +### Deploy ExternalDNS + +Use the following command to apply the [manifest](https://github.com/kubernetes-incubator/external-dns/blob/master/docs/tutorials/gke.md#manifest-for-clusters-without-rbac-enabled) to install ExternalDNS +```shell +cat < +EOF +``` +Note that you need to set the argument `domain-filter` to your custom domain. + +You should see ExternalDNS is installed by running: +```shell +kubectl get deployment external-dns +``` + +### Configuring Knative Gateway service + +In order to publish the Knative Gateway service, the annotation +`external-dns.alpha.kubernetes.io/hostname: '*.external-dns-test.my-org.do'` +needs to be added into Knative gateway service: +```shell +kubectl edit svc knative-ingressgateway -n istio-system +``` +This command opens your default text editor and allows you to add the +annotation to `knative-ingressgateway` service. After you've added your +annotation, your file may look similar to this: +``` +apiVersion: v1 +kind: Service +metadata: + annotations: + external-dns.alpha.kubernetes.io/hostname: '*.external-dns-test.my-org.do' + ... +``` + +### Verify ExternalDNS works + +After roughly two minutes, check that a corresponding DNS record for your +service was created. + +```shell +gcloud dns record-sets list --zone "external-dns-zone" --name "*.external-dns-test.my-org.do." +``` +You should see output similar to: + +``` +NAME TYPE TTL DATA +*.external-dns-test.my-org.do. A 300 35.231.248.30 +*.external-dns-test.my-org.do. TXT 300 "heritage=external-dns,external-dns/owner=my-identifier,external-dns/resource=service/istio-system/knative-ingressgateway" +``` + +### Verify domain has been published + +You can check if the domain has been published to the Internet be entering +the following command: +```shell +host test.external-dns-test.my-org.do +``` +You should see the below result after the domain is published: +``` +test.external-dns-test.my-org.do has address 35.231.248.30 +``` +> Note: The process of publishing the domain to the Internet can take several +minutes. From 9f5fed536d21210fe060dd0b0c45e572e9305fd7 Mon Sep 17 00:00:00 2001 From: Adriano Cunha <35786489+adrcunha@users.noreply.github.com> Date: Thu, 23 Aug 2018 21:27:59 -0700 Subject: [PATCH 26/36] Vendor the test-infra scripts (#353) * shared scripts from test-infra live in //vendor/github.com/knative/test-infra/scripts; * created `//hack/update-deps.sh` to properly update deps, including test-infra; * all bash scripts were updated to use the vendored scripts; Part of knative/test-infra#30. --- Gopkg.lock | 8 + Gopkg.toml | 9 + hack/update-deps.sh | 29 ++ test/e2e-tests.sh | 6 +- test/presubmit-tests.sh | 6 +- .../knative/test-infra/scripts/README.md | 3 + .../knative/test-infra/scripts/e2e-tests.sh | 313 ++++++++++++++++++ .../knative/test-infra/scripts/library.sh | 309 +++++++++++++++++ .../test-infra/scripts/presubmit-tests.sh | 118 +++++++ .../knative/test-infra/scripts/release.sh | 118 +++++++ 10 files changed, 909 insertions(+), 10 deletions(-) create mode 100644 hack/update-deps.sh create mode 100644 vendor/github.com/knative/test-infra/scripts/README.md create mode 100755 vendor/github.com/knative/test-infra/scripts/e2e-tests.sh create mode 100755 vendor/github.com/knative/test-infra/scripts/library.sh create mode 100755 vendor/github.com/knative/test-infra/scripts/presubmit-tests.sh create mode 100755 vendor/github.com/knative/test-infra/scripts/release.sh diff --git a/Gopkg.lock b/Gopkg.lock index 66763ac64..14fe30ca4 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -70,6 +70,14 @@ packages = ["pkg/event"] revision = "2b0383b8e4d67ffac446b17a7922bf7e5d9f5362" +[[projects]] + branch = "master" + digest = "1:d6415e6b744ec877c21fe734067636b9ee149af77276b08a3d33dd8698abf947" + name = "github.com/knative/test-infra" + packages = ["."] + pruneopts = "T" + revision = "4a4a682ee1fd31f33e450406393c3553b9ec5c2a" + [[projects]] name = "github.com/matttproud/golang_protobuf_extensions" packages = ["pbutil"] diff --git a/Gopkg.toml b/Gopkg.toml index a80bbf0ac..74b37931f 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -1,6 +1,10 @@ # Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md # for detailed Gopkg.toml documentation. +required = [ + "github.com/knative/test-infra", +] + ignored = [ "github.com/knative/docs/serving/samples/grpc-ping-go*", ] @@ -9,3 +13,8 @@ ignored = [ go-tests = true unused-packages = true non-go = true + +[[prune.project]] + name = "github.com/knative/test-infra" + unused-packages = false + non-go = false diff --git a/hack/update-deps.sh b/hack/update-deps.sh new file mode 100644 index 000000000..20b5de1ff --- /dev/null +++ b/hack/update-deps.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# Copyright 2018 The Knative Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +source $(dirname $0)/../vendor/github.com/knative/test-infra/scripts/library.sh + +set -o errexit +set -o nounset +set -o pipefail + +cd ${REPO_ROOT_DIR} + +# Ensure we have everything we need under vendor/ +dep ensure + +# Keep the only dir in knative/test-infra we're interested in +find vendor/github.com/knative/test-infra -mindepth 1 -maxdepth 1 ! -name scripts -exec rm -fr {} \; diff --git a/test/e2e-tests.sh b/test/e2e-tests.sh index 7798fe58d..12e5c86be 100755 --- a/test/e2e-tests.sh +++ b/test/e2e-tests.sh @@ -23,11 +23,7 @@ # Calling this script without arguments will create a new cluster in # project $PROJECT_ID, run the tests and delete the cluster. -# Load github.com/knative/test-infra/images/prow-tests/scripts/e2e-tests.sh -[ -f /workspace/e2e-tests.sh ] \ - && source /workspace/e2e-tests.sh \ - || eval "$(docker run --entrypoint sh gcr.io/knative-tests/test-infra/prow-tests -c 'cat e2e-tests.sh')" -[ -v KNATIVE_TEST_INFRA ] || exit 1 +source $(dirname $0)/../vendor/github.com/knative/test-infra/scripts/e2e-tests.sh # Script entry point. diff --git a/test/presubmit-tests.sh b/test/presubmit-tests.sh index 4ede9b244..0aec68778 100755 --- a/test/presubmit-tests.sh +++ b/test/presubmit-tests.sh @@ -18,11 +18,7 @@ # It is started by prow for each PR. # For convenience, it can also be executed manually. -# Load github.com/knative/test-infra/images/prow-tests/scripts/presubmit-tests.sh -[ -f /workspace/presubmit-tests.sh ] \ - && source /workspace/presubmit-tests.sh \ - || eval "$(docker run --entrypoint sh gcr.io/knative-tests/test-infra/prow-tests -c 'cat presubmit-tests.sh')" -[ -v KNATIVE_TEST_INFRA ] || exit 1 +source $(dirname $0)/../vendor/github.com/knative/test-infra/scripts/presubmit-tests.sh function build_tests() { header "TODO(#67): Write build tests" diff --git a/vendor/github.com/knative/test-infra/scripts/README.md b/vendor/github.com/knative/test-infra/scripts/README.md new file mode 100644 index 000000000..5ff9ccbce --- /dev/null +++ b/vendor/github.com/knative/test-infra/scripts/README.md @@ -0,0 +1,3 @@ +# Helper scripts + +This directory contains helper scripts used by Prow test jobs, as well and local development scripts. diff --git a/vendor/github.com/knative/test-infra/scripts/e2e-tests.sh b/vendor/github.com/knative/test-infra/scripts/e2e-tests.sh new file mode 100755 index 000000000..1262f9821 --- /dev/null +++ b/vendor/github.com/knative/test-infra/scripts/e2e-tests.sh @@ -0,0 +1,313 @@ +#!/bin/bash + +# Copyright 2018 The Knative Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This is a helper script for Knative E2E test scripts. To use it: +# 1. Source this script. +# 2. [optional] Write the teardown() function, which will tear down your test +# resources. +# 3. [optional] Write the dump_extra_cluster_state() function. It will be called +# when a test fails, and can dump extra information about the current state of +# the cluster (tipically using kubectl). +# 4. Call the initialize() function passing $@ (without quotes). +# 5. Write logic for the end-to-end tests. Run all go tests using report_go_test() +# and call fail_test() or success() if any of them failed. The envitronment +# variables DOCKER_REPO_OVERRIDE, K8S_CLUSTER_OVERRIDE and K8S_USER_OVERRIDE +# will be set accordingly to the test cluster. You can also use the following +# boolean (0 is false, 1 is true) environment variables for the logic: +# EMIT_METRICS: true if --emit-metrics is passed. +# USING_EXISTING_CLUSTER: true if the test cluster is an already existing one, +# and not a temporary cluster created by kubetest. +# All environment variables above are marked read-only. +# Notes: +# 1. Calling your script without arguments will create a new cluster in the GCP +# project $PROJECT_ID and run the tests against it. +# 2. Calling your script with --run-tests and the variables K8S_CLUSTER_OVERRIDE, +# K8S_USER_OVERRIDE and DOCKER_REPO_OVERRIDE set will immediately start the +# tests against the cluster. + +source $(dirname ${BASH_SOURCE})/library.sh + +# Build a resource name based on $E2E_BASE_NAME, a suffix and $BUILD_NUMBER. +# Restricts the name length to 40 chars (the limit for resource names in GCP). +# Name will have the form $E2E_BASE_NAME-$BUILD_NUMBER. +# Parameters: $1 - name suffix +function build_resource_name() { + local prefix=${E2E_BASE_NAME}-$1 + local suffix=${BUILD_NUMBER} + # Restrict suffix length to 20 chars + if [[ -n "${suffix}" ]]; then + suffix=${suffix:${#suffix}<20?0:-20} + fi + echo "${prefix:0:20}${suffix}" +} + +# Test cluster parameters +readonly E2E_BASE_NAME=k$(basename ${REPO_ROOT_DIR}) +readonly E2E_CLUSTER_NAME=$(build_resource_name e2e-cls) +readonly E2E_NETWORK_NAME=$(build_resource_name e2e-net) +readonly E2E_CLUSTER_REGION=us-central1 +readonly E2E_CLUSTER_ZONE=${E2E_CLUSTER_REGION}-a +readonly E2E_CLUSTER_NODES=3 +readonly E2E_CLUSTER_MACHINE=n1-standard-4 +readonly TEST_RESULT_FILE=/tmp/${E2E_BASE_NAME}-e2e-result + +# Tear down the test resources. +function teardown_test_resources() { + header "Tearing down test environment" + # Free resources in GCP project. + if (( ! USING_EXISTING_CLUSTER )) && [[ "$(type -t teardown)" == "function" ]]; then + teardown + fi + + # Delete Knative Serving images when using prow. + if (( IS_PROW )); then + echo "Images in ${DOCKER_REPO_OVERRIDE}:" + gcloud container images list --repository=${DOCKER_REPO_OVERRIDE} + delete_gcr_images ${DOCKER_REPO_OVERRIDE} + else + # Delete the kubernetes source downloaded by kubetest + rm -fr kubernetes kubernetes.tar.gz + fi +} + +# Exit test, dumping current state info. +# Parameters: $1 - error message (optional). +function fail_test() { + [[ -n $1 ]] && echo "ERROR: $1" + dump_cluster_state + exit 1 +} + +# Download the k8s binaries required by kubetest. +function download_k8s() { + local version=${SERVING_GKE_VERSION} + if [[ "${version}" == "latest" ]]; then + # Fetch latest valid version + local versions="$(gcloud container get-server-config \ + --project=${GCP_PROJECT} \ + --format='value(validMasterVersions)' \ + --region=${E2E_CLUSTER_REGION})" + local gke_versions=(`echo -n ${versions//;/ /}`) + # Get first (latest) version, excluding the "-gke.#" suffix + version="${gke_versions[0]%-*}" + echo "Latest GKE is ${version}, from [${versions//;/, /}]" + elif [[ "${version}" == "default" ]]; then + echo "ERROR: `default` GKE version is not supported yet" + return 1 + fi + # Download k8s to staging dir + version=v${version} + local staging_dir=${GOPATH}/src/k8s.io/kubernetes/_output/gcs-stage + rm -fr ${staging_dir} + staging_dir=${staging_dir}/${version} + mkdir -p ${staging_dir} + pushd ${staging_dir} + export KUBERNETES_PROVIDER=gke + export KUBERNETES_RELEASE=${version} + curl -fsSL https://get.k8s.io | bash + local result=$? + if [[ ${result} -eq 0 ]]; then + mv kubernetes/server/kubernetes-server-*.tar.gz . + mv kubernetes/client/kubernetes-client-*.tar.gz . + rm -fr kubernetes + # Create an empty kubernetes test tarball; we don't use it but kubetest will fetch it + tar -czf kubernetes-test.tar.gz -T /dev/null + fi + popd + return ${result} +} + +# Dump info about the test cluster. If dump_extra_cluster_info() is defined, calls it too. +# This is intended to be called when a test fails to provide debugging information. +function dump_cluster_state() { + echo "***************************************" + echo "*** TEST FAILED ***" + echo "*** Start of information dump ***" + echo "***************************************" + echo ">>> All resources:" + kubectl get all --all-namespaces + echo ">>> Services:" + kubectl get services --all-namespaces + echo ">>> Events:" + kubectl get events --all-namespaces + [[ "$(type -t dump_extra_cluster_state)" == "function" ]] && dump_extra_cluster_state + echo "***************************************" + echo "*** TEST FAILED ***" + echo "*** End of information dump ***" + echo "***************************************" +} + +# Create a test cluster with kubetest and call the current script again. +function create_test_cluster() { + header "Creating test cluster" + # Smallest cluster required to run the end-to-end-tests + local CLUSTER_CREATION_ARGS=( + --gke-create-args="--enable-autoscaling --min-nodes=1 --max-nodes=${E2E_CLUSTER_NODES} --scopes=cloud-platform" + --gke-shape={\"default\":{\"Nodes\":${E2E_CLUSTER_NODES}\,\"MachineType\":\"${E2E_CLUSTER_MACHINE}\"}} + --provider=gke + --deployment=gke + --cluster="${E2E_CLUSTER_NAME}" + --gcp-zone="${E2E_CLUSTER_ZONE}" + --gcp-network="${E2E_NETWORK_NAME}" + --gke-environment=prod + ) + if (( ! IS_PROW )); then + CLUSTER_CREATION_ARGS+=(--gcp-project=${PROJECT_ID:?"PROJECT_ID must be set to the GCP project where the tests are run."}) + else + CLUSTER_CREATION_ARGS+=(--gcp-service-account=/etc/service-account/service-account.json) + fi + # SSH keys are not used, but kubetest checks for their existence. + # Touch them so if they don't exist, empty files are create to satisfy the check. + touch $HOME/.ssh/google_compute_engine.pub + touch $HOME/.ssh/google_compute_engine + # Clear user and cluster variables, so they'll be set to the test cluster. + # DOCKER_REPO_OVERRIDE is not touched because when running locally it must + # be a writeable docker repo. + export K8S_USER_OVERRIDE= + export K8S_CLUSTER_OVERRIDE= + # Get the current GCP project + export GCP_PROJECT=${PROJECT_ID} + [[ -z ${GCP_PROJECT} ]] && export GCP_PROJECT=$(gcloud config get-value project) + # Assume test failed (see more details at the end of this script). + echo -n "1"> ${TEST_RESULT_FILE} + local test_cmd_args="--run-tests" + (( EMIT_METRICS )) && test_cmd_args+=" --emit-metrics" + echo "Test script is ${E2E_SCRIPT}" + download_k8s || return 1 + kubetest "${CLUSTER_CREATION_ARGS[@]}" \ + --up \ + --down \ + --extract local \ + --gcp-node-image ${SERVING_GKE_IMAGE} \ + --test-cmd "${E2E_SCRIPT}" \ + --test-cmd-args "${test_cmd_args}" + echo "Test subprocess exited with code $?" + # Delete target pools and health checks that might have leaked. + # See https://github.com/knative/serving/issues/959 for details. + # TODO(adrcunha): Remove once the leak issue is resolved. + local http_health_checks="$(gcloud compute target-pools list \ + --project=${GCP_PROJECT} --format='value(healthChecks)' --filter="instances~-${E2E_CLUSTER_NAME}-" | \ + grep httpHealthChecks | tr '\n' ' ')" + local target_pools="$(gcloud compute target-pools list \ + --project=${GCP_PROJECT} --format='value(name)' --filter="instances~-${E2E_CLUSTER_NAME}-" | \ + tr '\n' ' ')" + if [[ -n "${target_pools}" ]]; then + echo "Found leaked target pools, deleting" + gcloud compute forwarding-rules delete -q --project=${GCP_PROJECT} --region=${E2E_CLUSTER_REGION} ${target_pools} + gcloud compute target-pools delete -q --project=${GCP_PROJECT} --region=${E2E_CLUSTER_REGION} ${target_pools} + fi + if [[ -n "${http_health_checks}" ]]; then + echo "Found leaked health checks, deleting" + gcloud compute http-health-checks delete -q --project=${GCP_PROJECT} ${http_health_checks} + fi + local result="$(cat ${TEST_RESULT_FILE})" + echo "Test result code is $result" + exit ${result} +} + +# Setup the test cluster for running the tests. +function setup_test_cluster() { + # Fail fast during setup. + set -o errexit + set -o pipefail + + # Set the required variables if necessary. + if [[ -z ${K8S_USER_OVERRIDE} ]]; then + export K8S_USER_OVERRIDE=$(gcloud config get-value core/account) + fi + + if [[ -z ${K8S_CLUSTER_OVERRIDE} ]]; then + USING_EXISTING_CLUSTER=0 + export K8S_CLUSTER_OVERRIDE=$(kubectl config current-context) + acquire_cluster_admin_role ${K8S_USER_OVERRIDE} ${E2E_CLUSTER_NAME} ${E2E_CLUSTER_ZONE} + # Make sure we're in the default namespace. Currently kubetest switches to + # test-pods namespace when creating the cluster. + kubectl config set-context $K8S_CLUSTER_OVERRIDE --namespace=default + fi + readonly USING_EXISTING_CLUSTER + + if [[ -z ${DOCKER_REPO_OVERRIDE} ]]; then + export DOCKER_REPO_OVERRIDE=gcr.io/$(gcloud config get-value project)/${E2E_BASE_NAME}-e2e-img + fi + + echo "- Cluster is ${K8S_CLUSTER_OVERRIDE}" + echo "- User is ${K8S_USER_OVERRIDE}" + echo "- Docker is ${DOCKER_REPO_OVERRIDE}" + + trap teardown_test_resources EXIT + + if (( USING_EXISTING_CLUSTER )) && [[ "$(type -t teardown)" == "function" ]]; then + echo "Deleting any previous SUT instance" + teardown + fi + + readonly K8S_CLUSTER_OVERRIDE + readonly K8S_USER_OVERRIDE + readonly DOCKER_REPO_OVERRIDE + + # Handle failures ourselves, so we can dump useful info. + set +o errexit + set +o pipefail +} + +function success() { + # kubetest teardown might fail and thus incorrectly report failure of the + # script, even if the tests pass. + # We store the real test result to return it later, ignoring any teardown + # failure in kubetest. + # TODO(adrcunha): Get rid of this workaround. + echo -n "0"> ${TEST_RESULT_FILE} + echo "**************************************" + echo "*** ALL TESTS PASSED ***" + echo "**************************************" + exit 0 +} + +RUN_TESTS=0 +EMIT_METRICS=0 +USING_EXISTING_CLUSTER=1 +E2E_SCRIPT="" + +# Parse flags and initialize the test cluster. +function initialize() { + # Normalize calling script path; we can't use readlink because it's not available everywhere + E2E_SCRIPT=$0 + [[ ${E2E_SCRIPT} =~ ^[\./].* ]] || E2E_SCRIPT="./$0" + E2E_SCRIPT="$(cd ${E2E_SCRIPT%/*} && echo $PWD/${E2E_SCRIPT##*/})" + readonly E2E_SCRIPT + + cd ${REPO_ROOT_DIR} + for parameter in $@; do + case $parameter in + --run-tests) RUN_TESTS=1 ;; + --emit-metrics) EMIT_METRICS=1 ;; + *) + echo "error: unknown option ${parameter}" + echo "usage: $0 [--run-tests][--emit-metrics]" + exit 1 + ;; + esac + shift + done + readonly RUN_TESTS + readonly EMIT_METRICS + + if (( ! RUN_TESTS )); then + create_test_cluster + else + setup_test_cluster + fi +} diff --git a/vendor/github.com/knative/test-infra/scripts/library.sh b/vendor/github.com/knative/test-infra/scripts/library.sh new file mode 100755 index 000000000..d9a2e0bdb --- /dev/null +++ b/vendor/github.com/knative/test-infra/scripts/library.sh @@ -0,0 +1,309 @@ +#!/bin/bash + +# Copyright 2018 The Knative Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This is a collection of useful bash functions and constants, intended +# to be used in test scripts and the like. It doesn't do anything when +# called from command line. + +# Default GKE version to be used with Knative Serving +readonly SERVING_GKE_VERSION=latest +readonly SERVING_GKE_IMAGE=cos + +# Public images and yaml files. +readonly KNATIVE_ISTIO_YAML=https://storage.googleapis.com/knative-releases/serving/latest/istio.yaml +readonly KNATIVE_SERVING_RELEASE=https://storage.googleapis.com/knative-releases/serving/latest/release.yaml +readonly KNATIVE_BUILD_RELEASE=https://storage.googleapis.com/knative-releases/build/latest/release.yaml +readonly KNATIVE_EVENTING_RELEASE=https://storage.googleapis.com/knative-releases/eventing/latest/release.yaml + +# Useful environment variables +[[ -n "${PROW_JOB_ID}" ]] && IS_PROW=1 || IS_PROW=0 +readonly IS_PROW +readonly REPO_ROOT_DIR="$(git rev-parse --show-toplevel)" + +# Display a box banner. +# Parameters: $1 - character to use for the box. +# $2 - banner message. +function make_banner() { + local msg="$1$1$1$1 $2 $1$1$1$1" + local border="${msg//[-0-9A-Za-z _.,]/$1}" + echo -e "${border}\n${msg}\n${border}" +} + +# Simple header for logging purposes. +function header() { + local upper="$(echo $1 | tr a-z A-Z)" + make_banner "=" "${upper}" +} + +# Simple subheader for logging purposes. +function subheader() { + make_banner "-" "$1" +} + +# Simple warning banner for logging purposes. +function warning() { + make_banner "!" "$1" +} + +# Remove ALL images in the given GCR repository. +# Parameters: $1 - GCR repository. +function delete_gcr_images() { + for image in $(gcloud --format='value(name)' container images list --repository=$1); do + echo "Checking ${image} for removal" + delete_gcr_images ${image} + for digest in $(gcloud --format='get(digest)' container images list-tags ${image} --limit=99999); do + local full_image="${image}@${digest}" + echo "Removing ${full_image}" + gcloud container images delete -q --force-delete-tags ${full_image} + done + done +} + +# Waits until the given object doesn't exist. +# Parameters: $1 - the kind of the object. +# $2 - object's name. +# $3 - namespace (optional). +function wait_until_object_does_not_exist() { + local KUBECTL_ARGS="get $1 $2" + local DESCRIPTION="$1 $2" + + if [[ -n $3 ]]; then + KUBECTL_ARGS="get -n $3 $1 $2" + DESCRIPTION="$1 $3/$2" + fi + echo -n "Waiting until ${DESCRIPTION} does not exist" + for i in {1..150}; do # timeout after 5 minutes + kubectl ${KUBECTL_ARGS} 2>&1 > /dev/null || return 0 + echo -n "." + sleep 2 + done + echo -e "\n\nERROR: timeout waiting for ${DESCRIPTION} not to exist" + kubectl ${KUBECTL_ARGS} + return 1 +} + +# Waits until all pods are running in the given namespace. +# Parameters: $1 - namespace. +function wait_until_pods_running() { + echo -n "Waiting until all pods in namespace $1 are up" + for i in {1..150}; do # timeout after 5 minutes + local pods="$(kubectl get pods --no-headers -n $1 2>/dev/null)" + # All pods must be running + local not_running=$(echo "${pods}" | grep -v Running | grep -v Completed | wc -l) + if [[ -n "${pods}" && ${not_running} -eq 0 ]]; then + local all_ready=1 + while read pod ; do + local status=(`echo -n ${pod} | cut -f2 -d' ' | tr '/' ' '`) + # All containers must be ready + [[ -z ${status[0]} ]] && all_ready=0 && break + [[ -z ${status[1]} ]] && all_ready=0 && break + [[ ${status[0]} -lt 1 ]] && all_ready=0 && break + [[ ${status[1]} -lt 1 ]] && all_ready=0 && break + [[ ${status[0]} -ne ${status[1]} ]] && all_ready=0 && break + done <<< $(echo "${pods}" | grep -v Completed) + if (( all_ready )); then + echo -e "\nAll pods are up:\n${pods}" + return 0 + fi + fi + echo -n "." + sleep 2 + done + echo -e "\n\nERROR: timeout waiting for pods to come up\n${pods}" + kubectl get pods -n $1 + return 1 +} + +# Waits until the given service has an external IP address. +# Parameters: $1 - namespace. +# $2 - service name. +function wait_until_service_has_external_ip() { + echo -n "Waiting until service $2 in namespace $1 has an external IP" + for i in {1..150}; do # timeout after 15 minutes + local ip=$(kubectl get svc -n $1 $2 -o jsonpath="{.status.loadBalancer.ingress[0].ip}") + if [[ -n "${ip}" ]]; then + echo -e "\nService $2.$1 has IP $ip" + return 0 + fi + echo -n "." + sleep 6 + done + echo -e "\n\nERROR: timeout waiting for service $svc.$ns to have an external IP" + kubectl get pods -n $1 + return 1 +} + +# Returns the name of the pod of the given app. +# Parameters: $1 - app name. +# $2 - namespace (optional). +function get_app_pod() { + local namespace="" + [[ -n $2 ]] && namespace="-n $2" + kubectl get pods ${namespace} --selector=app=$1 --output=jsonpath="{.items[0].metadata.name}" +} + +# Sets the given user as cluster admin. +# Parameters: $1 - user +# $2 - cluster name +# $3 - cluster zone +function acquire_cluster_admin_role() { + # Get the password of the admin and use it, as the service account (or the user) + # might not have the necessary permission. + local password=$(gcloud --format="value(masterAuth.password)" \ + container clusters describe $2 --zone=$3) + kubectl config set-credentials cluster-admin \ + --username=admin --password=${password} + kubectl config set-context $(kubectl config current-context) \ + --user=cluster-admin + kubectl create clusterrolebinding cluster-admin-binding \ + --clusterrole=cluster-admin \ + --user=$1 + # Reset back to the default account + gcloud container clusters get-credentials \ + $2 --zone=$3 --project $(gcloud config get-value project) +} + +# Runs a go test and generate a junit summary through bazel. +# Parameters: $1... - parameters to go test +function report_go_test() { + # Just run regular go tests if not on Prow. + if (( ! IS_PROW )); then + go test $@ + return + fi + local report=$(mktemp) + local summary=$(mktemp) + local failed=0 + # Run tests in verbose mode to capture details. + # go doesn't like repeating -v, so remove if passed. + local args=("${@/-v}") + go test -race -v ${args[@]} > ${report} || failed=$? + # Tests didn't run. + [[ ! -s ${report} ]] && return 1 + # Create WORKSPACE file, required to use bazel + touch WORKSPACE + local targets="" + # Parse the report and generate fake tests for each passing/failing test. + while read line ; do + local fields=(`echo -n ${line}`) + local field0="${fields[0]}" + local field1="${fields[1]}" + local name=${fields[2]} + # Ignore subtests (those containing slashes) + if [[ -n "${name##*/*}" ]]; then + if [[ ${field1} == PASS: || ${field1} == FAIL: ]]; then + # Populate BUILD.bazel + local src="${name}.sh" + echo "exit 0" > ${src} + if [[ ${field1} == "FAIL:" ]]; then + read error + echo "cat < ${src} + echo "${error}" >> ${src} + echo "ERROR-EOF" >> ${src} + echo "exit 1" >> ${src} + fi + chmod +x ${src} + echo "sh_test(name=\"${name}\", srcs=[\"${src}\"])" >> BUILD.bazel + elif [[ ${field0} == FAIL || ${field0} == ok ]]; then + # Update the summary with the result for the package + echo "${line}" >> ${summary} + # Create the package structure, move tests and BUILD file + local package=${field1/github.com\//} + mkdir -p ${package} + targets="${targets} //${package}/..." + mv *.sh BUILD.bazel ${package} + fi + fi + done < ${report} + # If any test failed, show the detailed report. + # Otherwise, just show the summary. + # Exception: when emitting metrics, dump the full report. + if (( failed )) || [[ "$@" == *" -emitmetrics"* ]]; then + cat ${report} + else + cat ${summary} + fi + # Always generate the junit summary. + bazel test ${targets} > /dev/null 2>&1 + return ${failed} +} + +# Install the latest stable Knative/serving in the current cluster. +function start_latest_knative_serving() { + header "Starting Knative Serving" + subheader "Installing Istio" + kubectl apply -f ${KNATIVE_ISTIO_YAML} || return 1 + wait_until_pods_running istio-system || return 1 + kubectl label namespace default istio-injection=enabled || return 1 + subheader "Installing Knative Serving" + kubectl apply -f ${KNATIVE_SERVING_RELEASE} || return 1 + wait_until_pods_running knative-serving || return 1 + wait_until_pods_running knative-build || return 1 +} + +# Install the latest stable Knative/build in the current cluster. +function start_latest_knative_build() { + header "Starting Knative Build" + subheader "Installing Istio" + kubectl apply -f ${KNATIVE_ISTIO_YAML} || return 1 + wait_until_pods_running istio-system || return 1 + subheader "Installing Knative Build" + kubectl apply -f ${KNATIVE_BUILD_RELEASE} || return 1 + wait_until_pods_running knative-build || return 1 +} + +# Run dep-collector, installing it first if necessary. +# Parameters: $1..$n - parameters passed to dep-collector. +function run_dep_collector() { + local local_dep_collector="$(which dep-collector)" + if [[ -z ${local_dep_collector} ]]; then + go get -u github.com/mattmoor/dep-collector + fi + dep-collector $@ +} + +# Run dep-collector to update licenses. +# Parameters: $1 - output file, relative to repo root dir. +# $2...$n - directories and files to inspect. +function update_licenses() { + cd ${REPO_ROOT_DIR} || return 1 + local dst=$1 + shift + run_dep_collector $@ > ./${dst} +} + +# Run dep-collector to check for forbidden liceses. +# Parameters: $1...$n - directories and files to inspect. +function check_licenses() { + # Fetch the google/licenseclassifier for its license db + go get -u github.com/google/licenseclassifier + # Check that we don't have any forbidden licenses in our images. + run_dep_collector -check $@ +} + +# Check links in all .md files in the repo. +function check_links_in_markdown() { + local checker="markdown-link-check" + if ! hash ${checker} 2>/dev/null; then + warning "${checker} not installed, not checking links in .md files" + return 0 + fi + local failed=0 + for md_file in $(find ${REPO_ROOT_DIR} -name \*.md); do + ${checker} -q ${md_file} || failed=1 + done + return ${failed} +} diff --git a/vendor/github.com/knative/test-infra/scripts/presubmit-tests.sh b/vendor/github.com/knative/test-infra/scripts/presubmit-tests.sh new file mode 100755 index 000000000..384e3c5ae --- /dev/null +++ b/vendor/github.com/knative/test-infra/scripts/presubmit-tests.sh @@ -0,0 +1,118 @@ +#!/bin/bash + +# Copyright 2018 The Knative Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This is a helper script to run the presubmit tests. To use it: +# 1. Source this script. +# 2. Define the functions build_tests(), unit_tests() and +# integration_tests(). They should run all tests (i.e., not fail +# fast), and return 0 if all passed, 1 if a failure occurred. +# The environment variables RUN_BUILD_TESTS, RUN_UNIT_TESTS and +# RUN_INTEGRATION_TESTS are set to 0 (false) or 1 (true) accordingly. +# If --emit-metrics is passed, EMIT_METRICS will be set to 1. +# 3. Call the main() function passing $@ (without quotes). +# +# Running the script without parameters, or with the --all-tests +# flag, causes all tests to be executed, in the right order. +# Use the flags --build-tests, --unit-tests and --integration-tests +# to run a specific set of tests. The flag --emit-metrics is used +# to emit metrics when running the tests. + +source $(dirname ${BASH_SOURCE})/library.sh + +# Extensions or file patterns that don't require presubmit tests. +readonly NO_PRESUBMIT_FILES=(\.md \.png ^OWNERS) + +# Options set by command-line flags. +RUN_BUILD_TESTS=0 +RUN_UNIT_TESTS=0 +RUN_INTEGRATION_TESTS=0 +EMIT_METRICS=0 + +# Exit presubmit tests if only documentation files were changed. +function exit_if_presubmit_not_required() { + if [[ -n "${PULL_PULL_SHA}" ]]; then + # On a presubmit job + local changes="$(git diff --name-only ${PULL_PULL_SHA} ${PULL_BASE_SHA})" + local no_presubmit_pattern="${NO_PRESUBMIT_FILES[*]}" + local no_presubmit_pattern="\(${no_presubmit_pattern// /\\|}\)$" + echo -e "Changed files in commit ${PULL_PULL_SHA}:\n${changes}" + if [[ -z "$(echo "${changes}" | grep -v ${no_presubmit_pattern})" ]]; then + # Nothing changed other than files that don't require presubmit tests + header "Commit only contains changes that don't affect tests, skipping" + exit 0 + fi + fi +} + +# Process flags and run tests accordingly. +function main() { + exit_if_presubmit_not_required + + local all_parameters=$@ + [[ -z $1 ]] && all_parameters="--all-tests" + + for parameter in ${all_parameters}; do + case ${parameter} in + --all-tests) + RUN_BUILD_TESTS=1 + RUN_UNIT_TESTS=1 + RUN_INTEGRATION_TESTS=1 + shift + ;; + --build-tests) + RUN_BUILD_TESTS=1 + shift + ;; + --unit-tests) + RUN_UNIT_TESTS=1 + shift + ;; + --integration-tests) + RUN_INTEGRATION_TESTS=1 + shift + ;; + --emit-metrics) + EMIT_METRICS=1 + shift + ;; + *) + echo "error: unknown option ${parameter}" + exit 1 + ;; + esac + done + + readonly RUN_BUILD_TESTS + readonly RUN_UNIT_TESTS + readonly RUN_INTEGRATION_TESTS + readonly EMIT_METRICS + + cd ${REPO_ROOT_DIR} + + # Tests to be performed, in the right order if --all-tests is passed. + + local result=0 + if (( RUN_BUILD_TESTS )); then + build_tests || result=1 + fi + if (( RUN_UNIT_TESTS )); then + unit_tests || result=1 + fi + if (( RUN_INTEGRATION_TESTS )); then + integration_tests || result=1 + fi + exit ${result} +} diff --git a/vendor/github.com/knative/test-infra/scripts/release.sh b/vendor/github.com/knative/test-infra/scripts/release.sh new file mode 100755 index 000000000..abf89ddf4 --- /dev/null +++ b/vendor/github.com/knative/test-infra/scripts/release.sh @@ -0,0 +1,118 @@ +#!/bin/bash + +# Copyright 2018 The Knative Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This is a helper script for Knative release scripts. To use it: +# 1. Source this script. +# 2. Call the parse_flags() function passing $@ (without quotes). +# 3. Call the run_validation_tests() passing the script or executable that +# runs the release validation tests. +# 4. Write logic for the release process. Use the following boolean (0 is +# false, 1 is true) environment variables for the logic: +# SKIP_TESTS: true if --skip-tests is passed. This is handled automatically +# by the run_validation_tests() function. +# TAG_RELEASE: true if --tag-release is passed. In this case, the +# environment variable TAG will contain the release tag in the +# form vYYYYMMDD-. +# PUBLISH_RELEASE: true if --publish is passed. In this case, the environment +# variable KO_FLAGS will be updated with the -L option. +# SKIP_TESTS, TAG_RELEASE and PUBLISH_RELEASE default to false for safety. +# All environment variables above, except KO_FLAGS, are marked read-only once +# parse_flags() is called. + +source $(dirname ${BASH_SOURCE})/library.sh + +# Simple banner for logging purposes. +function banner() { + make_banner "@" "$1" +} + +# Tag images in the yaml file with a tag. If not tag is passed, does nothing. +# Parameters: $1 - yaml file to parse for images. +# $2 - registry where the images are stored. +# $3 - tag to apply (optional). +function tag_images_in_yaml() { + [[ -z $3 ]] && return 0 + echo "Tagging images with $3" + for image in $(grep -o "$2/[a-z\./-]\+@sha256:[0-9a-f]\+" $1); do + gcloud -q container images add-tag ${image} ${image%%@*}:$3 + done +} + +# Copy the given yaml file to a GCS bucket. Image is tagged :latest, and optionally :$2. +# Parameters: $1 - yaml file to copy. +# $2 - destination bucket name. +# $3 - tag to apply (optional). +function publish_yaml() { + gsutil cp $1 gs://$2/latest/ + [[ -n $3 ]] && gsutil cp $1 gs://$2/previous/$3/ +} + +SKIP_TESTS=0 +TAG_RELEASE=0 +PUBLISH_RELEASE=0 +TAG="" +KO_FLAGS="-P -L" + +# Parses flags and sets environment variables accordingly. +function parse_flags() { + cd ${REPO_ROOT_DIR} + for parameter in $@; do + case $parameter in + --skip-tests) SKIP_TESTS=1 ;; + --tag-release) TAG_RELEASE=1 ;; + --notag-release) TAG_RELEASE=0 ;; + --publish) + PUBLISH_RELEASE=1 + # Remove -L from ko flags + KO_FLAGS="${KO_FLAGS/-L}" + ;; + --nopublish) + PUBLISH_RELEASE=0 + # Add -L to ko flags + KO_FLAGS="-L ${KO_FLAGS}" + shift + ;; + *) + echo "error: unknown option ${parameter}" + exit 1 + ;; + esac + shift + done + + TAG="" + if (( TAG_RELEASE )); then + # Currently we're not considering the tags in refs/tags namespace. + commit=$(git describe --always --dirty) + # Like kubernetes, image tag is vYYYYMMDD-commit + TAG="v$(date +%Y%m%d)-${commit}" + fi + + readonly SKIP_TESTS + readonly TAG_RELEASE + readonly PUBLISH_RELEASE + readonly TAG +} + +# Run tests (unless --skip-tests was passed). Conveniently displays a banner indicating so. +# Parameters: $1 - executable that runs the tests. +function run_validation_tests() { + if (( ! SKIP_TESTS )); then + banner "Running release validation tests" + # Run tests. + $1 + fi +} From 85cb853b9bd6c5b2f156a9e965634e7326694f99 Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Fri, 24 Aug 2018 10:12:59 -0400 Subject: [PATCH 27/36] Update ROLES.md (#347) * Update ROLES.md * Update ROLES.md --- community/ROLES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/community/ROLES.md b/community/ROLES.md index 7059fb3c5..e34c31ee7 100644 --- a/community/ROLES.md +++ b/community/ROLES.md @@ -46,7 +46,7 @@ table describes: Member Regular active contributor in the community -

Sponsored by 2 reviewers

+

Sponsored by two members

Has made multiple contributions to the project

From 135aea43b06f7bde51e470e45a690f9f8b9eb746 Mon Sep 17 00:00:00 2001 From: David Buckley Date: Fri, 24 Aug 2018 14:15:59 -0400 Subject: [PATCH 28/36] remove redundant step in source-to-url deployment (#346) --- serving/samples/source-to-url-go/README.md | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/serving/samples/source-to-url-go/README.md b/serving/samples/source-to-url-go/README.md index c0f468a0e..857b4b778 100644 --- a/serving/samples/source-to-url-go/README.md +++ b/serving/samples/source-to-url-go/README.md @@ -189,16 +189,6 @@ container for the application. revisionName: app-from-source-00007 ``` - -1. After the build has completed and the container is pushed to Docker Hub, you - can deploy the app into your cluster. Ensure that the container image value - in `service.yaml` matches the container you built in - the previous step. Apply the configuration using `kubectl`: - - ```shell - kubectl apply -f service.yaml - ``` - 1. Now that your service is created, Knative will perform the following steps: * Fetch the revision specified from GitHub and build it into a container * Push the container to Docker Hub From b53ba6de29952b94c955e2804048a833fd8596eb Mon Sep 17 00:00:00 2001 From: Adriano Cunha <35786489+adrcunha@users.noreply.github.com> Date: Sun, 26 Aug 2018 08:42:03 -0700 Subject: [PATCH 29/36] Fail fast in update-deps.sh when sourcing library.sh (#357) --- hack/update-deps.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hack/update-deps.sh b/hack/update-deps.sh index 20b5de1ff..987503fed 100644 --- a/hack/update-deps.sh +++ b/hack/update-deps.sh @@ -14,12 +14,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -source $(dirname $0)/../vendor/github.com/knative/test-infra/scripts/library.sh - set -o errexit set -o nounset set -o pipefail +source $(dirname $0)/../vendor/github.com/knative/test-infra/scripts/library.sh + cd ${REPO_ROOT_DIR} # Ensure we have everything we need under vendor/ From 1fec344bccaeb238068519937b9fbf24fe92b3e1 Mon Sep 17 00:00:00 2001 From: jessiezcc <37942702+jessiezcc@users.noreply.github.com> Date: Mon, 27 Aug 2018 09:15:11 -0700 Subject: [PATCH 30/36] add productivity wg (#354) --- community/WORKING-GROUPS.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/community/WORKING-GROUPS.md b/community/WORKING-GROUPS.md index a0365cee0..04d06438e 100644 --- a/community/WORKING-GROUPS.md +++ b/community/WORKING-GROUPS.md @@ -25,6 +25,7 @@ The current working groups are: * [Events](#events) * [Networking](#networking) * [Observability](#observability) +* [Productivity](#productivity) * [Scaling](#scaling) @@ -133,6 +134,24 @@ Slack Channel | [#autoscaling](https://knative.slack.com) ------------------------------------------------------------- | -------------- | ------- | ------- | Joseph Burnett | Google | [josephburnett](https://github.com/josephburnett) +## Productivity + +Project health, test framework, continuous integration & deployment, release, performance/scale/load testing infrastructure + +Artifact | Link +-------------------------- | ---- +Forum | [knative-dev@](https://groups.google.com/forum/#!forum/knative-dev) +Community Meeting VC | [Hangouts](https://meet.google.com/sps-vbhg-rfx) +Community Meeting Calendar | [Calendar Invitation](https://calendar.google.com/event?action=TEMPLATE&tmeid=NW5zM21rbHVwZWgyNHFoMGpyY2JhMjB2bHRfMjAxODA4MzBUMjEwMDAwWiBnb29nbGUuY29tXzE4dW40ZnVoNnJva3FmOGhtZmZ0bTVvcXE0QGc&tmsrc=google.com_18un4fuh6rokqf8hmfftm5oqq4%40group.calendar.google.com&scp=ALL) +Meeting Notes | [Notes](https://docs.google.com/document/d/1aPRwYGD4XscRIqlBzbNsSB886PJ0G-vZYUAAUjoydko) +Document Folder | [Folder](https://drive.google.com/corp/drive/folders/1oMYB4LQHjySuMChmcWYCyhH7-CSkz2r_) +Slack Channel | [#productivity](https://knative.slack.com) + +  | Leads | Company | Profile +--------------------------------------------------------- | -------------- | ------- | ------- + | Jessie Zhu | Google | [jessiezcc](https://github.com/jessiezcc) + | Adriano Cunha | Google | [adrcunhua](https://github.com/adrcunha) + --- Except as otherwise noted, the content of this page is licensed under the From 6d564f81b2b625c79d9a941d9dadac4b05bd2483 Mon Sep 17 00:00:00 2001 From: Zhimin Xiang Date: Mon, 27 Aug 2018 16:07:11 -0700 Subject: [PATCH 31/36] Update ExternalDNS setup doc to require Cloud DNS scope when creating a cluster (#356) * Require Cloud DNS scope when setting up external DNS * fix typos * Updates to markdown formatting; wording tweaks --- serving/using-external-dns.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/serving/using-external-dns.md b/serving/using-external-dns.md index ff6aac136..e0806023b 100644 --- a/serving/using-external-dns.md +++ b/serving/using-external-dns.md @@ -9,9 +9,15 @@ of publishing the Knative domain. ## Prerequisite -1. A Kubernetes cluster with [Knative Serving](https://github.com/knative/docs/blob/master/install/README.md) installed. +1. A Google Kubernetes Engine cluster with Cloud DNS scope. + You can create a GKE cluster with Cloud DNS scope by entering the following command: + ```shell + gcloud container clusters create "external-dns" \ + --scopes "https://www.googleapis.com/auth/ndev.clouddns.readwrite" + ``` +1. [Knative Serving](https://github.com/knative/docs/blob/master/install/README.md) installed on your cluster. 1. A public domain that will be used in Knative. -1. Configure Knative to use your custom domain. +1. Knative configured to use your custom domain. ```shell kubectl edit cm config-domain -n knative-serving ``` From b37d9ab15f5d53c27656d577b7f09a1324bce48e Mon Sep 17 00:00:00 2001 From: Scott Nichols <32305648+n3wscott@users.noreply.github.com> Date: Mon, 27 Aug 2018 16:34:11 -0700 Subject: [PATCH 32/36] Adding GitHub Sample for move from eventing. (#339) * Staging for move from eventing. * the event name needed to be updated. * Dockerfile worked just fine. * Updated based on feedback. * core core core. * Updated based on feedback. * Add todo to add to Understanding what happened. --- eventing/samples/github-events/Dockerfile | 27 +++ eventing/samples/github-events/README.md | 174 ++++++++++++++++++ eventing/samples/github-events/auth.yaml | 43 +++++ eventing/samples/github-events/flow.yaml | 37 ++++ eventing/samples/github-events/function.go | 106 +++++++++++ eventing/samples/github-events/function.yaml | 34 ++++ .../samples/github-events/githubsecret.yaml | 25 +++ .../github-events/personal_access_token.png | Bin 0 -> 245850 bytes 8 files changed, 446 insertions(+) create mode 100644 eventing/samples/github-events/Dockerfile create mode 100644 eventing/samples/github-events/README.md create mode 100644 eventing/samples/github-events/auth.yaml create mode 100644 eventing/samples/github-events/flow.yaml create mode 100644 eventing/samples/github-events/function.go create mode 100644 eventing/samples/github-events/function.yaml create mode 100644 eventing/samples/github-events/githubsecret.yaml create mode 100644 eventing/samples/github-events/personal_access_token.png diff --git a/eventing/samples/github-events/Dockerfile b/eventing/samples/github-events/Dockerfile new file mode 100644 index 000000000..9f71b8506 --- /dev/null +++ b/eventing/samples/github-events/Dockerfile @@ -0,0 +1,27 @@ +# Copyright 2018 The Knative Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM golang AS builder + +WORKDIR /go/src/github.com/knative/docs/ +ADD . /go/src/github.com/knative/docs/ + +RUN CGO_ENABLED=0 go build ./eventing/samples/github-events + +FROM gcr.io/distroless/base + +COPY --from=builder /go/src/github.com/knative/docs/github-events /sample + +ENTRYPOINT ["/sample"] +EXPOSE 8080 diff --git a/eventing/samples/github-events/README.md b/eventing/samples/github-events/README.md new file mode 100644 index 000000000..b2024c112 --- /dev/null +++ b/eventing/samples/github-events/README.md @@ -0,0 +1,174 @@ +# Reacting to GitHub Events + +In response to a pull request event, the sample app _legit_ Service will add +`(looks pretty legit)` to the PR title. + +A GitHub webhook will be created on a repository and a Knative `Service` will be +deployed to receive the webhook's event deliveries and forward them into a +`Channel`, through a `Bus`, and out to the consumer via a `Subscription`. The +`Flow` resource takes care of provisioning the webhook, the `Service`, the +`Channel`, and the `Subscription`. + +## Prerequisites + +You will need: + +- A Kubernetes cluster with Knative serving installed. Follow the + [installation instructions](https://github.com/knative/docs/blob/master/install/README.md) + if you need to create one. +- [Docker](https://www.docker.com/) installed and running on your local machine, + and a Docker Hub account configured (you'll use it for a container registry). +- Knative eventing core installed on your Kubernetes cluster. You can install + with: + ```shell + kubectl apply -f https://storage.googleapis.com/knative-releases/eventing/latest/release.yaml + ``` +- A domain name that allows GitHub to call into the cluster: Follow the + [assign a static IP address](https://github.com/knative/docs/blob/master/serving/gke-assigning-static-ip-address.md) + and + [configure a custom domain](https://github.com/knative/docs/blob/master/serving/using-a-custom-domain.md) + instructions. + +## Configuring Knative + +To use this sample, you'll need to install the `stub` ClusterBus and the +`github` EventSource: + +```shell +# Installs ClusterBus +kubectl apply -f https://storage.googleapis.com/knative-releases/eventing/latest/release-clusterbus-stub.yaml +# Installs EventSource +kubectl apply -f https://storage.googleapis.com/knative-releases/eventing/latest/release-source-github.yaml +``` + +## Granting permissions + +Because the `github` EventSource needs to create a Knative Service, you'll need +to provision a special ServiceAccount with the necessary permissions. + +The `eventing/samples/github-events/auth.yaml` file provisions a service +account, and creates a role which can create a Knative Service in the `default` +namespace. In a production environment, you might want to limit the access of +this service account to only specific namespaces. + +```shell +kubectl apply -f eventing/samples/github-events/auth.yaml +``` + +## Building and deploying the sample + +1. Use Docker to build the sample code into a container. To build and push with + Docker Hub, run the following commands, replacing `{username}` with your + Docker Hub username. Run these commands, r following from the _root_ of the + `knative/docs` repo: + + ```shell + # Build the container on your local machine + docker build -t {username}/github-events --file=eventing/samples/github-events/Dockerfile . + + # Push the container to docker registry + docker push {username}/github-events + ``` + +1. After the build has completed and the container is pushed to Docker Hub, you + can deploy the function into your cluster. **Ensure that the container image + value in `function.yaml` matches the container you built in the previous + step.** Apply the configuration using `kubectl`: + + ```shell + kubectl apply -f eventing/samples/github-events/function.yaml + ``` + +1. Check that your service is running using: + + ```shell + kubectl get services.serving.knative.dev -o "custom-columns=NAME:.metadata.name,READY:.status.conditions[2].status,REASON:.status.conditions[2].message" + NAME READY REASON + legit True + ``` + +1. Create a [personal access token](https://github.com/settings/tokens) to + GitHub repo that the GitHub source can use to register webhooks with the + GitHub API. Also decide on a token that your code will use to authenticate + the incoming webhooks from GitHub (*accessToken*). + + The token can be named anything you find convenient. This sample requires + full `repo` control to be able update the title of the _Pull Request_. + The Source requires `admin:repo_hook`, this allows it to create webhooks + into repos that your account is allowed to do so. Copy and save this token; + GitHub will force you to generate it again if misplaced. + + Here I named my token "EventingSample" and have selected the recommended + scopes: + + ![GitHub UI](personal_access_token.png "GitHub personal access token screenshot") + + Update `eventing/samples/github-events/githubsecret.yaml` with those + values. If your generated access token is `'asdfasfdsaf'` and you choose + your *secretToken* as `'personal_access_token_value'`, you'd modify + `eventing/samples/github-events/githubsecret.yaml` like so: + + ```yaml + apiVersion: v1 + kind: Secret + metadata: + name: githubsecret + type: Opaque + stringData: + githubCredentials: > + { + "accessToken": "asdfasfdsaf", + "secretToken": "personal_access_token_value" + } + ``` + + Hint: you can makeup a random *accessToken* with: + + ```shell + head -c 8 /dev/urandom | base64 + ``` + + Then, apply the githubsecret using `kubectl`: + + ```shell + kubectl apply -f eventing/samples/github-events/githubsecret.yaml + ``` + +1. Update the resource inside `eventing/samples/github-events/flow.yaml` to the + org/repo of your choosing. Note that the personal access token must be valid + for the chosen org/repo. + + Then create the flow sending GitHub Events to the service: + + ```shell + kubectl apply -f eventing/samples/github-events/flow.yaml + ``` + +1. Create a PR for the repo you configured the webhook for, and you'll see that + the Title will be modified with the suffix `(looks pretty legit)` + + +## Understanding what happened + +`TODO: similar to k8s-events.` + + + +## Cleaning up + +To clean up the function, `Flow`, auth, and secret: + +```shell +kubectl delete -f eventing/samples/github-events/function.yaml +kubectl delete -f eventing/samples/github-events/flow.yaml +kubectl delete -f eventing/samples/github-events/auth.yaml +kubectl delete -f eventing/samples/github-events/githubsecret.yaml +``` + +And then delete the [personal access token](https://github.com/settings/tokens) +created from GitHub. diff --git a/eventing/samples/github-events/auth.yaml b/eventing/samples/github-events/auth.yaml new file mode 100644 index 000000000..d4ed3e811 --- /dev/null +++ b/eventing/samples/github-events/auth.yaml @@ -0,0 +1,43 @@ +# Copyright 2018 The Knative Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: v1 +kind: ServiceAccount +metadata: + name: feed-sa + namespace: default +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: create-knative-service + namespace: default +rules: +- apiGroups: ["serving.knative.dev"] + resources: ["services"] + verbs: ["get", "list", "watch", "create", "update", "delete", "patch"] +--- +# This enables the feed-sa to deploy the receive adapter. +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: feed-sa-deploy + namespace: default +subjects: + - kind: ServiceAccount + name: feed-sa + namespace: default +roleRef: + kind: Role + name: create-knative-service + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/eventing/samples/github-events/flow.yaml b/eventing/samples/github-events/flow.yaml new file mode 100644 index 000000000..cdf114386 --- /dev/null +++ b/eventing/samples/github-events/flow.yaml @@ -0,0 +1,37 @@ +# Copyright 2018 The Knative Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: flows.knative.dev/v1alpha1 +kind: Flow +metadata: + name: github-flow + namespace: default +spec: + serviceAccountName: feed-sa + trigger: + eventType: dev.knative.github.pullrequest + resource: / # TODO: update this + service: github + parameters: + secretName: githubsecret + secretKey: githubCredentials + parametersFrom: + - secretKeyRef: + name: githubsecret + key: githubCredentials + action: + target: + kind: Service + apiVersion: serving.knative.dev/v1alpha1 + name: legit diff --git a/eventing/samples/github-events/function.go b/eventing/samples/github-events/function.go new file mode 100644 index 000000000..831f48f33 --- /dev/null +++ b/eventing/samples/github-events/function.go @@ -0,0 +1,106 @@ +/* +Copyright 2018 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "context" + "encoding/json" + "flag" + "fmt" + ghclient "github.com/google/go-github/github" + "github.com/knative/eventing/pkg/event" + "golang.org/x/oauth2" + "gopkg.in/go-playground/webhooks.v3/github" + "log" + "net/http" + "os" + "strings" +) + +const ( + // Environment variable containing json credentials + envSecret = "GITHUB_SECRET" + // this is what we tack onto each PR title if not there already + titleSuffix = "looks pretty legit" +) + +// GithubHandler holds necessary objects for communicating with the Github. +type GithubHandler struct { + client *ghclient.Client + ctx context.Context +} + +type GithubSecrets struct { + AccessToken string `json:"accessToken"` + SecretToken string `json:"secretToken"` +} + +func (h *GithubHandler) newPullRequestPayload(ctx context.Context, pl *github.PullRequestPayload) { + + title := pl.PullRequest.Title + log.Printf("GOT PR with Title: %q", title) + + // Check the title and if it contains 'looks pretty legit' leave it alone + if strings.Contains(title, titleSuffix) { + // already modified, leave it alone. + return + } + + newTitle := fmt.Sprintf("%s (%s)", title, titleSuffix) + updatedPR := ghclient.PullRequest{ + Title: &newTitle, + } + newPR, response, err := h.client.PullRequests.Edit(h.ctx, + pl.Repository.Owner.Login, pl.Repository.Name, int(pl.Number), &updatedPR) + if err != nil { + log.Printf("Failed to update PR: %s\n%s", err, response) + return + } + if newPR.Title != nil { + log.Printf("New PR Title: %q", *newPR.Title) + } else { + log.Printf("New PR title is nil") + } +} + +func main() { + flag.Parse() + githubSecrets := os.Getenv(envSecret) + + var credentials GithubSecrets + err := json.Unmarshal([]byte(githubSecrets), &credentials) + if err != nil { + log.Fatalf("Failed to unmarshal credentials: %s", err) + return + } + + // Set up the auth for being able to talk to Github. + ctx := context.Background() + ts := oauth2.StaticTokenSource( + &oauth2.Token{AccessToken: credentials.AccessToken}, + ) + tc := oauth2.NewClient(ctx, ts) + + client := ghclient.NewClient(tc) + + h := &GithubHandler{ + client: client, + ctx: ctx, + } + + log.Fatal(http.ListenAndServe(":8080", event.Handler(h.newPullRequestPayload))) +} diff --git a/eventing/samples/github-events/function.yaml b/eventing/samples/github-events/function.yaml new file mode 100644 index 000000000..b553f2708 --- /dev/null +++ b/eventing/samples/github-events/function.yaml @@ -0,0 +1,34 @@ +# Copyright 2018 The Knative Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: serving.knative.dev/v1alpha1 +kind: Service +metadata: + name: legit +spec: + runLatest: + configuration: + revisionTemplate: + metadata: + labels: + knative.dev/type: function + spec: + container: + image: docker.io/{username}/github-events # TODO: fill username out + env: + - name: GITHUB_SECRET + valueFrom: + secretKeyRef: + key: githubCredentials + name: githubsecret diff --git a/eventing/samples/github-events/githubsecret.yaml b/eventing/samples/github-events/githubsecret.yaml new file mode 100644 index 000000000..0a7f3da5e --- /dev/null +++ b/eventing/samples/github-events/githubsecret.yaml @@ -0,0 +1,25 @@ +# Copyright 2018 The Knative Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v1 +kind: Secret +metadata: + name: githubsecret +type: Opaque +stringData: + githubCredentials: > + { + "accessToken": "", + "secretToken": "" + } diff --git a/eventing/samples/github-events/personal_access_token.png b/eventing/samples/github-events/personal_access_token.png new file mode 100644 index 0000000000000000000000000000000000000000..8f03ecc1d07210ef66334c8221476040bde7a5b9 GIT binary patch literal 245850 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≤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%0D7RtJWSUnlLO#1KeiA5p@&yvXJc%_AN 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 P2K|!~lNYTNHVpVb&*4DW literal 0 HcmV?d00001 From 557cacbf27d9c017cc76e2b1bab142902b327ba8 Mon Sep 17 00:00:00 2001 From: Sabari Kumar Murugesan Date: Wed, 29 Aug 2018 11:03:11 -0700 Subject: [PATCH 33/36] Run eventing samples from the samples home directory (#363) --- eventing/samples/event-flow/README.md | 14 +++++------ eventing/samples/github-events/README.md | 30 ++++++++++++------------ eventing/samples/k8s-events/README.md | 9 +++---- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/eventing/samples/event-flow/README.md b/eventing/samples/event-flow/README.md index ea32ada3a..cc7f1a304 100644 --- a/eventing/samples/event-flow/README.md +++ b/eventing/samples/event-flow/README.md @@ -88,8 +88,8 @@ is a random number 1-10. Now we want to consume these IoT events, so let's create the function to handle the events: ```shell -kubectl apply -f event-flow/route.yaml -kubectl apply -f event-flow/configuration.yaml +kubectl apply -f route.yaml +kubectl apply -f configuration.yaml ``` ## Create an event source @@ -103,10 +103,10 @@ in Pull mode to poll for the events from this topic. Then let's create a GCP PubSub as an event source that we can bind to. ```shell -kubectl apply -f event-flow/serviceaccount.yaml -kubectl apply -f event-flow/serviceaccountbinding.yaml -kubectl apply -f event-flow/eventsource.yaml -kubectl apply -f event-flow/eventtype.yaml +kubectl apply -f serviceaccount.yaml +kubectl apply -f serviceaccountbinding.yaml +kubectl apply -f eventsource.yaml +kubectl apply -f eventtype.yaml ``` ## Bind IoT events to our function @@ -115,5 +115,5 @@ We have now created a function that we want to consume our IoT events, and we ha source that's sending events via GCP PubSub, so let's wire the two together: ```shell -kubectl apply -f event-flow/flow.yaml +kubectl apply -f flow.yaml ``` diff --git a/eventing/samples/github-events/README.md b/eventing/samples/github-events/README.md index b2024c112..fc2176e24 100644 --- a/eventing/samples/github-events/README.md +++ b/eventing/samples/github-events/README.md @@ -46,25 +46,25 @@ kubectl apply -f https://storage.googleapis.com/knative-releases/eventing/latest Because the `github` EventSource needs to create a Knative Service, you'll need to provision a special ServiceAccount with the necessary permissions. -The `eventing/samples/github-events/auth.yaml` file provisions a service +The `auth.yaml` file provisions a service account, and creates a role which can create a Knative Service in the `default` namespace. In a production environment, you might want to limit the access of this service account to only specific namespaces. ```shell -kubectl apply -f eventing/samples/github-events/auth.yaml +kubectl apply -f auth.yaml ``` ## Building and deploying the sample 1. Use Docker to build the sample code into a container. To build and push with Docker Hub, run the following commands, replacing `{username}` with your - Docker Hub username. Run these commands, r following from the _root_ of the - `knative/docs` repo: + Docker Hub username: ```shell # Build the container on your local machine - docker build -t {username}/github-events --file=eventing/samples/github-events/Dockerfile . + # Note: The relative path points to the _root_ of the `knative/docs` repo + docker build -t {username}/github-events --file=Dockerfile ../../../ # Push the container to docker registry docker push {username}/github-events @@ -76,7 +76,7 @@ kubectl apply -f eventing/samples/github-events/auth.yaml step.** Apply the configuration using `kubectl`: ```shell - kubectl apply -f eventing/samples/github-events/function.yaml + kubectl apply -f function.yaml ``` 1. Check that your service is running using: @@ -103,10 +103,10 @@ kubectl apply -f eventing/samples/github-events/auth.yaml ![GitHub UI](personal_access_token.png "GitHub personal access token screenshot") - Update `eventing/samples/github-events/githubsecret.yaml` with those + Update `githubsecret.yaml` with those values. If your generated access token is `'asdfasfdsaf'` and you choose your *secretToken* as `'personal_access_token_value'`, you'd modify - `eventing/samples/github-events/githubsecret.yaml` like so: + `githubsecret.yaml` like so: ```yaml apiVersion: v1 @@ -131,17 +131,17 @@ kubectl apply -f eventing/samples/github-events/auth.yaml Then, apply the githubsecret using `kubectl`: ```shell - kubectl apply -f eventing/samples/github-events/githubsecret.yaml + kubectl apply -f githubsecret.yaml ``` -1. Update the resource inside `eventing/samples/github-events/flow.yaml` to the +1. Update the resource inside `flow.yaml` to the org/repo of your choosing. Note that the personal access token must be valid for the chosen org/repo. Then create the flow sending GitHub Events to the service: ```shell - kubectl apply -f eventing/samples/github-events/flow.yaml + kubectl apply -f flow.yaml ``` 1. Create a PR for the repo you configured the webhook for, and you'll see that @@ -164,10 +164,10 @@ and then deleted. To clean up the function, `Flow`, auth, and secret: ```shell -kubectl delete -f eventing/samples/github-events/function.yaml -kubectl delete -f eventing/samples/github-events/flow.yaml -kubectl delete -f eventing/samples/github-events/auth.yaml -kubectl delete -f eventing/samples/github-events/githubsecret.yaml +kubectl delete -f function.yaml +kubectl delete -f flow.yaml +kubectl delete -f auth.yaml +kubectl delete -f githubsecret.yaml ``` And then delete the [personal access token](https://github.com/settings/tokens) diff --git a/eventing/samples/k8s-events/README.md b/eventing/samples/k8s-events/README.md index d033646dd..00257444a 100644 --- a/eventing/samples/k8s-events/README.md +++ b/eventing/samples/k8s-events/README.md @@ -46,11 +46,12 @@ kubectl apply -f serviceaccount.yaml 1. Use Docker to build the sample code into a container. To build and push with Docker Hub, run these commands replacing `{username}` with your Docker Hub - username. Run the following from the _root_ of the `knative/docs` repo: + username: ```shell # Build the container on your local machine - docker build -t {username}/k8s-events --file=eventing/samples/k8s-events/Dockerfile . + # Note: The relative path points to the _root_ of the `knative/docs` repo + docker build -t {username}/k8s-events --file Dockerfile ../../../ # Push the container to docker registry docker push {username}/k8s-events @@ -62,7 +63,7 @@ kubectl apply -f serviceaccount.yaml step.** Apply the configuration using `kubectl`: ```shell - kubectl apply -f eventing/samples/k8s-events/function.yaml + kubectl apply -f function.yaml ``` 1. Check that your service is running using: @@ -76,7 +77,7 @@ kubectl apply -f serviceaccount.yaml 1. Create the flow sending Kubernetes Events to the service: ```shell - kubectl apply -f eventing/samples/k8s-events/flow.yaml + kubectl apply -f flow.yaml ``` 1. If you have the full knative install, you can read the function logs using From 37cbf823e8dc233943d66ed44801b62ebcbe273f Mon Sep 17 00:00:00 2001 From: Philipp Thun Date: Wed, 29 Aug 2018 23:11:11 +0200 Subject: [PATCH 34/36] Fix link to Error Conditions and Reporting page... (#364) ... that resides in the knative/serving repository. --- serving/debugging-application-issues.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/serving/debugging-application-issues.md b/serving/debugging-application-issues.md index 66d9e1724..51aa1ffc6 100644 --- a/serving/debugging-application-issues.md +++ b/serving/debugging-application-issues.md @@ -38,7 +38,7 @@ kubectl get route -o yaml The `conditions` in `status` provide the reason if there is any failure. For details, see Knative -[Error Conditions and Reporting](../spec/errors.md)(currently some of them +[Error Conditions and Reporting](https://github.com/knative/serving/blob/master/docs/spec/errors.md)(currently some of them are not implemented yet). ## Check Revision status @@ -77,7 +77,7 @@ If you see this condition, check the following to continue debugging: If you see other conditions, to debug further: * Look up the meaning of the conditions in Knative - [Error Conditions and Reporting](../spec/errors.md). Note: some of them + [Error Conditions and Reporting](https://github.com/knative/serving/blob/master/docs/spec/errors.md). Note: some of them are not implemented yet. An alternative is to [check Pod status](#check-pod-status). * If you are using `BUILD` to deploy and the `BuidComplete` condition is not From aea6aced77c1e7e81bee28f3e07af7c8104a17e9 Mon Sep 17 00:00:00 2001 From: Shashwathi Date: Thu, 30 Aug 2018 17:44:12 -0400 Subject: [PATCH 35/36] Add documentation for build timeout (#362) * Add documentation for build timeout * Formatting, wording tweaks --- build/builds.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/build/builds.md b/build/builds.md index 573b10884..91829be9b 100644 --- a/build/builds.md +++ b/build/builds.md @@ -17,6 +17,7 @@ A build runs until all `steps` have completed or until a failure occurs. * [Source](#source) * [Service Account](#service-account) * [Volumes](#volumes) + * [Timeout](#timeout) * [Examples](#examples) --- @@ -47,6 +48,7 @@ following fields: authentication information. * [`volumes`](#volumes) - Specifies one or more volumes that you want to make available to your build. + * [`timeout`](#timeout) - Specifies timeout after which the build will fail. [kubernetes-overview]: https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/#required-fields @@ -164,6 +166,12 @@ For example, use volumes to accomplish one of the following common tasks: * Mount a host's Docker socket to use a `Dockerfile` for container image builds. +#### Timeout + +Optional. Specifies timeout for the build. Includes time required for allocating resources and execution of build. + +* Defaults to 10 minutes. +* Refer to [Go's ParseDuration documentation](https://golang.org/pkg/time/#ParseDuration) for expected format. ### Examples @@ -179,6 +187,7 @@ additional code samples, including working copies of the following snippets: * [Mounting extra volumes](#using-an-extra-volume) * [Pushing an image](#using-steps-to-push-images) * [Authenticating with `ServiceAccount`](#using-a-serviceaccount) +* [Timeout](#using-timeout) #### Using `git` @@ -331,6 +340,22 @@ Note: For a working copy of this `ServiceAccount` example, see the [build/test/git-ssh](https://github.com/knative/build/tree/master/test/git-ssh) code sample. +#### Using `timeout` + +Specifying `timeout` for your `build`: + +```yaml +spec: + timeout: 20m + source: + git: + url: https://github.com/knative/build.git + revision: master + steps: + - image: ubuntu + args: ["cat", "README.md"] +``` + --- Except as otherwise noted, the content of this page is licensed under the From 00d6cec8ca6499f938b3d83e2e413731868e5799 Mon Sep 17 00:00:00 2001 From: Sam O'Dell <31352624+samodell@users.noreply.github.com> Date: Fri, 31 Aug 2018 09:58:12 -0700 Subject: [PATCH 36/36] services.serving.knative.dev -> ksvc, adding check install guide (#360) * services.serving.knative.dev -> ksvc, adding check install guide * Updating image to add outline * Making Richie's suggested edits --- eventing/samples/github-events/README.md | 8 +++- eventing/samples/k8s-events/README.md | 7 +++- images/knative-version.png | Bin 0 -> 51066 bytes install/README.md | 4 ++ install/check-install-version.md | 37 +++++++++++++++++++ install/getting-started-knative-app.md | 10 ++++- serving/samples/gitwebhook-go/README.md | 8 +++- serving/samples/helloworld-csharp/README.md | 8 +++- serving/samples/helloworld-elixir/README.md | 7 +++- serving/samples/helloworld-go/README.md | 8 +++- serving/samples/helloworld-haskell/README.md | 8 +++- serving/samples/helloworld-java/README.md | 8 +++- serving/samples/helloworld-nodejs/README.md | 8 +++- serving/samples/helloworld-php/README.md | 8 +++- serving/samples/helloworld-python/README.md | 8 +++- serving/samples/helloworld-ruby/README.md | 7 +++- serving/samples/helloworld-rust/README.md | 8 +++- serving/samples/source-to-url-go/README.md | 8 +++- 18 files changed, 144 insertions(+), 16 deletions(-) create mode 100644 images/knative-version.png create mode 100644 install/check-install-version.md diff --git a/eventing/samples/github-events/README.md b/eventing/samples/github-events/README.md index fc2176e24..49f5f1e4a 100644 --- a/eventing/samples/github-events/README.md +++ b/eventing/samples/github-events/README.md @@ -82,11 +82,17 @@ kubectl apply -f auth.yaml 1. Check that your service is running using: ```shell - kubectl get services.serving.knative.dev -o "custom-columns=NAME:.metadata.name,READY:.status.conditions[2].status,REASON:.status.conditions[2].message" + kubectl get ksvc -o "custom-columns=NAME:.metadata.name,READY:.status.conditions[2].status,REASON:.status.conditions[2].message" NAME READY REASON legit True ``` + > Note: `ksvc` is an alias for `services.serving.knative.dev`. If you have + an older version (version 0.1.0) of Knative installed, you'll need to use + the long name until you upgrade to version 0.1.1 or higher. See + [Checking Knative Installation Version](../../../install/check-install-version.md) + to learn how to see what version you have installed. + 1. Create a [personal access token](https://github.com/settings/tokens) to GitHub repo that the GitHub source can use to register webhooks with the GitHub API. Also decide on a token that your code will use to authenticate diff --git a/eventing/samples/k8s-events/README.md b/eventing/samples/k8s-events/README.md index 00257444a..6e56ecb4a 100644 --- a/eventing/samples/k8s-events/README.md +++ b/eventing/samples/k8s-events/README.md @@ -69,10 +69,15 @@ kubectl apply -f serviceaccount.yaml 1. Check that your service is running using: ```shell - kubectl get services.serving.knative.dev -o "custom-columns=NAME:.metadata.name,READY:.status.conditions[2].status,REASON:.status.conditions[2].message" + kubectl get ksvc -o "custom-columns=NAME:.metadata.name,READY:.status.conditions[2].status,REASON:.status.conditions[2].message" NAME READY REASON read-k8s-events True ``` + > Note: `ksvc` is an alias for `services.serving.knative.dev`. If you have + an older version (version 0.1.0) of Knative installed, you'll need to use + the long name until you upgrade to version 0.1.1 or higher. See + [Checking Knative Installation Version](../../../install/check-install-version.md) + to learn how to see what version you have installed. 1. Create the flow sending Kubernetes Events to the service: diff --git a/images/knative-version.png b/images/knative-version.png new file mode 100644 index 0000000000000000000000000000000000000000..f3b95ea8e633016c450f5e8b395fe5ba3412cac3 GIT binary patch literal 51066 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 Note: `ksvc` is an alias for `services.serving.knative.dev`. If you have + an older version (version 0.1.0) of Knative installed, you'll need to use + the long name until you upgrade to version 0.1.1 or higher. See + [Checking Knative Installation Version](check-install-version.md) + to learn how to see what version you have installed. + You can also export the host URL as a variable using the following command: ```shell - export HOST_URL=$(kubectl get services.serving.knative.dev helloworld-go -o jsonpath='{.status.domain}') + export HOST_URL=$(kubectl get ksvc helloworld-go -o jsonpath='{.status.domain}') ``` If you changed the name from `helloworld-go` to something else when creating diff --git a/serving/samples/gitwebhook-go/README.md b/serving/samples/gitwebhook-go/README.md index 458015103..178fd04c0 100644 --- a/serving/samples/gitwebhook-go/README.md +++ b/serving/samples/gitwebhook-go/README.md @@ -102,13 +102,19 @@ service "gitwebhook" created 1. Retrieve the hostname for this service, using the following command: ```shell - $ kubectl get services.serving.knative.dev gitwebhook \ + $ kubectl get ksvc gitwebhook \ -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain NAME DOMAIN gitwebhook gitwebhook.default.example.com ``` + > Note: `ksvc` is an alias for `services.serving.knative.dev`. If you have + an older version (version 0.1.0) of Knative installed, you'll need to use + the long name until you upgrade to version 0.1.1 or higher. See + [Checking Knative Installation Version](../../../install/check-install-version.md) + to learn how to see what version you have installed. + 1. Browse on GitHub to the repository where you want to create a webhook. 1. Click **Settings**, then **Webhooks**, then **Add webhook**. 1. Enter the **Payload URL** as `http://{DOMAIN}`, with the value of DOMAIN listed above. diff --git a/serving/samples/helloworld-csharp/README.md b/serving/samples/helloworld-csharp/README.md index a804bf17c..13725f995 100644 --- a/serving/samples/helloworld-csharp/README.md +++ b/serving/samples/helloworld-csharp/README.md @@ -130,11 +130,17 @@ folder) you're ready to build and deploy the sample app. 1. To find the URL for your service, use ``` - kubectl get services.serving.knative.dev helloworld-csharp -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain + kubectl get ksvc helloworld-csharp -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain NAME DOMAIN helloworld-csharp helloworld-csharp.default.example.com ``` + > Note: `ksvc` is an alias for `services.serving.knative.dev`. If you have + an older version (version 0.1.0) of Knative installed, you'll need to use + the long name until you upgrade to version 0.1.1 or higher. See + [Checking Knative Installation Version](../../../install/check-install-version.md) + to learn how to see what version you have installed. + 1. Now you can make a request to your app to see the result. Replace `{IP_ADDRESS}` with the address you see returned in the previous step. diff --git a/serving/samples/helloworld-elixir/README.md b/serving/samples/helloworld-elixir/README.md index a2bd34424..477ae7d3e 100644 --- a/serving/samples/helloworld-elixir/README.md +++ b/serving/samples/helloworld-elixir/README.md @@ -161,12 +161,17 @@ knative-ingressgateway LoadBalancer 10.35.254.218 35.225.171.32 80:32380 1. To find the URL for your service, use ``` - kubectl get services.serving.knative.dev helloworld-elixir -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain + kubectl get ksvc helloworld-elixir -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain NAME DOMAIN helloworld-elixir helloworld-elixir.default.example.com ``` + > Note: `ksvc` is an alias for `services.serving.knative.dev`. If you have + an older version (version 0.1.0) of Knative installed, you'll need to use + the long name until you upgrade to version 0.1.1 or higher. See + [Checking Knative Installation Version](../../../install/check-install-version.md) + to learn how to see what version you have installed. 1. Now you can make a request to your app to see the results. Replace `{IP_ADDRESS}` with the address you see returned in the previous step. diff --git a/serving/samples/helloworld-go/README.md b/serving/samples/helloworld-go/README.md index d4e0fbec8..97c59c242 100644 --- a/serving/samples/helloworld-go/README.md +++ b/serving/samples/helloworld-go/README.md @@ -141,11 +141,17 @@ folder) you're ready to build and deploy the sample app. 1. To find the URL for your service, use ``` - kubectl get services.serving.knative.dev helloworld-go -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain + kubectl get ksvc helloworld-go -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain NAME DOMAIN helloworld-go helloworld-go.default.example.com ``` + > Note: `ksvc` is an alias for `services.serving.knative.dev`. If you have + an older version (version 0.1.0) of Knative installed, you'll need to use + the long name until you upgrade to version 0.1.1 or higher. See + [Checking Knative Installation Version](../../../install/check-install-version.md) + to learn how to see what version you have installed. + 1. Now you can make a request to your app to see the results. Replace `{IP_ADDRESS}` with the address you see returned in the previous step. diff --git a/serving/samples/helloworld-haskell/README.md b/serving/samples/helloworld-haskell/README.md index 7f9aebe89..0cd30e662 100644 --- a/serving/samples/helloworld-haskell/README.md +++ b/serving/samples/helloworld-haskell/README.md @@ -175,11 +175,17 @@ folder) you're ready to build and deploy the sample app. 1. To find the URL for your service, enter: ``` - kubectl get services.serving.knative.dev helloworld-haskell -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain + kubectl get ksvc helloworld-haskell -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain NAME DOMAIN helloworld-haskell helloworld-haskell.default.example.com ``` + > Note: `ksvc` is an alias for `services.serving.knative.dev`. If you have + an older version (version 0.1.0) of Knative installed, you'll need to use + the long name until you upgrade to version 0.1.1 or higher. See + [Checking Knative Installation Version](../../../install/check-install-version.md) + to learn how to see what version you have installed. + 1. Now you can make a request to your app and see the result. Replace `{IP_ADDRESS}` with the address you see returned in the previous step. diff --git a/serving/samples/helloworld-java/README.md b/serving/samples/helloworld-java/README.md index f8190cf55..2b31a5bd9 100644 --- a/serving/samples/helloworld-java/README.md +++ b/serving/samples/helloworld-java/README.md @@ -154,11 +154,17 @@ folder) you're ready to build and deploy the sample app. 1. To find the URL for your service, use ``` - kubectl get services.serving.knative.dev helloworld-java -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain + kubectl get ksvc helloworld-java -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain NAME DOMAIN helloworld-java helloworld-java.default.example.com ``` + > Note: `ksvc` is an alias for `services.serving.knative.dev`. If you have + an older version (version 0.1.0) of Knative installed, you'll need to use + the long name until you upgrade to version 0.1.1 or higher. See + [Checking Knative Installation Version](../../../install/check-install-version.md) + to learn how to see what version you have installed. + 1. Now you can make a request to your app to see the result. Replace `{IP_ADDRESS}` with the address you see returned in the previous step. diff --git a/serving/samples/helloworld-nodejs/README.md b/serving/samples/helloworld-nodejs/README.md index 5b5448b86..5a0a27ced 100644 --- a/serving/samples/helloworld-nodejs/README.md +++ b/serving/samples/helloworld-nodejs/README.md @@ -172,11 +172,17 @@ folder) you're ready to build and deploy the sample app. 1. To find the URL for your service, use ``` - kubectl get services.serving.knative.dev helloworld-nodejs -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain + kubectl get ksvc helloworld-nodejs -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain NAME DOMAIN helloworld-nodejs helloworld-nodejs.default.example.com ``` + > Note: `ksvc` is an alias for `services.serving.knative.dev`. If you have + an older version (version 0.1.0) of Knative installed, you'll need to use + the long name until you upgrade to version 0.1.1 or higher. See + [Checking Knative Installation Version](../../../install/check-install-version.md) + to learn how to see what version you have installed. + 1. Now you can make a request to your app to see the result. Replace `{IP_ADDRESS}` with the address you see returned in the previous step. diff --git a/serving/samples/helloworld-php/README.md b/serving/samples/helloworld-php/README.md index 5a1fc5007..667271a4f 100644 --- a/serving/samples/helloworld-php/README.md +++ b/serving/samples/helloworld-php/README.md @@ -113,11 +113,17 @@ you're ready to build and deploy the sample app. 1. To find the URL for your service, use ``` - kubectl get services.serving.knative.dev helloworld-php -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain + kubectl get ksvc helloworld-php -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain NAME DOMAIN helloworld-php helloworld-php.default.example.com ``` + > Note: `ksvc` is an alias for `services.serving.knative.dev`. If you have + an older version (version 0.1.0) of Knative installed, you'll need to use + the long name until you upgrade to version 0.1.1 or higher. See + [Checking Knative Installation Version](../../../install/check-install-version.md) + to learn how to see what version you have installed. + 1. Now you can make a request to your app to see the result. Replace `{IP_ADDRESS}` with the address you see returned in the previous step. diff --git a/serving/samples/helloworld-python/README.md b/serving/samples/helloworld-python/README.md index f1b3640b6..298864ef9 100644 --- a/serving/samples/helloworld-python/README.md +++ b/serving/samples/helloworld-python/README.md @@ -125,11 +125,17 @@ folder) you're ready to build and deploy the sample app. 1. To find the URL for your service, use ``` - kubectl get services.serving.knative.dev helloworld-python -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain + kubectl get ksvc helloworld-python -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain NAME DOMAIN helloworld-python helloworld-python.default.example.com ``` + > Note: `ksvc` is an alias for `services.serving.knative.dev`. If you have + an older version (version 0.1.0) of Knative installed, you'll need to use + the long name until you upgrade to version 0.1.1 or higher. See + [Checking Knative Installation Version](../../../install/check-install-version.md) + to learn how to see what version you have installed. + 1. Now you can make a request to your app to see the result. Replace `{IP_ADDRESS}` with the address you see returned in the previous step. diff --git a/serving/samples/helloworld-ruby/README.md b/serving/samples/helloworld-ruby/README.md index 403b4c064..53732b9d4 100644 --- a/serving/samples/helloworld-ruby/README.md +++ b/serving/samples/helloworld-ruby/README.md @@ -140,10 +140,15 @@ you're ready to build and deploy the sample app. 1. To find the URL for your service, use ``` - kubectl get services.serving.knative.dev helloworld-ruby -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain + kubectl get ksvc helloworld-ruby -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain NAME DOMAIN helloworld-ruby helloworld-ruby.default.example.com ``` + > Note: `ksvc` is an alias for `services.serving.knative.dev`. If you have + an older version (version 0.1.0) of Knative installed, you'll need to use + the long name until you upgrade to version 0.1.1 or higher. See + [Checking Knative Installation Version](../../../install/check-install-version.md) + to learn how to see what version you have installed. 1. Now you can make a request to your app to see the result. Replace `{IP_ADDRESS}` with the address you see returned in the previous step. diff --git a/serving/samples/helloworld-rust/README.md b/serving/samples/helloworld-rust/README.md index 9a8ee1d8e..0010c984d 100644 --- a/serving/samples/helloworld-rust/README.md +++ b/serving/samples/helloworld-rust/README.md @@ -156,11 +156,17 @@ folder) you're ready to build and deploy the sample app. 1. To find the URL for your service, enter: ``` - kubectl get services.serving.knative.dev helloworld-rust -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain + kubectl get ksvc helloworld-rust -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain NAME DOMAIN helloworld-rust helloworld-rust.default.example.com ``` + > Note: `ksvc` is an alias for `services.serving.knative.dev`. If you have + an older version (version 0.1.0) of Knative installed, you'll need to use + the long name until you upgrade to version 0.1.1 or higher. See + [Checking Knative Installation Version](../../../install/check-install-version.md) + to learn how to see what version you have installed. + 1. Now you can make a request to your app and see the result. Replace `{IP_ADDRESS}` with the address you see returned in the previous step. diff --git a/serving/samples/source-to-url-go/README.md b/serving/samples/source-to-url-go/README.md index 857b4b778..e4286e7f8 100644 --- a/serving/samples/source-to-url-go/README.md +++ b/serving/samples/source-to-url-go/README.md @@ -210,11 +210,17 @@ container for the application. 1. To find the URL for your service, type: ```shell - $ kubectl get services.serving.knative.dev app-from-source -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain + $ kubectl get ksvc app-from-source -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain NAME DOMAIN app-from-source app-from-source.default.example.com ``` + > Note: `ksvc` is an alias for `services.serving.knative.dev`. If you have + an older version (version 0.1.0) of Knative installed, you'll need to use + the long name until you upgrade to version 0.1.1 or higher. See + [Checking Knative Installation Version](../../../install/check-install-version.md) + to learn how to see what version you have installed. + 1. Now you can make a request to your app to see the result. Replace `{IP_ADDRESS}` with the address that you got in the previous step: