diff --git a/README.md b/README.md
index 198dd73..ec84c82 100644
--- a/README.md
+++ b/README.md
@@ -6,12 +6,14 @@
[![Get it from the Snap Store](https://badgen.net/snapcraft/v/operator-builder)](https://snapcraft.io/operator-builder)
![Github Downloads (by Release)](https://img.shields.io/github/downloads/vmware-tanzu-labs/operator-builder/total.svg)
-
-
# Operator Builder
**Accelerate the development of Kubernetes Operators.**
+Operator Builder is a command line tool that ingests Kubernetes manifests and
+generates the source code for a working Kubernetes operator based on the
+resources defined in those manifests.
+
Operator Builder extends [Kubebuilder](https://github.com/kubernetes-sigs/kubebuilder)
to facilitate development and maintenance of Kubernetes operators. It is especially
helpful if you need to take large numbers of resources defined with static or
@@ -33,465 +35,22 @@ The custom resource defined in the source code can be cluster-scoped or
namespace-scoped based on the requirements of the project. More info
[here](docs/resource-scope.md).
-## Prerequisites
-
-- Make
-- Go version 1.16 or later
-- Docker (for building/pushing controller images)
-- An available test cluster. A local kind or minikube cluster will work just
- fine in many cases.
-- Operator Builder [installed](#installation).
-- [kubectl installed](https://kubernetes.io/docs/tasks/tools/#kubectl).
-- A set of static Kubernetes manifests that can be used to deploy
- your workload. It is highly recommended that you apply these manifests to a
- test cluster and verify the resulting resources work as expected.
- If you don't have a workload of your own to use, you can use the examples
- provided in this guide.
-
-## Installation Options
-
-### [Download the latest binary](https://github.com/vmware-tanzu-labs/operator-builder/releases/latest)
-
-### wget
-Use wget to download the pre-compiled binaries:
-
-```bash
-wget https://github.com/vmware-tanzu-labs/operator-builder/releases/download/${VERSION}/${BINARY}.tar.gz -O - |\
- tar xz && sudo mv operator-builder /usr/bin/operator-builder
-```
-
-For instance, VERSION=v0.5.0 and BINARY=operator-builder_${VERSION}_Linux_x86_64
-
-### MacOS / Linux via Homebrew install
-
-Using [Homebrew](https://brew.sh/)
-
-```bash
-brew tap vmware-tanzu-labs/tap
-brew install operator-builder
-```
-
-### Linux snap install
-
-```bash
-snap install operator-builder
-```
-
->**NOTE**: `operator-builder` installs with [_strict confinement_](https://docs.snapcraft.io/snap-confinement/6233) in snap, this means it doesn't have direct access to root files.
-
-### Docker image pull
-
-```bash
-docker pull ghcr.io/vmawre-tanzu-labs/operator-builder
-```
-
-#### One-shot container use
-
-```bash
-docker run --rm -v "${PWD}":/workdir ghcr.io/vmware-tanzu-labs/operator-builder [flags]
-```
-
-
-#### Run container commands interactively
-
-```bash
-docker run --rm -it -v "${PWD}":/workdir --entrypoint sh ghcr.io/vmawre-tanzu-labs/operator-builder
-```
-
-It can be useful to have a bash function to avoid typing the whole docker command:
-
-```bash
-operator-builder() {
- docker run --rm -i -v "${PWD}":/workdir ghcr.io/vmware-tanzu-labs/operator-builder "$@"
-}
-```
-
-### Go install
-
-```bash
-GO111MODULE=on go get github.com/vmware-tanzu-labs/operator-builder/cmd/operator-builder
-```
-## Getting Started
-
-This guide will walk you through the creation of a Kubernetes operator for a
-single workload. This workload can consist of any number of Kubernetes
-resources and will be configured with a single custom resource. Please review
-the [prerequisites](#prerequisites) prior to attempting to follow this guide.
-
-This guide consists of the following steps:
-
-1. [Create a repository](#step-1).
-1. Determine what fields in your static manifests will need to be configurable for
- deployment into different environments. [Add commented markers to the
- manifests](#step-2). These will serve as instructions to Operator Builder.
-1. [Create a workload configuration for your project](#step-3).
-1. [Use the Operator Builder CLI to generate the source code for your operator](#step-4).
-1. [Test the operator against your test cluster](#step-5).
-1. [Build and install your operator's controller manager in your test cluster](#step-6).
-1. [Build and test the operator's companion CLI](#step-7).
-
-### Step 1
-
-Create a new directory for your operator's source code. We recommend you follow
-the standard [code organization
-guidelines](https://golang.org/doc/code#Organization).
-In that directory initialize a new git repo.
-
- git init
-
-And intialize a new go module. The module should be the import path for your
-project, usually something like `github.com/user-account/project-name`. Use the
-command `go help importpath` for more info.
-
- go mod init [module]
-
-Lastly create a directory for your static manifests. Operator Builder will use
-these as a source for defining resources in your operator's codebase. It must be a
-hidden directory so as not to interfere with source code generation.
-
- mkdir .source-manifests
-
-Put your static manifests in this `.source-manifests` directory. In the next
-step we will add commented markers to them. Note that these static manifests
-can be in one or more files. And you can have one or more manifests (separated
-by `---`) in each file. Just organize them in a way that makes sense to you.
-
-### Step 2
-
-Look through your static manifests and determine which fields will need to be
-configurable for deployment into different environments. Let's look at a simple
-example to illustrate. Following is a Deployment, Ingress and Service that may
-be used to deploy a workload.
-
- # .source-manifests/app.yaml
-
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: webstore-deploy
- spec:
- replicas: 2 # <===== configurable
- selector:
- matchLabels:
- app: webstore
- template:
- metadata:
- labels:
- app: webstore
- spec:
- containers:
- - name: webstore-container
- image: nginx:1.17 # <===== configurable
- ports:
- - containerPort: 8080
- ---
- apiVersion: networking.k8s.io/v1beta1
- kind: Ingress
- metadata:
- name: webstore-ing
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /
- spec:
- rules:
- - host: app.acme.com
- http:
- paths:
- - path: /
- backend:
- serviceName: webstorep-svc
- servicePort: 80
- ---
- kind: Service
- apiVersion: v1
- metadata:
- name: webstore-svc
- spec:
- selector:
- app: webstore
- ports:
- - protocol: TCP
- port: 80
- targetPort: 8080
-
-There are two fields in the Deployment manifest that will need to be
-configurable. They are noted with comments. The Deployment's replicas and the
-Pod's container image will change between different environments. For example,
-in a dev environment the number of replicas will be low and a development
-version of the app will be run. In production, there will be more replicas and
-a stable release of the app will be used. In this example we don't have any
-configurable fields in the Ingress or Service.
-
-Next we need to use `+operator-builder:field` markers in comments to inform Operator Builder
-that the operator will need to support configuration of these elements.
-Following is the Deployment manifest with these markers in place.
-
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: webstore-deploy
- labels:
- team: dev-team # +operator-builder:field:name=teamName,type=string
- spec:
- replicas: 2 # +operator-builder:field:name=webStoreReplicas,default=2,type=int
- selector:
- matchLabels:
- app: webstore
- template:
- metadata:
- labels:
- app: webstore
- team: dev-team # +operator-builder:field:name=teamName,type=string
- spec:
- containers:
- - name: webstore-container
- image: nginx:1.17 # +operator-builder:field:name=webStoreImage,type=string
- ports:
- - containerPort: 8080
-
-These markers should always be provided as an in-line comment or as a head
-comment. The marker always begins with `+operator-builder:field:` or
-`+operator-builder:collection:field:` See [Markers](docs/markers.md) to learn
-more.
-
-### Step 3
-
-Operator Builder uses a workload configuration to provide important details for
-your operator project. This guide uses a [standalone
-workload](docs/standalone-workloads.md). Save a workload config to your
-`.source-manifests` directory by using one of the following commands (or
-simply copy/pasting the YAML below the commands):
-
- # generate a workload config with the path (-p) flag
- operator-builder init-config standalone -p .source-manifests/workload.yaml
-
- # generate a workload config from stdout
- operator-builder init-config standalone > .source-manifests/workload.yaml
-
-This will generate the following YAML:
-
- # .source-manifests/workload.yaml
- name: webstore
- kind: StandaloneWorkload
- spec:
- api:
- domain: acme.com
- group: apps
- version: v1alpha1
- kind: WebStore
- clusterScoped: false
- companionCliRootcmd:
- name: webstorectl
- description: Manage webstore application
- resources:
- - app.yaml
-
-The `name` is arbitrary and can be whatever you like.
-
-In the `spec`, the following fields are required:
-
-- `api.domain`: This must be a globally unique name that will not be used by other
- organizations or groups. It will contain groups of API types.
-- `api.group`: This is a logical group of API types used as a namespacing
- mechanism for your APIs.
-- `api.version`: Provide the intiial version for your API.
-- `api.kind`: The name of the API type that will represent the workload you are
- managing with this operator.
-- `resources`: An array of filenames where your static manifests live. List the
- relative path from the workload manifest to all the files that contain the
- static manifests we talked about in step 2.
-
-For more info about API groups, versions and kinds, check out the [Kubebuilder
-docs](https://kubebuilder.io/cronjob-tutorial/gvks.html).
-
-The following fields in the `spec` are optional:
-
-- `api.clusterScoped`: If your workload includes cluster-scoped resources like
- namespaces, this will need to be `true`. The default is `false`.
-- `companionCLIRootcmd`: If you wish to generate source code for a companion CLI
- for your operator, include this field. We recommend you do. Your end users
- will appreciate it.
- - `name`: The root command your end users will type when using the companion
- CLI.
- - `description`: The general information your end users will get if they use
- the `help` subcommand of your companion CLI.
-
-At this point in our example, our `.source-manifests` directory looks as
-follows:
-
- tree .source-manifests
-
- .source-manifests
- ├── app.yaml
- └── workload.yaml
-
-Our StandaloneWorkload config is in `workload.yaml` and the Deployment, Ingress
-and Service manifests are in `app.yaml` and referenced under `spec.resources` in
-our StandaloneWorkload config.
-
-We are now ready to generate our project's source code.
-
-### Step 4
-
-We first use the `init` command to create the general scaffolding. We run this
-command from the root of our repo and provide a single argument with the path to
-our workload config.
-
- operator-builder init \
- --workload-config .source-manfiests/workload.yaml
-
-With the basic project now set up, we can now run the `create api` command to
-create a new custom API for our workload.
-
- operator-builder create api \
- --workload-config .source-manfiests/workload.yaml \
- --controller \
- --resource
-
-We again provide the same workload config file. Here we also added the
-`--controller` and `--resource` arguments. These indicate that we want both a
-new controller and new custom resource created.
-
-You now have a new working Kubernetes Operator! Next, we will test it out.
-
-### Step 5
-
-Assuming you have a kubeconfig in place that allows you to interact with your
-cluster with kubectl, you are ready to go.
-
-First, install the new custom resource definition (CRD).
-
- make install
-
-Now we can run the controller locally to test it out.
-
- make run
-
-Operator Builder created a sample manifest in the `config/samples` directory.
-For this example it looks like this:
-
- apiVersion: apps.acme.com/v1alpha1
- kind: WebStore
- metadata:
- name: webstore-sample
- spec:
- webStoreReplicas: 2
- webStoreImage: nginx:1.17
- teamName: dev-team
-
-You will notice the fields and values in the `spec` were derived from the
-markers you added to your static manifests.
-
-Next, in another terminal, create a new instance of your workload with
-the provided sample manifest.
-
- kubectl apply -f config/samples/
-
-You should see your custom resource sample get created. Now use `kubectl` to
-inspect your cluster to confirm the workload's resources got created. You should
-find all the resources that were defined in your static manifests.
-
- kubectl get all
-
-Clean up by stopping your controller with ctrl-c in that terminal and then
-remove all the resources you just created.
-
- make uninstall
-
-### Step 6
-
-Now let's deploy your controller into the cluster.
-
-First export an environment variable for your container image.
-
- export IMG=myrepo/acme-webstore-mgr:0.1.0
-
-Run the rest of the commands in this step 6 in this same terminal as most of
-them will need this `IMG` env var.
-
-In order to run the controller in-cluster (as opposed to running locally with
-`make run`) we will need to build a container image for it.
-
- make docker-build
-
-Now we can push it to a registry that is accessible from the test cluster.
-
- make docker-push
-
-Finally, we can deploy it to our test cluster.
-
- make deploy
-
-Next, perform the same tests from step 5 to ensure proper operation of our
-operator.
-
- kubectl apply -f config/sample/
-
-Again, verify that all the resources you expect are created.
-
-Once satisfied, remove the instance of your workload.
-
- kubectl delete -f config/sample/
-
-For now, leave the controller running in your test cluster. We'll use it in
-Step 7.
-
-### Step 7
-
-Now let's build and test the companion CLI.
-
-You will have a make target that includes the name of your CLI. For this
-example it is:
-
- make build-webstorectl
-
-We can view the help info as follows.
-
- ./bin/webstorectl help
-
-Your end users can use it to create a new custom resource manifest.
-
- ./bin/webstorectl init > /tmp/webstore.yaml
-
-If you would like to change any of the default values, edit the file.
-
- vim /tmp/webstore.yaml
-
-Then you can apply it to the cluster.
-
- kubectl apply -f /tmp/webstore.yaml
-
-If your end users find they wish to make changes to the resources that aren't
-supported by the operator, they can generate the resources from the custom
-resource.
-
- ./bin/webstorectl generate --workload-manifest /tmp/webstore.yaml
-
-This will print the resources to stdout. These may be piped into an overlay
-tool or written to disk and modified before applying to a cluster.
-
-That's it! You have a working operator without manually writing a single line
-of code. If you'd like to make any changes to your workload's API, you'll find
-the code in the `apis` directory. The controller's source code is in
-`controllers` directory. And the companion CLI code is in `cmd`.
-
-Don't forget to clean up. Remove the controller, CRD and the workload's
-resources as follows.
-
- make undeploy
-
-For more information, checkout the [Operator Builder docs](docs/) as
-well as the [Kubebuilder docs](https://kubebuilder.io/).
-
-## Workload Collections
+## Documentation
-Operator Builder can generate source code for operators that manage multiple
-workloads. See [workload collections](docs/workload-collections.md) for more info.
+### User Docs
-## Licensing
+* [Installation](docs/installation.md)
+* [Getting Started](docs/getting-started.md)
+* [Workloads](docs/workloads.md)
+ * [Standalone Workloads](docs/standalone-workloads.md)
+ * [Workload Collections](docs/workload-collections.md)
+* [Markers](docs/markers.md)
+* [Resource Scope](docs/resource-scope.md)
+* [Companion CLI](docs/companion-cli.md)
+* [API Updates & Upgrades](docs/api-updates-upgrades.md)
+* [License Manaagement](docs/license.md)
-Operator Builder can help manage licensing for the resulting project. More
-info [here](docs/license.md).
+### Developer Docs
-## Testing
+* [Testing](docs/testing.md)
-Testing of Operator Builder is documented [here](docs/testing.md).
diff --git a/docs/api-updates-upgrades.md b/docs/api-updates-upgrades.md
index f92df62..f116f34 100644
--- a/docs/api-updates-upgrades.md
+++ b/docs/api-updates-upgrades.md
@@ -18,11 +18,13 @@ describe how to overwrite an existing API to update the existing spec.
After making the necessary changes to your manifests run the following:
- operator-builder create api \
- --workload-config [path/to/workload/config] \
- --controller=false \
- --resource \
- --force
+```bash
+operator-builder create api \
+ --workload-config [path/to/workload/config] \
+ --controller=false \
+ --resource \
+ --force
+```
You will pass the same workload config file. The `--controller=false` flag will
skip generating controller code but `--resource` and `--force` will cause the
@@ -111,7 +113,7 @@ the software when other features not related to an API are released.
To create a new version of an existing API, update the `spec.api.version` value
in your workload config, for example:
-```
+```yaml
name: webstore
kind: StandaloneWorkload
spec:
@@ -130,11 +132,13 @@ spec:
Now reference the config in a new `create api` command:
- operator-builder create api \
- --workload-config [path/to/workload/config] \
- --controller \
- --resource \
- --force
+```bash
+operator-builder create api \
+ --workload-config [path/to/workload/config] \
+ --controller \
+ --resource \
+ --force
+```
Note that we _do_ want to re-generate the controller in this case.
A new API definition will be create alongside the previous version. If the
@@ -143,24 +147,26 @@ version.
For example if your APIs look as follows:
- tree apis/apps
- apis/apps
- ├── v1alpha1
- │ ├── groupversion_info.go
- │ ├── webstore
- │ │ ├── app.go
- │ │ └── resources.go
- │ ├── webstore_types.go
- │ └── zz_generated.deepcopy.go
- └── v1alpha2
- ├── groupversion_info.go
- ├── webstore
- │ ├── app.go
- │ └── resources.go
- ├── webstore_types.go
- └── zz_generated.deepcopy.go
-
- 4 directories, 10 files
+```bash
+tree apis/apps
+apis/apps
+├── v1alpha1
+│ ├── groupversion_info.go
+│ ├── webstore
+│ │ ├── app.go
+│ │ └── resources.go
+│ ├── webstore_types.go
+│ └── zz_generated.deepcopy.go
+└── v1alpha2
+ ├── groupversion_info.go
+ ├── webstore
+ │ ├── app.go
+ │ └── resources.go
+ ├── webstore_types.go
+ └── zz_generated.deepcopy.go
+
+4 directories, 10 files
+```
You will delete the earlier version with `rm -rf apis/apps/v1alpha1`.
diff --git a/docs/companion-cli.md b/docs/companion-cli.md
index 86a6ac5..17e021e 100644
--- a/docs/companion-cli.md
+++ b/docs/companion-cli.md
@@ -1,6 +1,8 @@
# Companion CLI
-Generate source code for a companion CLI to a Kubernetes operator.
+When you generate the source code for a Kubernetes operator with Operator
+Builder, it can include the code for a companion CLI. The source code for the
+companion CLI will be found in the `cmd` directory of the generated codebase.
The companion CLI does three things:
1. Generate Sample Manifests: the `init` command will save a sample manifest to
diff --git a/docs/getting-started.md b/docs/getting-started.md
new file mode 100644
index 0000000..7602158
--- /dev/null
+++ b/docs/getting-started.md
@@ -0,0 +1,446 @@
+# Getting Started
+
+## Prerequisites
+
+- Make
+- Go version 1.16 or later
+- Docker (for building/pushing controller images)
+- An available test cluster. A local kind or minikube cluster will work just
+ fine in many cases.
+- Operator Builder [installed](#installation).
+- [kubectl installed](https://kubernetes.io/docs/tasks/tools/#kubectl).
+- A set of static Kubernetes manifests that can be used to deploy
+ your workload. It is highly recommended that you apply these manifests to a
+ test cluster and verify the resulting resources work as expected.
+ If you don't have a workload of your own to use, you can use the examples
+ provided in this guide.
+
+## Guide
+
+This guide will walk you through the creation of a Kubernetes operator for a
+single workload. This workload can consist of any number of Kubernetes
+resources and will be configured with a single custom resource. Please review
+the [prerequisites](#prerequisites) prior to attempting to follow this guide.
+
+This guide consists of the following steps:
+
+1. [Create a repository](#step-1).
+1. Determine what fields in your static manifests will need to be configurable for
+ deployment into different environments. [Add commented markers to the
+ manifests](#step-2). These will serve as instructions to Operator Builder.
+1. [Create a workload configuration for your project](#step-3).
+1. [Use the Operator Builder CLI to generate the source code for your operator](#step-4).
+1. [Test the operator against your test cluster](#step-5).
+1. [Build and install your operator's controller manager in your test cluster](#step-6).
+1. [Build and test the operator's companion CLI](#step-7).
+
+### Step 1: Create a Repo
+
+Create a new directory for your operator's source code. We recommend you follow
+the standard [code organization
+guidelines](https://golang.org/doc/code#Organization).
+In that directory initialize a new git repo.
+
+```bash
+git init
+```
+
+And intialize a new go module. The module should be the import path for your
+project, usually something like `github.com/user-account/project-name`. Use the
+command `go help importpath` for more info.
+
+```bash
+go mod init [module]
+```
+
+Lastly create a directory for your static manifests. Operator Builder will use
+these as a source for defining resources in your operator's codebase. It must be a
+hidden directory so as not to interfere with source code generation.
+
+```bash
+mkdir .source-manifests
+```
+
+Put your static manifests in this `.source-manifests` directory. In the next
+step we will add commented markers to them. Note that these static manifests
+can be in one or more files. And you can have one or more manifests (separated
+by `---`) in each file. Just organize them in a way that makes sense to you.
+
+### Step 2: Add Manifest Markers
+
+Look through your static manifests and determine which fields will need to be
+configurable for deployment into different environments. Let's look at a simple
+example to illustrate. Following is a Deployment, Ingress and Service that may
+be used to deploy a workload.
+
+```yaml
+# .source-manifests/app.yaml
+
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: webstore-deploy
+spec:
+ replicas: 2 # <===== configurable
+ selector:
+ matchLabels:
+ app: webstore
+ template:
+ metadata:
+ labels:
+ app: webstore
+ spec:
+ containers:
+ - name: webstore-container
+ image: nginx:1.17 # <===== configurable
+ ports:
+ - containerPort: 8080
+---
+apiVersion: networking.k8s.io/v1beta1
+kind: Ingress
+metadata:
+ name: webstore-ing
+ annotations:
+ nginx.ingress.kubernetes.io/rewrite-target: /
+spec:
+ rules:
+ - host: app.acme.com
+ http:
+ paths:
+ - path: /
+ backend:
+ serviceName: webstorep-svc
+ servicePort: 80
+---
+kind: Service
+apiVersion: v1
+metadata:
+ name: webstore-svc
+spec:
+ selector:
+ app: webstore
+ ports:
+ - protocol: TCP
+ port: 80
+ targetPort: 8080
+```
+
+There are two fields in the Deployment manifest that will need to be
+configurable. They are noted with comments. The Deployment's replicas and the
+Pod's container image will change between different environments. For example,
+in a dev environment the number of replicas will be low and a development
+version of the app will be run. In production, there will be more replicas and
+a stable release of the app will be used. In this example we don't have any
+configurable fields in the Ingress or Service.
+
+Next we need to use `+operator-builder:field` markers in comments to inform Operator Builder
+that the operator will need to support configuration of these elements.
+Following is the Deployment manifest with these markers in place.
+
+```yaml
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: webstore-deploy
+ labels:
+ team: dev-team # +operator-builder:field:name=teamName,type=string
+spec:
+ replicas: 2 # +operator-builder:field:name=webStoreReplicas,default=2,type=int
+ selector:
+ matchLabels:
+ app: webstore
+ template:
+ metadata:
+ labels:
+ app: webstore
+ team: dev-team # +operator-builder:field:name=teamName,type=string
+ spec:
+ containers:
+ - name: webstore-container
+ image: nginx:1.17 # +operator-builder:field:name=webStoreImage,type=string
+ ports:
+ - containerPort: 8080
+```
+
+These markers should always be provided as an in-line comment or as a head
+comment. The marker always begins with `+operator-builder:field:` or
+`+operator-builder:collection:field:` See [Markers](docs/markers.md) to learn
+more.
+
+### Step 3: Create a Workload Config
+
+Operator Builder uses a workload configuration to provide important details for
+your operator project. This guide uses a [standalone
+workload](docs/standalone-workloads.md). Save a workload config to your
+`.source-manifests` directory by using one of the following commands (or
+simply copy/pasting the YAML below the commands):
+
+```bash
+# generate a workload config with the path (-p) flag
+operator-builder init-config standalone -p .source-manifests/workload.yaml
+
+# generate a workload config from stdout
+operator-builder init-config standalone > .source-manifests/workload.yaml
+```
+
+This will generate the following YAML:
+
+```yaml
+# .source-manifests/workload.yaml
+name: webstore
+kind: StandaloneWorkload
+spec:
+ api:
+ domain: acme.com
+ group: apps
+ version: v1alpha1
+ kind: WebStore
+ clusterScoped: false
+ companionCliRootcmd:
+ name: webstorectl
+ description: Manage webstore application
+ resources:
+ - app.yaml
+```
+
+The `name` is arbitrary and can be whatever you like.
+
+In the `spec`, the following fields are required:
+
+- `api.domain`: This must be a globally unique name that will not be used by other
+ organizations or groups. It will contain groups of API types.
+- `api.group`: This is a logical group of API types used as a namespacing
+ mechanism for your APIs.
+- `api.version`: Provide the intiial version for your API.
+- `api.kind`: The name of the API type that will represent the workload you are
+ managing with this operator.
+- `resources`: An array of filenames where your static manifests live. List the
+ relative path from the workload manifest to all the files that contain the
+ static manifests we talked about in step 2.
+
+For more info about API groups, versions and kinds, check out the [Kubebuilder
+docs](https://kubebuilder.io/cronjob-tutorial/gvks.html).
+
+The following fields in the `spec` are optional:
+
+- `api.clusterScoped`: If your workload includes cluster-scoped resources like
+ namespaces, this will need to be `true`. The default is `false`.
+- `companionCLIRootcmd`: If you wish to generate source code for a companion CLI
+ for your operator, include this field. We recommend you do. Your end users
+ will appreciate it.
+ - `name`: The root command your end users will type when using the companion
+ CLI.
+ - `description`: The general information your end users will get if they use
+ the `help` subcommand of your companion CLI.
+
+At this point in our example, our `.source-manifests` directory looks as
+follows:
+
+```bash
+tree .source-manifests
+
+.source-manifests
+├── app.yaml
+└── workload.yaml
+```
+
+Our StandaloneWorkload config is in `workload.yaml` and the Deployment, Ingress
+and Service manifests are in `app.yaml` and referenced under `spec.resources` in
+our StandaloneWorkload config.
+
+We are now ready to generate our project's source code.
+
+### Step 4: Generate Operator Source Code
+
+We first use the `init` command to create the general scaffolding. We run this
+command from the root of our repo and provide a single argument with the path to
+our workload config.
+
+```bash
+operator-builder init \
+ --workload-config .source-manfiests/workload.yaml
+```
+
+With the basic project now set up, we can now run the `create api` command to
+create a new custom API for our workload.
+
+```bash
+operator-builder create api \
+ --workload-config .source-manfiests/workload.yaml \
+ --controller \
+ --resource
+```
+
+We again provide the same workload config file. Here we also added the
+`--controller` and `--resource` arguments. These indicate that we want both a
+new controller and new custom resource created.
+
+You now have a new working Kubernetes Operator! Next, we will test it out.
+
+### Step 5: Run & Test the Operator
+
+Assuming you have a kubeconfig in place that allows you to interact with your
+cluster with kubectl, you are ready to go.
+
+First, install the new custom resource definition (CRD).
+
+```bash
+make install
+```
+
+Now we can run the controller locally to test it out.
+
+```bash
+make run
+```
+
+Operator Builder created a sample manifest in the `config/samples` directory.
+For this example it looks like this:
+
+```yaml
+apiVersion: apps.acme.com/v1alpha1
+kind: WebStore
+metadata:
+ name: webstore-sample
+spec:
+ webStoreReplicas: 2
+ webStoreImage: nginx:1.17
+ teamName: dev-team
+```
+
+You will notice the fields and values in the `spec` were derived from the
+markers you added to your static manifests.
+
+Next, in another terminal, create a new instance of your workload with
+the provided sample manifest.
+
+```bash
+kubectl apply -f config/samples/
+```
+
+You should see your custom resource sample get created. Now use `kubectl` to
+inspect your cluster to confirm the workload's resources got created. You should
+find all the resources that were defined in your static manifests.
+
+```bash
+kubectl get all
+```
+
+Clean up by stopping your controller with ctrl-c in that terminal and then
+remove all the resources you just created.
+
+```bash
+make uninstall
+```
+
+### Step 6: Build & Deploy the Controller Manager
+
+Now let's deploy your controller into the cluster.
+
+First export an environment variable for your container image.
+
+```bash
+export IMG=myrepo/acme-webstore-mgr:0.1.0
+```
+
+Run the rest of the commands in this step 6 in this same terminal as most of
+them will need this `IMG` env var.
+
+In order to run the controller in-cluster (as opposed to running locally with
+`make run`) we will need to build a container image for it.
+
+```bash
+make docker-build
+```
+
+Now we can push it to a registry that is accessible from the test cluster.
+
+```bash
+make docker-push
+```
+
+Finally, we can deploy it to our test cluster.
+
+```bash
+make deploy
+```
+
+Next, perform the same tests from step 5 to ensure proper operation of our
+operator.
+
+```bash
+kubectl apply -f config/sample/
+```
+
+Again, verify that all the resources you expect are created.
+
+Once satisfied, remove the instance of your workload.
+
+```bash
+kubectl delete -f config/sample/
+```
+
+For now, leave the controller running in your test cluster. We'll use it in
+Step 7.
+
+### Step 7: Build & Test Companion CLI
+
+Now let's build and test the companion CLI.
+
+You will have a make target that includes the name of your CLI. For this
+example it is:
+
+```bash
+make build-webstorectl
+```
+
+We can view the help info as follows.
+
+```bash
+./bin/webstorectl help
+```
+
+Your end users can use it to create a new custom resource manifest.
+
+```bash
+./bin/webstorectl init > /tmp/webstore.yaml
+```
+
+If you would like to change any of the default values, edit the file.
+
+```bash
+vim /tmp/webstore.yaml
+```
+
+Then you can apply it to the cluster.
+
+```bash
+kubectl apply -f /tmp/webstore.yaml
+```
+
+If your end users find they wish to make changes to the resources that aren't
+supported by the operator, they can generate the resources from the custom
+resource.
+
+```bash
+./bin/webstorectl generate --workload-manifest /tmp/webstore.yaml
+```
+
+This will print the resources to stdout. These may be piped into an overlay
+tool or written to disk and modified before applying to a cluster.
+
+That's it! You have a working operator without manually writing a single line
+of code. If you'd like to make any changes to your workload's API, you'll find
+the code in the `apis` directory. The controller's source code is in
+`controllers` directory. And the companion CLI code is in `cmd`.
+
+Don't forget to clean up. Remove the controller, CRD and the workload's
+resources as follows.
+
+```bash
+make undeploy
+```
+
+For more information, checkout the [Operator Builder docs](docs/) as
+well as the [Kubebuilder docs](https://kubebuilder.io/).
+
diff --git a/docs/installation.md b/docs/installation.md
new file mode 100644
index 0000000..0a421ce
--- /dev/null
+++ b/docs/installation.md
@@ -0,0 +1,74 @@
+# Installation
+
+You have the following options to install the operator-builder CLI:
+* [Download the latest binary with your browser](https://github.com/nukleros/operator-builder/releases/latest)
+* [Download with wget](#wget)
+* [Homebrew](#homebrew)
+* [Snap](#snap)
+* [Docker Image](#docker-image)
+* [Go Install](#go-install)
+
+### wget
+Use wget to download the pre-compiled binaries:
+
+```bash
+VERSION=v0.6.0
+OS=Linux
+ARCH=x86_64
+wget https://github.com/nukleros/operator-builder/releases/download/${VERSION}/operator-builder_${VERSION}_${OS}_${ARCH}.gz -O - |\
+ gzip -d && sudo mv operator-builder_${VERSION}_${OS}_${ARCH} /usr/local/bin/operator-builder
+```
+
+### Homebrew
+
+Available for Mac and Linux.
+
+Using [Homebrew](https://brew.sh/)
+
+```bash
+brew tap vmware-tanzu-labs/tap
+brew install operator-builder
+```
+
+### Snap
+
+Available for Linux only.
+
+```bash
+snap install operator-builder
+```
+
+>**NOTE**: `operator-builder` installs with [_strict confinement_](https://docs.snapcraft.io/snap-confinement/6233) in snap, this means it doesn't have direct access to root files.
+
+### Docker Image
+
+```bash
+docker pull ghcr.io/vmawre-tanzu-labs/operator-builder
+```
+
+#### One-shot container use
+
+```bash
+docker run --rm -v "${PWD}":/workdir ghcr.io/vmware-tanzu-labs/operator-builder [flags]
+```
+
+#### Run container commands interactively
+
+```bash
+docker run --rm -it -v "${PWD}":/workdir --entrypoint sh ghcr.io/vmawre-tanzu-labs/operator-builder
+```
+
+It can be useful to have a bash function to avoid typing the whole docker command:
+
+```bash
+operator-builder() {
+ docker run --rm -i -v "${PWD}":/workdir ghcr.io/vmware-tanzu-labs/operator-builder "$@"
+}
+```
+
+### Go Install
+
+```bash
+GO111MODULE=on go get github.com/vmware-tanzu-labs/operator-builder/cmd/operator-builder
+```
+
diff --git a/docs/license.md b/docs/license.md
index 6fb449b..251f280 100644
--- a/docs/license.md
+++ b/docs/license.md
@@ -6,42 +6,46 @@ Manage the creation and update of licensing for your Kubebuilder project.
Create two license files for testing:
- cat > /tmp/project.txt < /tmp/source-header.txt < /tmp/project.txt < /tmp/source-header.txt <