From e9ce0e328a18236421d7282e983201f0a130c285 Mon Sep 17 00:00:00 2001 From: Jessica Yao <jessica@heptio.com> Date: Wed, 15 Nov 2017 15:08:44 -0500 Subject: [PATCH] update readme --- CODE-OF-CONDUCT.md | 37 +++++++ CONTRIBUTING.md | 106 ++++++++++++------- DCO-SIGNOFF.md | 58 +++++++++++ README.md | 190 ++++++++++++++++++++++++++--------- docs/README.md | 6 ++ docs/cli-reference/README.md | 62 +++++++++++- docs/concepts.md | 27 +++++ docs/img/guestbook.png | Bin 0 -> 12235 bytes 8 files changed, 400 insertions(+), 86 deletions(-) create mode 100644 CODE-OF-CONDUCT.md create mode 100644 DCO-SIGNOFF.md create mode 100644 docs/README.md create mode 100644 docs/concepts.md create mode 100644 docs/img/guestbook.png diff --git a/CODE-OF-CONDUCT.md b/CODE-OF-CONDUCT.md new file mode 100644 index 00000000..57ad5652 --- /dev/null +++ b/CODE-OF-CONDUCT.md @@ -0,0 +1,37 @@ +## ksonnet Community Code of Conduct + +### Contributor Code of Conduct + +As contributors and maintainers of this project, and in the interest of fostering +an open and welcoming community, we pledge to respect all people who contribute +through reporting issues, posting feature requests, updating documentation, +submitting pull requests or patches, and other activities. + +We are committed to making participation in this project a harassment-free experience for +everyone, regardless of level of experience, gender, gender identity and expression, +sexual orientation, disability, personal appearance, body size, race, ethnicity, age, +religion, or nationality. + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery +* Personal attacks +* Trolling or insulting/derogatory comments +* Public or private harassment +* Publishing other's private information, such as physical or electronic addresses, + without explicit permission +* Other unethical or unprofessional conduct. + +Project maintainers have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are not +aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers +commit themselves to fairly and consistently applying these principles to every aspect +of managing this project. Project maintainers who do not follow or enforce the Code of +Conduct may be permanently removed from the project team. + +This code of conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project maintainer(s). + +This Code of Conduct is adapted from the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md) and [Contributor Covenant](http://contributor-covenant.org/version/1/2/0/), version 1.2.0. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b4b68122..44cd2267 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,64 +1,96 @@ -## Managing vendor/ +## Contributing to ksonnet -This project uses `govendor`. To make things easier for reviewers, -put updates to `vendor/` in a separate commit within the same PR. +Thank you for taking the time to contribute to ksonnet! Before you submit any PRs, we encourage you to read the instructions for the [developer certificate of origin (DCO)](DCO-SIGNOFF.md), as well as the guidelines below: -### Clean up removed/unnecessary dependencies +* [Build](#build) +* [Manage dependencies](#manage-dependencies) + * [Add a new dependency](#add-a-new-dependency) + * [Pin a dependency to a specific version](#pin-a-dependency-to-a-specific-version) + * [Clean up unnecessary dependencies](#clean-up-unnecessary-dependencies) +* [Test](#test) +* [Make a release](#make-a-release) -This is a good one to run before sending a non-trivial change for -review. +### Build +To build ksonnet locally (e.g. for open-source development), run the following in the root of your ksonnet repo: ``` -# See unused -govendor list +unused +make all +``` +This indirectly makes the following targets: + * `make ks` - Compiles all the code into a `ks` binary + * `make docs` - Regenerates all the documentation for the ksonnet CLI, based on the code inside `cmd/`. -# Remove unused -govendor remove +unused +*Troubleshooting* + +`make docs` relies on the `realpath` Linux utility. If you encounter a `realpath: command not found` error, and you are using OSX, run the following command: +``` +brew install coreutils ``` +Running `make` again afterwards should work. + +### Manage dependencies -### Add a new dependency +This project uses `govendor` to manage Go dependencies. To make things easier for reviewers, put updates to `vendor/` in a separate commit within the same PR. -Make code change that imports new library, then: +#### Add a new dependency + +First make the code change that imports your new library, then run the following in the root of the repo: ``` -# See missing +# View missing dependencies govendor list +missing -% govendor fetch -v +missing +# Download missing dependencies into vendor/ +govendor fetch -v +missing ``` -Note pinning a library to a specific version requires extra work. In -particular, we do this for `client-go` and `apimachinery` - to find -the current version used for these libraries, look in -`vendor/vendor.json` for the `version` field (not `versionExact`) of -an existing package. Use that same version in the commands below: +#### Pin a dependency to a specific version + +Note that pinning a library to a specific version requires extra work. + +We do this for key libraries like `client-go` and `apimachinery`. To find the current version used for these particular packages, look in `vendor/vendor.json` for the `version` field (not `versionExact`). +Use that same version in the commands below: + +``` +# Pin all imported client-go packages to release v3.0 +govendor fetch -v k8s.io/client-go/...@v3.0 ``` -# For example: To pin all imported client-go packages to release v3.0 -% govendor fetch -v k8s.io/client-go/...@v3.0 -# *Note* the above may pull in new packages from client-go, which will -# be imported at HEAD. You need to re-run the above command until -# all imports are at the desired version. -# TODO: There is probably a better way to do this. +*NOTE:* The command above may pull in new packages from `client-go`, which will +be imported at HEAD. You need to re-run the above command until *all* imports are at the desired version. + +If you make a mistake or miss some libraries, it is safe (and appropriate) to re-run `govendor fetch` with a different version. + +#### Clean up unnecessary dependencies + +Before sending a non-trivial change for review, consider running the following command: + +``` +# See unused dependencies +govendor list +unused + +# Remove unused dependencies +govendor remove +unused ``` -It is safe (and appropriate) to re-run `govendor fetch` with a -different version, if you made a mistake or missed some libraries. +### Test + +You can run ksonnet tests with `make test` in the root of the repo, specifying any additional, custom Go flags with `$EXTRA_GO_FLAGS`. + +### Make a Release -## Making a Release +To make a new release, follow these instructions: -1. Add appropriate tag. We do this via git (not github UI) so the tag - is signed. This process requires you to have write access to the - real master branch (not your local fork). +1. Add an appropriate tag. We do this via `git` (not the github UI) so that the tag is signed. This process requires you to have write access to the real `master` branch (not your local fork). ``` - % tag=vX.Y.Z - % git fetch # update - % git tag -s -m $tag $tag origin/master - % git push origin tag $tag + tag=vX.Y.Z + git fetch # update + git tag -s -m $tag $tag origin/master + git push origin tag $tag ``` -2. Wait for the travis autobuilders to build release binaries. +2. Wait for the Travis autobuilders to build release binaries. -3. *Now* create the github release, using the existing tag created +3. *Now* create the Github release, using the existing tag created above. diff --git a/DCO-SIGNOFF.md b/DCO-SIGNOFF.md new file mode 100644 index 00000000..ea32c1ea --- /dev/null +++ b/DCO-SIGNOFF.md @@ -0,0 +1,58 @@ +## DCO Sign off + +All authors to the project retain copyright to their work. However, to ensure +that they are only submitting work that they have rights to, we are requiring +everyone to acknowledge this by signing their work. + +Any copyright notices in this repos should specify the authors as "The +ksonnet authors". + +To sign your work, just add a line like this at the end of your commit message: + +``` +Signed-off-by: Joe Beda <joe@heptio.com> +``` + +This can easily be done with the `--signoff` option to `git commit`. + +By doing this you state that you can certify the following (from https://developercertificate.org/): + +``` +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +1 Letterman Drive +Suite D4700 +San Francisco, CA, 94129 + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. +``` diff --git a/README.md b/README.md index dddbc0e6..0acef237 100644 --- a/README.md +++ b/README.md @@ -6,75 +6,169 @@ *ksonnet* is a framework for writing, sharing, and deploying Kubernetes application manifests. With its CLI, you can generate a complete application from scratch in only a few commands, or manage a complex system at scale. Specifically, ksonnet allows you to: -* *Reuse* common manifest patterns (within your app or from external libraries) -* *Customize* manifests directly with powerful object concatenation syntax -* *Deploy* app manifests to multiple environments -* *Diff* across environments to compare two running versions of your app -* *Track* the entire state of your app manifests in version control +* **Reuse** common manifest patterns (within your app or from external libraries) +* **Customize** manifests directly with powerful object concatenation syntax +* **Deploy** app manifests to multiple environments +* **Diff** across environments to compare two running versions of your app +* **Track** the entire state of your app configuration in version controllable files + +All of this results in a more iterative process for developing manifests, one that can be supplemented by continuous integration (CI). *STATUS: Development is ongoing—this tool is pre-alpha.* ## Install -To build from source: +> You should have Go installed, and an appropriately set `$GOPATH`. (For most systems, the minimum Go version is 1.7. However, recent OSX may [require golang >=1.8.1](https://github.com/golang/go/issues/19734) to +avoid an immediate `Killed: 9`.) If you need additional help, see the [official Go installation guide](https://golang.org/doc/install#install). + +ksonnet is installed like any other Go binary. Run the following shell commands to download ksonnet and ensure that it is runnable in any directory: + +```bash +go get github.com/ksonnet/ksonnet +PATH=$PATH:$GOPATH/bin +``` + +If your ksonnet is properly installed, you should be able to run the following `--help` command and see similar output: -```console -% PATH=$PATH:$GOPATH/bin -% go get github.com/ksonnet/ksonnet ``` +$ ksonnet --help + +Synchronise Kubernetes resources with config files -Requires golang >=1.7 and a functional cgo environment (C++ with libstdc++). -Note that recent OSX environments -[require golang >=1.8.1](https://github.com/golang/go/issues/19734) to -avoid an immediate `Killed: 9`. +Usage: + ks [command] + +Available Commands: + apply Apply local configuration to remote cluster + delete Delete Kubernetes resources described in local config + diff Display differences between server and local config, or server and server config + env Manage ksonnet environments + generate Expand prototype, place in components/ directory of ksonnet app + ... +``` ## Quickstart -```console -# Include <ksonnet.git>/lib in ksonnet/jsonnet library search path. -# Can also use explicit `-J` args everywhere. -% export KUBECFG_JPATH=/path/to/ksonnet/lib +Here we provide a shell script that shows some basic ksonnet features in action. You can run this script to deploy and update a basic web app UI, via a Kubernetes Service and Deployment. This app is shown below: + +<p align="center"> +<img alt="guestbook screenshot" src="/docs/img/guestbook.png" style="width:60% !important;"> +</p> + +Note that we will not be implementing the entire app in this quickstart, so the buttons will not work! + +**Minimal explanation is provided here, and only basic ksonnet features are shown---this is intended to be a quick demonstration.** If you are interested in learning more, see [Additional Documentation](#additional-documentation). + +### Prerequisites +* *You should have access to an up-and-running Kubernetes cluster (**maximum version 1.7**).* Support for Kubernetes 1.8 is under development. -# Show generated YAML -% ks show -o yaml -f examples/guestbook.jsonnet + If you do not have a cluster, [choose a setup solution](https://kubernetes.io/docs/setup/) from the official Kubernetes docs. -# Create resources -% ks apply -f examples/guestbook.jsonnet +* *You should have `kubectl` installed.* If not, follow the instructions for [installing via Homebrew (MacOS)](https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-with-homebrew-on-macos) or [building the binary (Linux)](https://kubernetes.io/docs/tasks/tools/install-kubectl/#tabset-1). -# Modify configuration (downgrade gb-frontend image) -% sed -i.bak '\,gcr.io/google-samples/gb-frontend,s/:v4/:v3/' examples/guestbook.jsonnet -# See differences vs server -% ks diff -f examples/guestbook.jsonnet +* *Your `$KUBECONFIG` should specify a valid `kubeconfig` file*, which points at the cluster you want to use for this demonstration. -# Update to new config -% ks apply -f examples/guestbook.jsonnet +### Script + +Copy and paste the script below to deploy the container image for a basic web app UI: + +``` +# Start by creating your app directory +# (This references your current cluster using $KUBECONFIG) +ksonnet init quickstart +cd quickstart + +# Autogenerate a basic manifest +ksonnet generate deployment-exposed-with-service guestbook-ui \ +--name guestbook \ +--image alpinejay/dns-single-redis-guestbook:0.3 \ +--type ClusterIP + +# Deploy your manifest to your cluster +ksonnet apply default + +# Set up an API proxy so that you can access the guestbook service locally +kc proxy > /dev/null & +PROXY_PID=$! +QUICKSTART_NAMESPACE=$(kubectl get svc guestbook -o jsonpath="{.metadata.namespace}") +GUESTBOOK_SERVICE_URL=http://localhost:8001/api/v1/proxy/namespaces/$QUICKSTART_NAMESPACE/services/guestbook + +# Check out the guestbook app in your browser (NOTE: the buttons don't work!) +open $GUESTBOOK_SERVICE_URL + +``` + +The rest of this script upgrades the container image to a new version: -# Clean up after demo -% ks delete -f examples/guestbook.jsonnet ``` +# Bump the container image to a different version +ksonnet param set guestbook-ui image alpinejay/dns-single-redis-guestbook:0.4 + +# See the differences between your local manifest and what's running on your cluster +# (ERROR is expected here since there are differences) +ksonnet diff local:default remote:default + +# Update your cluster with your latest changes +ksonnet apply default + +# (Wait a bit) and open another tab to see newly added javascript +open $GUESTBOOK_SERVICE_URL + +``` + +Notice that the webpage looks different! Now clean up: + +``` +# Teardown +kill -9 $PROXY_PID +ksonnet delete default + +# There should be no guestbook service left running +kubectl get svc guestbook +``` + +Even though you've made modifications to the Guestbook app and removed it from your cluster, ksonnet still tracks all your manifests locally: + +``` +# View all expanded manifests (YAML) +ks show default +``` + +If you're wondering how ksonnet differs from existing tools, the full-length tutorial (WIP) shows you how to use other ksonnet features to implement the rest of the Guestbook app (so that the buttons work!). + +## Additional documentation + +ksonnet is a feature-rich framework. To learn more about how to integrate it into your workflow, check out the resources below: + +* **Tutorial (WIP)** - How do I use ksonnet and why? This finishes the Guestbook app from the [Quickstart](#quickstart) above. + +* **Interactive tour of ksonnet (WIP)** - Where does the ksonnet magic come from? + +* **[CLI Reference](/docs/cli-reference#command-line-reference)** - What ksonnet commands are available, and how do I use them? + +* **[Concept Reference (WIP)](/docs/concepts.md)** - What do all these special ksonnet terms mean (e.g. *prototypes*) ? + + +## Troubleshooting + +If you encounter any problems that the documentation does not address, [file an issue](https://github.com/ksonnet/ksonnet/issues). + +## Contributing -## Features +Thanks for taking the time to join our community and start contributing! -- Supports JSON, YAML or jsonnet files (by file suffix). -- Best-effort sorts objects before updating, so that dependencies are - pushed to the server before objects that refer to them. -- Additional jsonnet builtin functions. See `lib/kubecfg.libsonnet`. +#### Before you start -## Infrastructure-as-code Philosophy +* Please familiarize yourself with the [Code of +Conduct](CODE_OF_CONDUCT.md) before contributing. +* Read the contribution guidelines in [CONTRIBUTING.md](CONTRIBUTING.md). +* There is a [mailing list](https://groups.google.com/forum/#!forum/ksonnet) and [Slack channel](https://ksonnet.slack.com/) if you want to interact with +other members of the community. -The idea is to describe *as much as possible* about your configuration -as files in version control (eg: git). +#### Pull requests -Changes to the configuration follow a regular review, approve, merge, -etc code change workflow (github pull-requests, phabricator diffs, -etc). At any point, the config in version control captures the entire -desired-state, so the system can be easily recreated in a QA cluster -or to recover from disaster. +* We welcome pull requests. Feel free to dig through the [issues](https://github.com/ksonnet/ksonnet/issues) and jump in. -### Jsonnet +## Changelog -ksonnet relies heavily on [jsonnet](http://jsonnet.org/) to describe -Kubernetes resources, and is really just a thin Kubernetes-specific -wrapper around jsonnet evaluation. You should read the jsonnet -[tutorial](http://jsonnet.org/docs/tutorial.html), and skim the functions available in the jsonnet [`std`](http://jsonnet.org/docs/stdlib.html) -library. +See [the list of releases](https://github.com/ksonnet/ksonnet/releases) to find out about feature changes. diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..c9cdd003 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,6 @@ +## Additional documentation + +While the ksonnet site updates are still pending, you can find additional documentation in this directory: + +* [CLI reference](/docs/cli-reference#command-line-reference) +* [Concept reference](/docs/concepts.md) diff --git a/docs/cli-reference/README.md b/docs/cli-reference/README.md index b7fd6401..aa5d8923 100644 --- a/docs/cli-reference/README.md +++ b/docs/cli-reference/README.md @@ -1,5 +1,65 @@ # Command line reference -Ksonnet provides a CLI (invoked with `ks`) that allows you to generate Kubernetes resource manifests locally (in `jsonnet`, `JSON`, or `YAML` format) and synchronize them with your remote cluster(s). +Ksonnet provides a CLI (invoked with [`ks`](ks.md)) that allows you to generate Kubernetes resource manifests locally (in `jsonnet`) and synchronize them with your remote cluster(s). *The files in this directory enumerate each of the possible `ks` commands and their flags. Note that you can also find this info with the CLI itself, using the `--help` flag.* + +Suggested command usage is described below: + +## Getting started + +* Set up a ksonnet [*application*](/docs/concepts.md#application) + * [`ks init`](ks_init.md) + +* Generate [*components*](/docs/concepts.md#component) for your app (e.g. Redis) + * [`ks generate`](ks_generate.md) (alias of [`ks prototype use`](ks_prototype_use.md)) + +* Deploy to a cluster + * [`ks apply`](ks_apply.md) + +* Delete resources running on a cluster + * [`ks delete`](ks_delete.md) + +## Fancier components + +* Learn about existing [*prototypes*](/docs/concepts.md#prototype) ([`ks prototype`](ks_prototype.md)) + * [`ks prototype list`](ks_prototype_list.md) + * [`ks prototype search`](ks_prototype_search.md) + * [`ks prototype describe`](ks_prototype_describe.md) + * [`ks prototype preview`](ks_prototype_preview.md) + +* Learn about and download currently available [*packages*](/docs/concepts.md#package) ([`ks pkg`](ks_pkg.md)) + * [`ks pkg list`](ks_pkg_list.md) + * [`ks pkg describe`](ks_pkg_describe.md) + * [`ks pkg install`](ks_pkg_install.md) + +* Learn about existing [*registries*](/docs/concepts.md#registry) ([`ks registry`](ks_registry.md)) + * [`ks registry list`](ks_registry_list.md) + * [`ks registry describe `](ks_registry_describe.md) + +## Environments + +* Managing [*environments*](/docs/concepts.md#environment) ([`ks env`](ks_env.md)) + * [`ks env list`](ks_env_list.md) + * [`ks env add`](ks_env_add.md) + * [`ks env set`](ks_env_set.md) + * [`ks env rm`](ks_env_rm.md) + +* Customizing environments with [*parameters*](/docs/concepts.md#parameter) ([`ks param`](ks_param.md)) + * [`ks param list`](ks_param_list.md) + * [`ks param set`](ks_param_set.md) + +* Comparing environments + * [`ks diff`](ks_diff.md) + * [`ks param diff`](ks_param_diff.md) + +## Miscellaneous + +* View expanded manifests + * [`ks show`](ks_show.md) + +* Validate manifests against the Kubernetes API + * [`ks validate`](ks_validate.md) + +* View metadata about the ksonnet binary + * [`ks version`](ks_version.md) diff --git a/docs/concepts.md b/docs/concepts.md new file mode 100644 index 00000000..f127cc8e --- /dev/null +++ b/docs/concepts.md @@ -0,0 +1,27 @@ +## Concepts + +The ksonnet framework is centered around a couple of key concepts. + +### Application +TODO + +### Environment +TODO + +### Component +TODO + +### Prototype +TODO + +### Parameter +TODO + +### Part +TODO + +### Package +TODO + +### Registry +TODO diff --git a/docs/img/guestbook.png b/docs/img/guestbook.png new file mode 100644 index 0000000000000000000000000000000000000000..e7ae9866af773970eb1abd962703ed371de002b2 GIT binary patch literal 12235 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 literal 0 HcmV?d00001 -- GitLab