diff --git a/CONTRIBUTING.adoc b/CONTRIBUTING.adoc new file mode 100644 index 0000000..c366392 --- /dev/null +++ b/CONTRIBUTING.adoc @@ -0,0 +1,124 @@ += Contributing +:toc: +:toc-title: +:toc-placement!: +\ifdef::env-github[] +:tip-caption: :bulb: +:note-caption: :information_source: +:important-caption: :heavy_exclamation_mark: +:caution-caption: :fire: +:warning-caption: :warning: +\endif::[] +:image-name: jgriff/k8s-resource + +toc::[] + +== Issues and Pull Requests + +* For *small* changes or quick fixes, a simple https://github.com/jgriff/k8s-resource/pulls[pull request] is sufficient. + +* For *non-trivial* changes or bug reports, please file an https://github.com/jgriff/k8s-resource/issues[issue] _before_ submitting a pull request. + +* For *substantial* changes, or to discuss a feature request, prefix your issue with "RFC:" (Request For Comment) and tag it with the label https://github.com/jgriff/k8s-resource/labels/rfc[`rfc`]. + +== Development Builds + +For local dev builds, the term `dev` is used in place of the link:RELEASES.adoc[release tag] for the final image tag. + +There are `make` targets for each `build` and `test` variant. + +|=== +|Make Target |Description + +|`build_` +|Builds local image tagged as `:dev-kubectl-` and `:dev-kubectl-`. + +|`test_` +|Runs unit tests against image tag `:dev-kubectl-`. + +|`build_latest` +|Builds local image tagged as `:latest`. + +|`test_latest` +|Runs unit tests against image `:latest`. +|=== + +where: + +* `` defaults to `{image-name}` +* `` are the `kubectl` versions we are currently shipping (see the link:Makefile[Makefile]). + +=== Examples + +Build new local `{image-name}:latest`: + +[source,bash] +---- +make build_latest +---- + +Build a single, specific `kubectl` variant (`{image-name}:dev-kubectl-1.22`): + +[source,bash] +---- +make build_1.22 +---- + +Build all `kubectl` variants (`dev-kubectl-`): + +[source,bash] +---- +make build +---- + +Test a single, specific variant: + +[source,bash] +---- +make test_1.22 +---- + +Run unit tests across all `dev` image variants: + +[source,bash] +---- +make test +---- + +Combine targets in single invocation: + +[source,bash] +---- +make build_1.22 test_1.22 +---- + +=== Overriding the Image Name + +Sometimes, you may need to push your dev images to another (private) registry for integration testing or other uses. In those scenarios, you have 2 basic options: + +. Make another tag from source image `{image-name}` after every dev build. ++ +[source,bash,subs="attributes"] +---- +make build_latest +docker tag {image-name}:latest my-registry/k8s-resource:latest +---- +However, this can get hairy for all the `kubectl` version variants and also requires some two-step scripting on your part. +. Override the `Makefile` variable `IMAGE` to set it to your custom image name (without the tag). ++ +[source,bash] +---- +make build_latest IMAGE=my-registry/k8s-resource +---- +This has the added benefit of working for _every_ target. For example, to build _all_ image variants with your custom image registry name: ++ +[source,bash] +---- +make build IMAGE=my-registry/k8s-resource +---- +Works with any target, such as `test`: ++ +[source,bash] +---- +make test IMAGE=my-registry/k8s-resource +---- diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index ef88606..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,51 +0,0 @@ -# Contributing - -## Issues and Pull Requests - -For small changes or quick fixes, a simple [pull request](https://github.com/jgriff/k8s-resource/pulls) is sufficient. - -For non-trivial changes or bug reports, please file an [issue](https://github.com/jgriff/k8s-resource/issues) _before_ submitting a pull request. - -For substantial changes, or to discuss a feature request, prefix your issue with "RFC:" (Request For Comment) and tag it with the label [`rfc`](https://github.com/jgriff/k8s-resource/labels/rfc). - -## Development - -Build local `dev` images of all `kubectl` variants (`dev-kubectl-`): -```shell -make build -``` - -Build a single, specific `kubectl` variant (`dev-kubectl-1.22`): -```shell -make build_1.22 -``` - -Run unit tests across all `dev` image variants: -```shell -make test -``` - -Test a single, specific variant: -```shell -make test_1.22 -``` - -Combine targets in single invocation: -```shell -make build_1.22 test_1.22 -``` - -## Releases - -Image releases to Docker Hub are performed by GitHub Actions whenever a new `v*` tag is created. The leading `v` will be stripped when creating the Docker tag. - -Each release ships a set of image variants for a range of `kubectl` versions following the pattern `-kubectl-`, where `` will be the `major.minor.patch` that we are shipping along with `major.minor` (tag moves with latest patch) - -For example, tagging the repo with `v1.2.3` will build and publish: - -* `1.2.3-kubectl-..` -* `1.2.3-kubectl-.` - -See the [`Makefile`](Makefile) for list of all current `kubectl` versions we are supporting. - -The `latest` tag always represents the latest state of the `master` branch. diff --git a/README.adoc b/README.adoc new file mode 100644 index 0000000..dca705c --- /dev/null +++ b/README.adoc @@ -0,0 +1,356 @@ += k8s-resource +:toc: +:toc-placement!: +\ifdef::env-github[] +:tip-caption: :bulb: +:note-caption: :information_source: +:important-caption: :heavy_exclamation_mark: +:caution-caption: :fire: +:warning-caption: :warning: +\endif::[] + +image::https://img.shields.io/docker/pulls/jgriff/k8s-resource[] + +A Concourse https://resource-types.concourse-ci.org/[resource] for retrieving resources +from a kubernetes cluster, along with a general purpose `put` for running any `kubectl` command. + +toc::[] + +== Source Configuration + +* `url`: _Required_. The kubernetes server URL, e.g. `"https://my-cluster:8443"`. +* `token`: _Required_. Authorization token for the api server. +* `certificate_authority`: _Required_. The certificate authority for the api server. ++ +[source,yaml] +---- + certificate_authority: | + -----BEGIN CERTIFICATE----- + ... + -----END CERTIFICATE----- +---- + +* `insecure_skip_tls_verify`: _Optional_. If `true`, ignores `certificate_authority` and skips the validity check of the kubernetes server's certificate. Default is `false`. ++ +CAUTION: Use with caution. This makes the HTTPS connection insecure! + +* `resource_types`: _Optional_. Comma separated list of resource type(s) to retrieve (defaults to just `pod`). ++ +[source,yaml] +---- + resource_types: deployment,service,pod +---- + +* `namespace`: _Optional_. The namespace to restrict the query to. + +For `check`/`get`, this will default to all namespaces (`--all-namespaces`). + +For `put`, this will default to remaining unset (not specified), but can be overridden with a step param (see [below](#out-execute-a-kubectl-command)). + +* `filter`: _Optional_. Can contain any/all the following criteria: + +** `selector`: Specify a label `--selector` for the query. Can use any valid https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors[label selector expression]. Defaults to empty. ++ +[source,yaml] +---- +source: + filter: + selector: app=my-app,app.kubernetes.io/component in (frontend, backend) +---- ++ +NOTE: Selectors are the only filter that are performed server-side, and can help cull down the response before it passes through the rest of the filters (below). +This can speed up `check` operations when dealing with a potentially large volume of resources. + +** `name`: Matches against the `metadata.name` of the resource. Supports both literal (`my-ns-1`) and regular expressions (`"my-ns-[0-9]*$"`). ++ +[source,yaml] +---- +source: + filter: + name: "my-ns-[0-9]*$" +---- + +** `olderThan`: Time in seconds that the `metadata.creationTimestamp` must be older than (ex: `86400` for 24hrs). ++ +[source,yaml] +---- +source: + filter: + olderThan: 86400 +---- + +** `phases`: List of `status.phase` value(s) the resource must match at least one of. This varies depending on the resource. +For example, a https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase[pod's status] can be one of `Pending`, `Running`, `Succeeded`, `Failed` or `Unknown`. +To retrieve only `Failed` or `Unknown` pods: ++ +[source,yaml] +---- +source: + filter: + phases: + - Failed + - Unknown +---- + +** `jq`: Apply any other custom filter(s) on the JSON returned by `kubectl`. +For example, to retrieve only resources whose image comes from the registry `registry.acme.io`: ++ +[source,yaml] +---- +source: + filter: + jq: + - '.spec.containers[] | .image | startswith("registry.acme.io")' +---- +We can add multiple filters that are (by default) "OR'd" together. For example, to also look for _any_ resource with a container that has restarted more than `10` times: ++ +[source,yaml] +---- +source: + filter: + jq: + - '.spec.containers[] | .image | startswith("registry.acme.io")' + - '.status.containerStatuses[] | .restartCount > 10' +---- ++ +[TIP] +==== +This is advanced usage and requires good knowledge about https://stedolan.github.io/jq/[jq] and the Kubernetes API. Best approach to writing such queries is to experiment directly with `kubectl` and `jq`: + +[source,shell] +---- +kubectl ... get ... -o json | jq +---- +==== ++ +When at least one `jq` filter is present, the following additional options can be configured (optionally): + +*** `jq_operator`: Defaults to `,` - the *basic identity operator* which combines them as "OR". It can be any filter joining operation `jq` understands, including `+` and `-` (see https://stedolan.github.io/jq/manual/#Basicfilters[jq Manual: Basic Filters]). +Building on the example above, if we wanted to constrain the matches to only resources that matched _both_ filters _together_, we can use the `and` operator: ++ +[source,yaml] +---- +source: + filter: + jq: + - '.spec.containers[] | .image | startswith("registry.acme.io")' + - '.status.containerStatuses[] | .restartCount > 10' + jq_operator: 'and' +---- + +*** `jq_transform`: Defaults to empty (_do nothing_) - specifies a final JSON transform of the result(s) matched by the list of `jq` queries. +It can be used to alter the structure of the matched json or even produce a completely new json. +The interactive equivalent to this is: ++ +[source,shell] +---- +kubectl ... get ... -o json | jq "[.[] | select( $MATCH_QUERY ) ] | unique $TRANSFORM_QUERY" +---- ++ +[WARNING] +==== +Use with caution. Whatever the transformation is, it should also include the `metadata: {uid: "...", resourceVersion: "..."}` structure, because this is reported to Concourse as the result of the check. +See link:test/fixtures/stdin-source-filter-jq-transformation.json[here] for an example. + +The _empty result_ `[]` appears to not be considered a new version by Concourse (does not trigger a job) - the transform query can make use of that in a condition where it does not want to produce a new version. +==== +* `sensitive`: _Optional._ If `true`, the resource content will be considered sensitive and not show up in the logs or Concourse UI. Can be overridden as a param to each `get` step. Default is `false`. + +== Behavior + +=== `check`: Check for new k8s resource(s) + +The current list of `resource_types` resources are fetched from the cluster, and filtered against any `filter` criteria configured. +Each matching resource is emitted as a separate version, uniquely identified by its `uid`/`resourceVersion` pair. + +New versions will be triggered by encountering any of: + +* new `uid` not seen before +* new `resourceVersion` for a `uid` (that was previously seen at a different `resourceVersion`) + +NOTE: Due to the way Concourse treats the versions from the first `check`, this resource will emit _only_ a +single initial resource version (or zero if none match). It will be the first resource in the list returned from the query. +All subsequent `check` invocations after that will always emit the full batch of resources as individual versions. +This is done to give pipelines the opportunity to run across each k8s resource. Otherwise, if all versions were emitted +from the first initial `check`, Concourse would only trigger on the last version in the list. + + +=== `in`: Retrieve the k8s resource + +Retrieve the single resource as JSON (`-o json`) and writes it to a file `resource.json`. + +[source,json] +---- +{ + "apiVersion": "v1", + "kind": "...", + "metadata": {...}, + ... +} +---- + +==== Parameters + +* `sensitive`: _Optional._ Overrides the source configuration's value for this particular `get`. + +=== `out`: Execute a `kubectl` command + +General purpose execution of `kubectl` with args provided as a param to `put`. + +==== Parameters + +* `kubectl`: _Required._ The args to pass directly to `kubectl`. ++ +NOTE: The `--server`, `--token`, `--certificate-authority` and `--namespace` will all be implicitly included in +the command based on the `source` configuration. + +* `namespace`: _Optional._ Overrides the source configuration's value for this particular `put` step. + + +== Examples + +=== `get` Resources + +The pipeline below checks for kubernetes `namespaces` named `my-ns-` created more than 24 hours ago. + +[source,yaml] +---- +resource_types: + - name: k8s-resource + type: docker-image + source: + repository: jgriff/k8s-resource + +resources: + - name: expired-namespace + type: k8s-resource + icon: kubernetes + source: + url: ((k8s-server)) + token: ((k8s-token)) + certificate_authority: ((k8s-ca)) + resource_types: namespaces <1> + filter: + name: "my-ns-[0-9]*$" <2> + olderThan: 86400 <3> + +jobs: + - name: view-expired-namespaces + plan: + - get: expired-namespace + version: every + trigger: true + - task: take-a-look + config: + platform: linux + image_resource: + type: registry-image + source: { repository: busybox } + inputs: + - name: expired-namespace + run: + path: cat + args: ["expired-namespace/resource.json"] +---- +<1> are `namespaces`. +<2> are named `my-ns-` (e.g `my-ns-1`, `my-ns-200`, etc). +<3> have existed for longer than 24 hours (`86400` seconds). + +Each k8s resource that matches the above criteria is emitted individually from the `expired-namespace` resource, +and then the `take-a-look` task echoes the contents of the retrieved resource file (for demonstration purposes). + +NOTE: Be sure to include `version: every` in your `get` step so you get _every_ k8s resource that matches your query. +Otherwise, Concourse will only trigger on the _latest_ resource to be emitted (the last one in the list that comes back from the query). + +=== `put` Resources + +The pipeline below demonstrates using the `put` operation to deploy a resource file `deploy.yaml` from a git repo `my-k8s-repo` (config not shown). + +[source,yaml] +---- +resource_types: + - name: k8s-resource + type: docker-image + source: + repository: jgriff/k8s-resource + +resources: + - name: k8s + type: k8s-resource + icon: kubernetes + source: + url: ((k8s-server)) + token: ((k8s-token)) + certificate_authority: ((k8s-ca)) + +jobs: + - name: deploy-prod + plan: + - get: my-k8s-repo + trigger: true + - put: k8s + params: + kubectl: apply -f my-k8s-repo/deploy.yaml + namespace: prod +---- + + + +=== `get` and `put` Resources + +The pipeline below demonstrates using both `get` and `put` in the same pipeline. + +[WARNING] +==== +Don't use the same `k8s-resource` instance for _both_ `get` and `put` operations! The `put` step +emits a meaningless version (it's just the `kubectl` command that was executed). The problem is Concourse will include +that (meaningless) version in the version history for the resource. It will then be offered to your `get` step which +will be unable to retrieve the nonsensical version and then fail. + +So the best way to deal with this is to use one resource instance for the resources you are ``get``'ing, and another +instance for general purpose ``put``'ing things. +==== +Here's an example that combines the previous 2 examples into a single pipeline that watches for expired namespaces, and +then deletes them. + +[source,yaml] +---- +k8s-resource-source-config: &k8s-resource-source-config + url: ((k8s-server)) + token: ((k8s-token)) + certificate_authority: ((k8s-ca)) + +resource_types: + - name: k8s-resource + type: docker-image + source: + repository: jgriff/k8s-resource + +resources: + - name: k8s + type: k8s-resource + icon: kubernetes + source: + << : *k8s-resource-source-config + + - name: expired-namespace + type: k8s-resource + icon: kubernetes + source: + << : *k8s-resource-source-config + resource_types: namespaces + filter: + name: "my-ns-[0-9]*$" + olderThan: 86400 + phases: [Active] + +jobs: + - name: delete-expired-namespaces + plan: + - get: expired-namespace + version: every + trigger: true + - load_var: expired-namespace-resource + file: expired-namespace/resource.json + - put: k8s + params: + kubectl: delete namespace ((.:expired-namespace-resource.metadata.name)) +---- diff --git a/README.md b/README.md deleted file mode 100644 index 6cff46b..0000000 --- a/README.md +++ /dev/null @@ -1,295 +0,0 @@ -# k8s-resource - -![pulls](https://img.shields.io/docker/pulls/jgriff/k8s-resource) - -A Concourse [resource](https://resource-types.concourse-ci.org/) for retrieving resources from a kubernetes cluster, along -with a general purpose `put` for running any `kubectl` command. - -## Source Configuration - -* `url`: _Required_. The kubernetes server URL, e.g. `"https://my-cluster:8443"`. -* `token`: _Required_. Authorization token for the api server. -* `certificate_authority`: _Required_. The certificate authority for the api server. - ```yaml - certificate_authority: | - -----BEGIN CERTIFICATE----- - ... - -----END CERTIFICATE----- - ``` -* `insecure_skip_tls_verify`: _Optional_. If `true`, ignores `certificate_authority` and skips the validity check of the kubernetes server's certificate. Default is `false`. \ - ⚠️ **Warning**: _Use with caution. This makes the HTTPS connection insecure!_ -* `resource_types`: _Optional_. Comma separated list of resource type(s) to retrieve (defaults to just `pod`). - ```yaml - resource_types: deployment,service,pod - ``` -* `namespace`: _Optional_. The namespace to restrict the query to. \ - For `check`/`get`, this will default to all namespaces (`--all-namespaces`). \ - For `put`, this will default to remaining unset (not specified), but can be overridden with a step param (see [below](#out-execute-a-kubectl-command)). -* `filter`: _Optional_. Can contain any/all of the following criteria: - * `selector`: Specify a label `--selector` for the query. Can use any valid [label selector expression](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors). Defaults to empty. - ```yaml - source: - filter: - selector: app=my-app,app.kubernetes.io/component in (frontend, backend) - ``` - **Note:** _Selectors are the only filter that are performed server-side, and can help cull down the response before it passes through the rest of the filters (below). - This can speed up `check` operations when dealing with a potentially large volume of resources._ - * `name`: Matches against the `metadata.name` of the resource. Supports both literal (`my-ns-1`) and regular expressions (`"my-ns-[0-9]*$"`). - ```yaml - source: - filter: - name: "my-ns-[0-9]*$" - ``` - * `olderThan`: Time in seconds that the `metadata.creationTimestamp` must be older than (ex: `86400` for 24hrs). - ```yaml - source: - filter: - olderThan: 86400 - ``` - * `phases`: List of `status.phase` value(s) the resource must match at least one of. This varies depending on the resource. - For example, a [pod's status](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase) can be - one of `Pending`, `Running`, `Succeeded`, `Failed` or `Unknown`. To retrieve only `Failed` or `Unknown` pods: - ```yaml - source: - filter: - phases: - - Failed - - Unknown - ``` - * `jq`: Apply any other custom filter(s) on the JSON returned by `kubectl`. - For example, to retrieve only resources whose image comes from the registry `registry.acme.io`: - ```yaml - source: - filter: - jq: - - '.spec.containers[] | .image | startswith("registry.acme.io")' - ``` - We can add multiple filters that are (by default) "OR'd" together. For example, to also look for _any_ resource with a container that has restarted more than `10` times: - ```yaml - source: - filter: - jq: - - '.spec.containers[] | .image | startswith("registry.acme.io")' - - '.status.containerStatuses[] | .restartCount > 10' - ``` - - :bulb: **Tip**: _This is advanced usage and requires good knowledge about [jq](https://stedolan.github.io/jq/) and the Kubernetes API. Best approach to writing such queries is to experiment directly with `kubectl` and `jq`_: - ```shell - kubectl ... get ... -o json | jq - ``` - When at least one `jq` filter is present, the following additional options can be configured (optionally): - * `jq_operator`: Defaults to `,` - the *basic identity operator* which combines them as "OR". It can be any filter joining operation `jq` understands, including `+` and `-` (see [jq Manual: Basic Filters](https://stedolan.github.io/jq/manual/#Basicfilters)). - Building on the example above, if we wanted to constrain the matches to only resources that matched _both_ filters _together_, we can use the `and` operator: - ```yaml - source: - filter: - jq: - - '.spec.containers[] | .image | startswith("registry.acme.io")' - - '.status.containerStatuses[] | .restartCount > 10' - jq_operator: 'and' - ``` - * `jq_transform`: Defaults to empty (_do nothing_) - specifies a final JSON transform of the result(s) matched by the list of `jq` queries. - It can be used to alter the structure of the matched json or even produce a completely new json. - The interactive equivalent to this is: - ```shell - kubectl ... get ... -o json | jq "[.[] | select( $MATCH_QUERY ) ] | unique $TRANSFORM_QUERY" - ``` - :warning: **Warning**: Use with caution. Whatever the transformation is, it should also include the `metadata: {uid: "...", resourceVersion: "..."}` structure, because this is reported to Concourse as the result of the check. - See [`test/fixtures/stdin-source-filter-jq-transformation.json`](test/fixtures/stdin-source-filter-jq-transformation.json) for an example. - The _empty result_ `[]` appears to not be considered a new version by Concourse (does not trigger a job) - the transform query can make use of that in a condition where it does not want to produce a new version. - -* `sensitive`: _Optional._ If `true`, the resource content will be considered sensitive and not show up in the logs or Concourse UI. Can be overridden as a param to each `get` step. Default is `false`. - -## Behavior - -### `check`: Check for new k8s resource(s) - -The current list of `resource_types` resources are fetched from the cluster, and filtered against any `filter` criteria configured. -Each matching resource is emitted as a separate version, uniquely identified by its `uid`/`resourceVersion` pair. - -New versions will be triggered by encountering any of: - -* new `uid` not seen before -* new `resourceVersion` for a `uid` (that was previously seen at a different `resourceVersion`) - -**NOTE:** Due to the way Concourse treats the versions from the first `check`, this resource will emit _only_ a -single initial resource version (or zero if none match). It will be the first resource in the list returned from the query. -All subsequent `check` invocations after that will always emit the full batch of resources as individual versions. -This is done to give pipelines the opportunity to run across each k8s resource. Otherwise, if all versions were emitted -from the first initial `check`, Concourse would only trigger on the last version in the list. - - -### `in`: Retrieve the k8s resource - -Retrieve the single resource as JSON (`-o json`) and writes it to a file `resource.json`. -```json -{ - "apiVersion": "v1", - "kind": "...", - "metadata": {...}, - ... -} -``` - -#### Parameters - -* `sensitive`: _Optional._ Overrides the source configuration's value for this particular `get`. - -### `out`: Execute a `kubectl` command - -General purpose execution of `kubectl` with args provided as a param to `put`. - -#### Parameters - -* `kubectl`: _Required._ The args to pass directly to `kubectl`. \ - **Note:** The `--server`, `--token`, `--certificate-authority` and `--namespace` will all be implicitly included in - the command based on the `source` configuration. -* `namespace`: _Optional._ Overrides the source configuration's value for this particular `put` step. - - -## Example - -### `get` Resources - -```yaml -resource_types: - - name: k8s-resource - type: docker-image - source: - repository: jgriff/k8s-resource - -resources: - - name: expired-namespace - type: k8s-resource - icon: kubernetes - source: - url: ((k8s-server)) - token: ((k8s-token)) - certificate_authority: ((k8s-ca)) - resource_types: namespaces - filter: - name: "my-ns-[0-9]*$" - olderThan: 86400 - -jobs: - - name: view-expired-namespaces - plan: - - get: expired-namespace - version: every - trigger: true - - task: take-a-look - config: - platform: linux - image_resource: - type: registry-image - source: { repository: busybox } - inputs: - - name: expired-namespace - run: - path: cat - args: ["expired-namespace/resource.json"] -``` - -The pipeline above checks for kubernetes resources that: - -* [x] are `namespaces`. -* [x] are named `my-ns-` (e.g `my-ns-1`, `my-ns-200`, etc). -* [x] have existed for longer than 24 hours (`86400` seconds). - -Each k8s resource that matches the above criteria is emitted individually from the `expired-namespace` resource, -and then the `take-a-look` task echoes the contents of the retrieved resource file (for demonstration purposes). - -**NOTE:** Be sure to include `version: every` in your `get` step so you get _every_ k8s resource that matches your query. -Otherwise, Concourse will only trigger on the _latest_ resource to be emitted (the last one in the list that comes back from the query). - -### `put` Resources - -The pipeline below demonstrates using the `put` operation to deploy a resource file `deploy.yaml` from a git repo `my-k8s-repo` (config not shown). - -```yaml -resource_types: - - name: k8s-resource - type: docker-image - source: - repository: jgriff/k8s-resource - -resources: - - name: k8s - type: k8s-resource - icon: kubernetes - source: - url: ((k8s-server)) - token: ((k8s-token)) - certificate_authority: ((k8s-ca)) - -jobs: - - name: deploy-prod - plan: - - get: my-k8s-repo - trigger: true - - put: k8s - params: - kubectl: apply -f my-k8s-repo/deploy.yaml - namespace: prod -``` - - - -### `get` and `put` Resources - -The pipeline below demonstrates using both `get` and `put` in the same pipeline. - -⚠️ **Warning:** Don't use the same `k8s-resource` instance for **both** `get` and `put` operations! The `put` step -emits a meaningless version (it's just the `kubectl` command that was executed). The problem is Concourse will include -that (meaningless) version in the version history for the resource. It will then be offered to your `get` step which -will be unable to retrieve the nonsensical version and then fail. - -So the best way to deal with this is to use one resource instance for the resources you are `get`'ing, and another -instance for general purpose `put`'ing things. - -Here's an example that combines the previous 2 examples into a single pipeline that watches for expired namespaces, and -then deletes them. - -```yaml ---- -k8s-resource-source-config: &k8s-resource-source-config - url: ((k8s-server)) - token: ((k8s-token)) - certificate_authority: ((k8s-ca)) - -resource_types: - - name: k8s-resource - type: docker-image - source: - repository: jgriff/k8s-resource - -resources: - - name: k8s - type: k8s-resource - icon: kubernetes - source: - << : *k8s-resource-source-config - - - name: expired-namespace - type: k8s-resource - icon: kubernetes - source: - << : *k8s-resource-source-config - resource_types: namespaces - filter: - name: "my-ns-[0-9]*$" - olderThan: 86400 - phases: [Active] - -jobs: - - name: delete-expired-namespaces - plan: - - get: expired-namespace - version: every - trigger: true - - load_var: expired-namespace-resource - file: expired-namespace/resource.json - - put: k8s - params: - kubectl: delete namespace ((.:expired-namespace-resource.metadata.name)) -``` diff --git a/RELEASES.adoc b/RELEASES.adoc new file mode 100644 index 0000000..c72c927 --- /dev/null +++ b/RELEASES.adoc @@ -0,0 +1,37 @@ += Releases +\ifdef::env-github[] +:tip-caption: :bulb: +:note-caption: :information_source: +:important-caption: :heavy_exclamation_mark: +:caution-caption: :fire: +:warning-caption: :warning: +\endif::[] + +Images are built by our https://github.com/jgriff/k8s-resource/actions[GitHub Actions] +and released to https://hub.docker.com/r/jgriff/k8s-resource/tags[Docker Hub] using the +conventions below. + +== `latest` + +The `latest` image tag always represents the latest state of our `master` branch, shipping with the latest `kubectl` version. + +It is built and pushed to Docker Hub by our GitHub Action link:.github/workflows/latest.yml[`latest.yml`] whenever `master` is updated. + + +== Git Release Tags + +All versioned releases are performed by our GitHub Action link:.github/workflows/release.yml[`release.yml`] whenever a new `v*` tag is created. + +NOTE: The leading `v` will be stripped when creating the Docker tag. + + +Each release ships a set of image variants for a range of `kubectl` versions following the pattern `-kubectl-`, where `` is the `major.minor.patch` that we are shipping along with its `major.minor` "moving" tag (moves with the latest patch version). + +For example, tagging the repo with `v1.2.3` will build and publish the following Docker images: + +* `1.2.3-kubectl-..` +* `1.2.3-kubectl-.` + +for every `..` version of `kubectl` we are shipping with. + +The versions of `kubectl` we are currently shipping are listed in the link:Makefile[`Makefile`].