diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0786fdf43468..18c5b3af433e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,7 +15,12 @@ You generally only need to submit a CLA once, so if you've already submitted one (even if it was for a different project), you probably don't need to do it again. -## Code reviews +## Workflow + +* All PRs must be pulled from [forks](./DEVELOPMENT.md#setup-your-repo) +* All PRs must [be reviewed](#code-reviews) + +### Code reviews All submissions, including submissions by project members, require review. We use GitHub pull requests for this purpose. Consult [GitHub Help] for more diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 000000000000..20569cb3e89b --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,93 @@ +# Development + +## Getting started + +* Create [a github account](https://github.com/join) +* Install [requirements](#requirements) +* Setup [environment](#environment-setup) + +Before submitting a PR, see also [CONTRIBUTING.md](./CONTRIBUTING.md). + +### Requirements + +You must install these tools: + +1. [`go`](https://golang.org/doc/install): The language `Elafros` is built in +1. [`git`](https://help.github.com/articles/set-up-git/): For source control +1. [`dep`](https://github.com/golang/dep): For managing external Go dependencies. +1. [`bazel`](https://docs.bazel.build/versions/master/getting-started.html): For performing builds. +1. [`kubectl`](https://kubernetes.io/docs/tasks/tools/install-kubectl/): For managing development environments. + + +You'll also need to setup: + +1. [This repo](#setup-your-repo) +1. A running kubernetes cluster (for example, using + [minikube](https://github.com/kubernetes/minikube)); your user **must** have + cluster-admin privileges: + ```bash + kubectl create clusterrolebinding cluster-admin-binding + --clusterrole=cluster-admin --user=${YOUR_KUBE_USER} + ``` +1. A docker repository you can push to +1. [Your environment](#environment-setup) + +Once you meet these requirements, you can [start an `Elafros` +environment](README.md#start-elafros)! + +### Setup your repo + +The repository must be set up properly relative to your +[`GOPATH`](https://github.com/golang/go/wiki/SettingGOPATH). + +To check out this repository first [fork this +repo](https://help.github.com/articles/fork-a-repo/), then: + +```shell +mkdir -p ${GOPATH}/src/github.com/google/elafros +git clone git@github.com:${YOUR_GITHUB_USERNAME}/elafros.git +git remote add upstream git@github.com:google/elafros.git +git remote set-url --push upstream no_push +``` +### Environment setup + +To [start your envrionment](./README.md#start-elafros) you'll need to set these environment +variables (we recommend adding them to your `.bashrc`): + +1. `GOPATH`: If you don't have one, simply pick a directory and add `export GOPATH=...` +1. `$GOPATH/bin` on `PATH`: This is so that tooling installed via `go get` will work properly. +1. `DOCKER_REPO_OVERRIDE`: The docker repository to which developer images should be pushed. +1. `K8S_CLUSTER_OVERRIDE`: The Kubernetes cluster on which development environments should be managed. + +(Make sure to configure [authentication](https://github.com/bazelbuild/rules_docker#authorization) for your +`DOCKER_REPO_OVERRIDE` if required.) + +For `K8S_CLUSTER_OVERRIDE`, we expect that this name matches a cluster with authentication configured +with `kubectl`. You can list the clusters you currently have configured via: +`kubectl config get-contexts`. For the cluster you want to target, the value in the cluster column +should be put in this variable. + +These environment variables will be provided to `bazel` via +[`print-workspace-status.sh`](print-workspace-status.sh) to +[stamp](https://github.com/bazelbuild/rules_docker#stamping) the variables in +[`WORKSPACE`](WORKSPACE). + +_It is notable that if you change the `*_OVERRIDE` variables, you may need to `bazel clean` in order +to properly pick up the change._ + +### Iterating + +As you make changes to the code-base, there are two special cases to be aware of: +* **If you change a type definition ([pkg/apis/ela/v1alpha1/](./pkg/apis/ela/v1alpha1/.)),** then you must run [`./hack/update-codegen.sh`](./hack/update-codegen.sh). +* **If you change a package's deps** (including adding external dep), then you must run + [`./hack/update-deps.sh`](./hack/update-deps.sh). + +These are both idempotent, and we expect that running these at `HEAD` to have no diffs. + +Once the codegen and dependency information is correct, redeploying the controller is simply: +```shell +bazel run :controller.replace +``` + +Or you can [clean it up completely](./README.md#clean-up) and [completely +redeploy `Elafros`](./README.md#start-elafros). diff --git a/README.md b/README.md index 61c55b02ac5f..b78f8489498f 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,64 @@ This repository contains an open source specification and implementation of Google's next-generation serverless product. + +If you are interested in contributing to `Elafros`, see +[CONTRIBUTING.md](./CONTRIBUTING.md) and [DEVELOPMENT.md](./DEVELOPMENT.md). + +* [Setup your development environment](./DEVELOPMENT.md#getting-started) +* [Starting Elafros](#start-elafros) +* [Run samples](./sample/README.md) + +## Start Elafros + +Once you've [setup your development +environment](./DEVELOPMENT.md#getting-started), stand up `Elafros` with: + +```shell +bazel run :everything.create +``` + +This will: + * Build the `ela-controller` into a Docker container. + * Publish the `ela-controller` container to `{DOCKER_REPO_OVERRIDE}/ela-controller:latest`. + * Create a number of resources, including: + * A `Namespace` in which we run Elafros components. + * A `ServiceAccount` as which Elafros will authorize requests. + * A `ClusterRoleBinding`, which grants the Elafros service account the capability to interact with + cluster resources. + * The `CustomResourceDefinition`s for Elafros resources. + * The `Deployment` running the Elafros controller. + +You can see things running with: +```shell +$ kubectl -n ela-system get pods +NAME READY STATUS RESTARTS AGE +ela-controller-77897cc687-vp27q 1/1 Running 0 16s +``` + +You can access the Elafros Controller's logs with: + +```shell +$ kubectl -n ela-system logs $(kubectl -n ela-system get pods -l app=ela-controller -o name) +``` + +## Clean up + +You can delete all of the service components with: +```shell +bazel run :elafros.delete +bazel run :istio.delete +``` + +Due to [a bazel deletion ordering issue](https://github.com/bazelbuild/rules_k8s/issues/97), +which also prevents `bazel run :everything.delete` from working, +both of the above commands will output errors such as: + +``` +deployments.extensions "ela-webhook" not found +... +serviceaccounts "istio-mixer-service-account" not found +``` + +Deleting the Custom Resource Definitions will cascade and cause any instances +of those resources to be cleaned up. diff --git a/sample/README.md b/sample/README.md new file mode 100644 index 000000000000..582e533857b4 --- /dev/null +++ b/sample/README.md @@ -0,0 +1,13 @@ +# Samples + +This directory contains sample services which demonstrate `Elafros` +functionality. + +## Prerequisites + +1. [Setup your development environment](../DEVELOPMENT.md#getting-started) +2. [Start Elafros](../README.md#start-elafros) + +## Samples + +* [helloworld](./demo/helloworld) - A simple webserver diff --git a/sample/demo/helloworld/README.md b/sample/demo/helloworld/README.md new file mode 100644 index 000000000000..cfb696d5f5e6 --- /dev/null +++ b/sample/demo/helloworld/README.md @@ -0,0 +1,57 @@ +# Helloworld + +A simple web server 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 + +1. [Setup your development environment](../DEVELOPMENT.md#getting-started) +2. [Start Elafros](../README.md#start-elafros) + +## Running + +You can deploy this to Elafros from the root directory via: +```shell +bazel run sample/demo/helloworld:everything.create +``` + +Once deployed, you can inspect the created resources with `kubectl` commands: + +```shell +# This will show the ES that we created: +kubectl get elaservice -o yaml + +# This will show the RT that we created: +kubectl get revisiontemplates -o yaml + +# This will show the Revision that was created by our RT: +kubectl get revisions -o yaml + +``` + +To access this service via `curl`, we first need to determine its ingress address: +```shell +$ watch kubectl get ingress +NAME HOSTS ADDRESS PORTS AGE +elaservice-example-ela-ingress demo.myhost.net 80 14s +``` + +Once the `ADDRESS` gets assigned to the cluster, you can run: + +```shell +# Put the Ingress IP into an environment variable. +$ export SERVICE_IP=`kubectl get ingress elaservice-example-ela-ingress -o jsonpath="{.status.loadBalancer.ingress[*]['ip']}"` + +# Curl the Ingress IP "as-if" DNS were properly configured. +$ curl --header 'Host:demo.myhost.net' http://${SERVICE_IP} +Hello World: shiniestnewestversion! +``` + +## Cleaning up + +To clean up the sample service: + +```shell +bazel run sample/demo/helloworld:everything.delete +``` diff --git a/sample/elaservice.yaml b/sample/elaservice.yaml index 84b54790b14c..98ac7da85dda 100644 --- a/sample/elaservice.yaml +++ b/sample/elaservice.yaml @@ -18,7 +18,7 @@ metadata: name: elaservice-example namespace: default spec: - domainSuffix: demo.googlecustomer.net + domainSuffix: demo.myhost.net traffic: - revisionTemplate: revisiontemplate-example percent: 100