mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-13 10:00:56 +00:00
Merge branch 'master' into add-skip-validation-flag-to-edit-add-resource
This commit is contained in:
2
.github/workflows/apidiff.yml
vendored
2
.github/workflows/apidiff.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
compare-imports: true
|
||||
print-compatible: true
|
||||
- name: Report failure
|
||||
uses: nashmaniac/create-issue-action@v1.1
|
||||
uses: nashmaniac/create-issue-action@v1.2
|
||||
# Only report failures of pushes (PRs have are visible through the Checks section) to the default branch
|
||||
if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
with:
|
||||
|
||||
128
CONTRIBUTING.md
128
CONTRIBUTING.md
@@ -59,6 +59,113 @@ Kustomize follows the [Kubernetes Community Membership] contributor ladder. Role
|
||||
|
||||
The kyaml module within the Kustomize repo has additional owners following the same ladder.
|
||||
|
||||
For the kustomize project, we have defined some specific guidelines on each step of the ladder:
|
||||
|
||||
To reach reviewer status, you must:
|
||||
- Have been actively involved in kustomize for 3+ months
|
||||
- Review at least 8 PRs that have been driven through to completion (see the reviewer guide below)
|
||||
- Author at least 5 PRs that have been approved and merged
|
||||
- Be a member of the kubernetes-sigs org. This should not be a blocker though, as once you meet the requirements for reviewer here,
|
||||
the existing kustomize maintainers will be happy to sponsor your request to join the kubernetes-sigs org.
|
||||
- Once you have met the above requirements, you may submit a PR adding yourself to the kustomize reviewers list, with links to your
|
||||
contributions in the description.
|
||||
|
||||
To reach approver status, you must:
|
||||
- Meet all the requirements of a reviewer
|
||||
- Have been actively involved in kustomize for 6+ months
|
||||
- Review at least 15 PRs that have been driven through to completion (see the reviewer guide below)
|
||||
- Authored PRs meeting *either* of the following requirements:
|
||||
- 15 PRs that have been approved and merged
|
||||
- *OR* 10 PRs that have been approved and merged where some were more difficult, required greater thought/design,
|
||||
or built up to larger features/long-term goals.
|
||||
- File 3 issues. This can be any number of things, including but not limited to:
|
||||
- Bugs with kustomize usage that you've found
|
||||
- CI or release improvements
|
||||
- Creating subtasks of a larger feature or project that you are in charge of.
|
||||
- Long term improvements for the health of the project
|
||||
- Triage at least 10 untriaged issues, including at least 1 feature request. The kustomize bug scrub is a great place to get practice with doing this, but you can
|
||||
also follow the triage guide below to get started on your own.
|
||||
- Demonstrate deeper understanding of kustomize goals. This can take many forms and is a bit subjective, but here are a few examples:
|
||||
- saying no to an eschewed feature, instead recommending an alternative solution that is more aligned with the declarative configuration model
|
||||
- active participation in discussion on a feature request issue
|
||||
- filing an issue describing a long term problem and solution aligned with kustomize goals, for example: https://github.com/kubernetes-sigs/kustomize/issues/5140
|
||||
- writing up KEPs for features that will improve the kustomize workflow while being aligned with kustomize goals, for example: https://github.com/kubernetes-sigs/kustomize/pull/4558
|
||||
- Regularly interact with the existing kustomize maintainers, with clear communication about what you are working on or planning to work on. The kustomize
|
||||
maintainers should know who you are and be familiar with your contributions.
|
||||
- If you meet *most* of the above requirements while going above and beyond in a few areas, we will still consider your request to become an approver even
|
||||
if you are missing one or two of the requirements. Please contact the maintainers directly to ask about getting approver status if you fall into this category.
|
||||
- Otherwise, once you meet all the above requirements, you may:
|
||||
- request to be added to the kustomize maintainer meeting that occurs each week with the kustomize PMs.
|
||||
- submit a PR adding yourself to the kustomize approvers list, with links to your contributions in the description.
|
||||
|
||||
To reach owner status, you must:
|
||||
- Meet all the requirements of an approver
|
||||
- Have been actively involved with kustomize for 1+ year
|
||||
- Assisted the current owner in driving the roadmap. This can be explicit or implicit help, such as:
|
||||
- Editing the roadmap directly
|
||||
- Reviewing the roadmap
|
||||
- Providing suggestions for issues or prioritization in meetings that indirectly influence the roadmap
|
||||
- Regularly triage issues and attend the kustomize bug scrub
|
||||
- Regularly review PRs (1-2 a week)
|
||||
- Periodically lead the kustomize bug scrub
|
||||
- Periodically release kustomize (ensuring that there are no release blockers and that release notes are clean)
|
||||
- Be the primary owner or point of contact for a particular project or area of code
|
||||
- Ideally, there should be 2-3 owners at a time. Reach out to the current owners if you are interested in ownership. These
|
||||
requirements are not strict and evaluation is somewhat subjective.
|
||||
|
||||
## Reviewer guide
|
||||
Please watch this talk on how to review code from Tim Hockin: https://www.youtube.com/watch?v=OZVv7-o8i40
|
||||
|
||||
For reviewing PRs in kustomize, we have some specific guidelines:
|
||||
- If the PR is introducing a new feature:
|
||||
- *It must be implementing an issue that has already been triage/accepted or
|
||||
a KEP that has been approved.* If it is not, then request the PR author to first file an issue.
|
||||
- The PR must include thorough tests for the new feature, including unit and integration tests
|
||||
- The code must be clean and readable, with thought given to how we will maintain the code in the future
|
||||
- If the feature requires being broken up into multiple PRs to ease review, the feature should not be exposed to users
|
||||
until the feature is completed in the last PR. For example, while we were building `kustomize localize`, we
|
||||
built the feature almost entirely under the `api` module as a library with all the needed tests. There was no way
|
||||
for users to invoke the localize code until the last PR that actually exposed the `kustomize localize` command in the
|
||||
kustomize binary. This allowed us to continue development of `kustomize localize` without blocking kustomize releases.
|
||||
If this type of development is not possible, then new features requiring multiple PRs should be
|
||||
developed in their own feature branch.
|
||||
- If the PR is introducing a bug fix:
|
||||
- If the PR is not fixing an issue that has already been triage/accepted, follow the triage guide below on bug
|
||||
fixes to decide if this is a PR we want to accept.
|
||||
- The PR should have two distinct commits:
|
||||
- The first commit should add a test demonstrating incorrect behavior
|
||||
- The second commit should include the bug fix
|
||||
- Some sample PRs:
|
||||
- https://github.com/kubernetes-sigs/kustomize/pull/5263/commits
|
||||
- https://github.com/kubernetes-sigs/kustomize/pull/3931/commits
|
||||
- The regression test is absolutely required, and we cannot accept bug fixes without tests.
|
||||
- If the PR is introducing a performance improvement:
|
||||
- The PR description should give an indication of how much the performance is being improved and how we
|
||||
can measure it - benchmark tests are fantastic.
|
||||
- Other PRs (documentation, CI improvements, etc.) should be reviewed based on your best judgment.
|
||||
|
||||
## Triage guide
|
||||
The possible triage labels are listed here: https://github.com/kubernetes-sigs/kustomize/labels?q=triage.
|
||||
|
||||
Triaging a feature request means:
|
||||
- Understand what the user is asking for, and their use case.
|
||||
- Verify that it is not an [eschewed feature](https://kubectl.docs.kubernetes.io/faq/kustomize/eschewedfeatures/#build-time-side-effects-from-cli-args-or-env-variables)
|
||||
- Verify that it is not a duplicate issue.
|
||||
- Look into workarounds. Is there another way that the user can achieve their use case with existing features?
|
||||
- If you are new to this role, prior to leaving a comment on the issue, please bring it to weekly standup
|
||||
for group discussion to make sure that we are all on the same page.
|
||||
- Once you feel ready, you can label it with a triage label. Here's an [example](https://github.com/kubernetes-sigs/kustomize/issues/5049). You can also
|
||||
look at other feature request issues to see how they were triaged and resolved. There are a few different triage labels that you can use, you can see the
|
||||
full list [here](https://github.com/kubernetes-sigs/kustomize/labels?q=triage).
|
||||
|
||||
Triaging a bug means:
|
||||
- First, verify that you can reproduce the issue. If you cannot reproduce the issue or need more information to give
|
||||
it a go, triage it accordingly.
|
||||
- Try to understand if this is really a bug or if this is intended behavior from kustomize. If it seems like intended
|
||||
behavior, do your best to explain to the user why this is the case.
|
||||
- If it seems to be a genuine bug, you can /triage accept the issue. In addition, investigate if there are workarounds or
|
||||
alternative solutions for the user that they can try until the issue gets resolved.
|
||||
|
||||
Administrative notes:
|
||||
|
||||
- The [OWNERS file spec] is a useful resources in making changes.
|
||||
@@ -66,23 +173,16 @@ Administrative notes:
|
||||
|
||||
## Project/Product Managers
|
||||
|
||||
Kustomize will have opportunities to join in a project/product manager role. You can
|
||||
typically start working on this role as part of a kustomize training cohort, so please
|
||||
keep an eye out for that or reach out to the leads if you are interested in this type of
|
||||
work. Expectations for this role are:
|
||||
Kustomize will have opportunities to join in a project/product manager role. You can reach out to
|
||||
the existing kustomize maintainers if you are interested in this type of role. Project management work
|
||||
can greatly help supplement your contributions as you climb from reviewer to approver
|
||||
to owner.
|
||||
|
||||
Expectations for this role are:
|
||||
|
||||
- Triage 1 feature request each week, and bring it to weekly stand-up for discussion. Feature
|
||||
requests are issues labeled kind/feature, and you can find them [here](https://github.com/kubernetes-sigs/kustomize/issues?q=is%3Aissue+is%3Aopen+kind+feature+label%3Akind%2Ffeature).
|
||||
Triaging a feature request means:
|
||||
- Understand what the user is asking for, and their use case.
|
||||
- Verify that it is not an [eschewed feature](https://kubectl.docs.kubernetes.io/faq/kustomize/eschewedfeatures/#build-time-side-effects-from-cli-args-or-env-variables)
|
||||
- Verify that it is not a duplicate issue.
|
||||
- Look into workarounds. Is there another way that the user can achieve their use case with existing features?
|
||||
- If you are new to this role, prior to leaving a comment on the issue, please bring it to weekly standup
|
||||
for group discussion to make sure that we are all on the same page.
|
||||
- Once you feel ready, you can label it with a triage label. Here's an [example](https://github.com/kubernetes-sigs/kustomize/issues/5049). You can also
|
||||
look at other feature request issues to see how they were triaged and resolved. There are a few different triage labels that you can use, you can see the
|
||||
full list [here](https://github.com/kubernetes-sigs/kustomize/labels?q=triage).
|
||||
Please view the above triage guide for details on how to approach feature request triage.
|
||||
- Monitor the kustomize Slack channel and try to help users if you can. It is a pretty
|
||||
active channel, so responding to 4-5 users per week is sufficient even if some
|
||||
questions go unanswered. If there is an interesting topic or a recurring problem that many
|
||||
|
||||
@@ -8,6 +8,7 @@ aliases:
|
||||
- knverey
|
||||
- natasha41575
|
||||
- annasong20
|
||||
- koba1t
|
||||
kustomize-reviewers:
|
||||
- knverey
|
||||
- natasha41575
|
||||
|
||||
84
README.md
84
README.md
@@ -36,11 +36,16 @@ be updated on a regular basis going forward, and such updates
|
||||
will be reflected in the Kubernetes release notes.
|
||||
|
||||
| Kubectl version | Kustomize version |
|
||||
| --- | --- |
|
||||
| < v1.14 | n/a |
|
||||
| v1.14-v1.20 | v2.0.3 |
|
||||
| v1.21 | v4.0.5 |
|
||||
| v1.22 | v4.2.0 |
|
||||
| --------------- | ----------------- |
|
||||
| < v1.14 | n/a |
|
||||
| v1.14-v1.20 | v2.0.3 |
|
||||
| v1.21 | v4.0.5 |
|
||||
| v1.22 | v4.2.0 |
|
||||
| v1.23 | v4.4.1 |
|
||||
| v1.24 | v4.5.4 |
|
||||
| v1.25 | v4.5.7 |
|
||||
| v1.26 | v4.5.7 |
|
||||
| v1.27 | v5.0.1 |
|
||||
|
||||
[v2.0.3]: https://github.com/kubernetes-sigs/kustomize/releases/tag/v2.0.3
|
||||
[#2506]: https://github.com/kubernetes-sigs/kustomize/issues/2506
|
||||
@@ -63,7 +68,37 @@ This file should declare those resources, and any
|
||||
customization to apply to them, e.g. _add a common
|
||||
label_.
|
||||
|
||||
![base image][imageBase]
|
||||
```
|
||||
|
||||
base: kustomization + resources
|
||||
|
||||
kustomization.yaml deployment.yaml service.yaml
|
||||
+---------------------------------------------+ +-------------------------------------------------------+ +-----------------------------------+
|
||||
| apiVersion: kustomize.config.k8s.io/v1beta1 | | apiVersion: apps/v1 | | apiVersion: v1 |
|
||||
| kind: Kustomization | | kind: Deployment | | kind: Service |
|
||||
|.commonLabels: | | metadata: | | metadata: |
|
||||
| app: myapp | | name: myapp | | name: myapp |
|
||||
| resources: | | spec: | | spec: |
|
||||
| - deployment.yaml | | selector: | | selector: |
|
||||
| - service.yaml | | matchLabels: | | app: myapp |
|
||||
| configMapGenerator: | | app: myapp | | ports: |
|
||||
| - name: myapp-map | | template: | | - port: 6060 |
|
||||
| literals: | | metadata: | | targetPort: 6060 |
|
||||
| - KEY=value | | labels: | +-----------------------------------+
|
||||
+---------------------------------------------+ | app: myapp |
|
||||
| spec: |
|
||||
| containers: |
|
||||
| - name: myapp |
|
||||
| image: myapp |
|
||||
| resources: |
|
||||
| limits: |
|
||||
| memory: "128Mi" |
|
||||
| cpu: "500m" |
|
||||
| ports: |
|
||||
| - containerPort: 6060 |
|
||||
+-------------------------------------------------------+
|
||||
|
||||
```
|
||||
|
||||
File structure:
|
||||
|
||||
@@ -99,20 +134,41 @@ Manage traditional [variants] of a configuration - like
|
||||
_development_, _staging_ and _production_ - using
|
||||
[overlays] that modify a common [base].
|
||||
|
||||
![overlay image][imageOverlay]
|
||||
```
|
||||
|
||||
overlay: kustomization + patches
|
||||
|
||||
kustomization.yaml replica_count.yaml cpu_count.yaml
|
||||
+-----------------------------------------------+ +-------------------------------+ +------------------------------------------+
|
||||
| apiVersion: kustomize.config.k8s.io/v1beta1 | | apiVersion: apps/v1 | | apiVersion: apps/v1 |
|
||||
| kind: Kustomization | | kind: Deployment | | kind: Deployment |
|
||||
| commonLabels: | | metadata: | | metadata: |
|
||||
| variant: prod | | name: myapp | | name: myapp |
|
||||
| resources: | | spec: | | spec: |
|
||||
| - ../../base | | replicas: 80 | | template: |
|
||||
| patches: | +-------------------------------+ | spec: |
|
||||
| - path: replica_count.yaml | | containers: |
|
||||
| - path: cpu_count.yaml | | - name: myapp |
|
||||
+-----------------------------------------------+ | resources: |
|
||||
| limits: |
|
||||
| memory: "128Mi" |
|
||||
| cpu: "7000m" |
|
||||
+------------------------------------------+
|
||||
```
|
||||
|
||||
|
||||
File structure:
|
||||
> ```
|
||||
> ~/someApp
|
||||
> ├── base
|
||||
> │ ├── deployment.yaml
|
||||
> │ ├── kustomization.yaml
|
||||
> │ └── service.yaml
|
||||
> │ ├── deployment.yaml
|
||||
> │ ├── kustomization.yaml
|
||||
> │ └── service.yaml
|
||||
> └── overlays
|
||||
> ├── development
|
||||
> │ ├── cpu_count.yaml
|
||||
> │ ├── kustomization.yaml
|
||||
> │ └── replica_count.yaml
|
||||
> │ ├── cpu_count.yaml
|
||||
> │ ├── kustomization.yaml
|
||||
> │ └── replica_count.yaml
|
||||
> └── production
|
||||
> ├── cpu_count.yaml
|
||||
> ├── kustomization.yaml
|
||||
@@ -166,8 +222,6 @@ is governed by the [Kubernetes Code of Conduct].
|
||||
[applied]: https://kubectl.docs.kubernetes.io/references/kustomize/glossary/#apply
|
||||
[base]: https://kubectl.docs.kubernetes.io/references/kustomize/glossary/#base
|
||||
[declarative configuration]: https://kubectl.docs.kubernetes.io/references/kustomize/glossary/#declarative-application-management
|
||||
[imageBase]: images/base.jpg
|
||||
[imageOverlay]: images/overlay.jpg
|
||||
[kubectl announcement]: https://kubernetes.io/blog/2019/03/25/kubernetes-1-14-release-announcement
|
||||
[kubernetes documentation]: https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/
|
||||
[kubernetes style]: https://kubectl.docs.kubernetes.io/references/kustomize/glossary/#kubernetes-style-object
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
. "sigs.k8s.io/kustomize/api/internal/accumulator"
|
||||
"sigs.k8s.io/kustomize/api/internal/loader"
|
||||
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
. "sigs.k8s.io/kustomize/api/internal/generators"
|
||||
"sigs.k8s.io/kustomize/api/kv"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/pkg/loader"
|
||||
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
. "sigs.k8s.io/kustomize/api/internal/generators"
|
||||
"sigs.k8s.io/kustomize/api/kv"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/pkg/loader"
|
||||
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
|
||||
@@ -25,7 +25,7 @@ func IsRemoteFile(path string) bool {
|
||||
return err == nil && (u.Scheme == "http" || u.Scheme == "https")
|
||||
}
|
||||
|
||||
// fileLoader is a kustomization's interface to files.
|
||||
// FileLoader is a kustomization's interface to files.
|
||||
//
|
||||
// The directory in which a kustomization file sits
|
||||
// is referred to below as the kustomization's _root_.
|
||||
@@ -38,49 +38,48 @@ func IsRemoteFile(path string) bool {
|
||||
//
|
||||
// * supplemental data paths
|
||||
//
|
||||
// `Load` is used to visit these paths.
|
||||
// `Load` is used to visit these paths.
|
||||
//
|
||||
// These paths refer to resources, patches,
|
||||
// data for ConfigMaps and Secrets, etc.
|
||||
// These paths refer to resources, patches,
|
||||
// data for ConfigMaps and Secrets, etc.
|
||||
//
|
||||
// The loadRestrictor may disallow certain paths
|
||||
// or classes of paths.
|
||||
// The loadRestrictor may disallow certain paths
|
||||
// or classes of paths.
|
||||
//
|
||||
// * bases (other kustomizations)
|
||||
//
|
||||
// `New` is used to load bases.
|
||||
// `New` is used to load bases.
|
||||
//
|
||||
// A base can be either a remote git repo URL, or
|
||||
// a directory specified relative to the current
|
||||
// root. In the former case, the repo is locally
|
||||
// cloned, and the new loader is rooted on a path
|
||||
// in that clone.
|
||||
// A base can be either a remote git repo URL, or
|
||||
// a directory specified relative to the current
|
||||
// root. In the former case, the repo is locally
|
||||
// cloned, and the new loader is rooted on a path
|
||||
// in that clone.
|
||||
//
|
||||
// As loaders create new loaders, a root history
|
||||
// is established, and used to disallow:
|
||||
// As loaders create new loaders, a root history
|
||||
// is established, and used to disallow:
|
||||
//
|
||||
// - A base that is a repository that, in turn,
|
||||
// specifies a base repository seen previously
|
||||
// in the loading stack (a cycle).
|
||||
// - A base that is a repository that, in turn,
|
||||
// specifies a base repository seen previously
|
||||
// in the loading stack (a cycle).
|
||||
//
|
||||
// - An overlay depending on a base positioned at
|
||||
// or above it. I.e. '../foo' is OK, but '.',
|
||||
// '..', '../..', etc. are disallowed. Allowing
|
||||
// such a base has no advantages and encourages
|
||||
// cycles, particularly if some future change
|
||||
// were to introduce globbing to file
|
||||
// specifications in the kustomization file.
|
||||
// - An overlay depending on a base positioned at
|
||||
// or above it. I.e. '../foo' is OK, but '.',
|
||||
// '..', '../..', etc. are disallowed. Allowing
|
||||
// such a base has no advantages and encourages
|
||||
// cycles, particularly if some future change
|
||||
// were to introduce globbing to file
|
||||
// specifications in the kustomization file.
|
||||
//
|
||||
// These restrictions assure that kustomizations
|
||||
// are self-contained and relocatable, and impose
|
||||
// some safety when relying on remote kustomizations,
|
||||
// e.g. a remotely loaded ConfigMap generator specified
|
||||
// to read from /etc/passwd will fail.
|
||||
//
|
||||
type fileLoader struct {
|
||||
type FileLoader struct {
|
||||
// Loader that spawned this loader.
|
||||
// Used to avoid cycles.
|
||||
referrer *fileLoader
|
||||
referrer *FileLoader
|
||||
|
||||
// An absolute, cleaned path to a directory.
|
||||
// The Load function will read non-absolute
|
||||
@@ -107,23 +106,9 @@ type fileLoader struct {
|
||||
cleaner func() error
|
||||
}
|
||||
|
||||
// NewFileLoaderAtCwd returns a loader that loads from PWD.
|
||||
// A convenience for kustomize edit commands.
|
||||
func NewFileLoaderAtCwd(fSys filesys.FileSystem) *fileLoader {
|
||||
return newLoaderOrDie(
|
||||
RestrictionRootOnly, fSys, filesys.SelfDir)
|
||||
}
|
||||
|
||||
// NewFileLoaderAtRoot returns a loader that loads from "/".
|
||||
// A convenience for tests.
|
||||
func NewFileLoaderAtRoot(fSys filesys.FileSystem) *fileLoader {
|
||||
return newLoaderOrDie(
|
||||
RestrictionRootOnly, fSys, filesys.Separator)
|
||||
}
|
||||
|
||||
// Repo returns the absolute path to the repo that contains Root if this fileLoader was created from a url
|
||||
// or the empty string otherwise.
|
||||
func (fl *fileLoader) Repo() string {
|
||||
func (fl *FileLoader) Repo() string {
|
||||
if fl.repoSpec != nil {
|
||||
return fl.repoSpec.Dir.String()
|
||||
}
|
||||
@@ -132,13 +117,13 @@ func (fl *fileLoader) Repo() string {
|
||||
|
||||
// Root returns the absolute path that is prepended to any
|
||||
// relative paths used in Load.
|
||||
func (fl *fileLoader) Root() string {
|
||||
func (fl *FileLoader) Root() string {
|
||||
return fl.root.String()
|
||||
}
|
||||
|
||||
func newLoaderOrDie(
|
||||
func NewLoaderOrDie(
|
||||
lr LoadRestrictorFunc,
|
||||
fSys filesys.FileSystem, path string) *fileLoader {
|
||||
fSys filesys.FileSystem, path string) *FileLoader {
|
||||
root, err := filesys.ConfirmDir(fSys, path)
|
||||
if err != nil {
|
||||
log.Fatalf("unable to make loader at '%s'; %v", path, err)
|
||||
@@ -147,12 +132,12 @@ func newLoaderOrDie(
|
||||
lr, root, fSys, nil, git.ClonerUsingGitExec)
|
||||
}
|
||||
|
||||
// newLoaderAtConfirmedDir returns a new fileLoader with given root.
|
||||
// newLoaderAtConfirmedDir returns a new FileLoader with given root.
|
||||
func newLoaderAtConfirmedDir(
|
||||
lr LoadRestrictorFunc,
|
||||
root filesys.ConfirmedDir, fSys filesys.FileSystem,
|
||||
referrer *fileLoader, cloner git.Cloner) *fileLoader {
|
||||
return &fileLoader{
|
||||
referrer *FileLoader, cloner git.Cloner) *FileLoader {
|
||||
return &FileLoader{
|
||||
loadRestrictor: lr,
|
||||
root: root,
|
||||
referrer: referrer,
|
||||
@@ -164,7 +149,7 @@ func newLoaderAtConfirmedDir(
|
||||
|
||||
// New returns a new Loader, rooted relative to current loader,
|
||||
// or rooted in a temp directory holding a git repo clone.
|
||||
func (fl *fileLoader) New(path string) (ifc.Loader, error) {
|
||||
func (fl *FileLoader) New(path string) (ifc.Loader, error) {
|
||||
if path == "" {
|
||||
return nil, errors.Errorf("new root cannot be empty")
|
||||
}
|
||||
@@ -200,7 +185,7 @@ func (fl *fileLoader) New(path string) (ifc.Loader, error) {
|
||||
// directory holding a cloned git repo.
|
||||
func newLoaderAtGitClone(
|
||||
repoSpec *git.RepoSpec, fSys filesys.FileSystem,
|
||||
referrer *fileLoader, cloner git.Cloner) (ifc.Loader, error) {
|
||||
referrer *FileLoader, cloner git.Cloner) (ifc.Loader, error) {
|
||||
cleaner := repoSpec.Cleaner(fSys)
|
||||
err := cloner(repoSpec)
|
||||
if err != nil {
|
||||
@@ -229,7 +214,7 @@ func newLoaderAtGitClone(
|
||||
return nil, fmt.Errorf("%q refers to directory outside of repo %q", repoSpec.AbsPath(),
|
||||
repoSpec.CloneDir())
|
||||
}
|
||||
return &fileLoader{
|
||||
return &FileLoader{
|
||||
// Clones never allowed to escape root.
|
||||
loadRestrictor: RestrictionRootOnly,
|
||||
root: root,
|
||||
@@ -241,7 +226,7 @@ func newLoaderAtGitClone(
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (fl *fileLoader) errIfGitContainmentViolation(
|
||||
func (fl *FileLoader) errIfGitContainmentViolation(
|
||||
base filesys.ConfirmedDir) error {
|
||||
containingRepo := fl.containingRepo()
|
||||
if containingRepo == nil {
|
||||
@@ -259,7 +244,7 @@ func (fl *fileLoader) errIfGitContainmentViolation(
|
||||
|
||||
// Looks back through referrers for a git repo, returning nil
|
||||
// if none found.
|
||||
func (fl *fileLoader) containingRepo() *git.RepoSpec {
|
||||
func (fl *FileLoader) containingRepo() *git.RepoSpec {
|
||||
if fl.repoSpec != nil {
|
||||
return fl.repoSpec
|
||||
}
|
||||
@@ -271,7 +256,7 @@ func (fl *fileLoader) containingRepo() *git.RepoSpec {
|
||||
|
||||
// errIfArgEqualOrHigher tests whether the argument,
|
||||
// is equal to or above the root of any ancestor.
|
||||
func (fl *fileLoader) errIfArgEqualOrHigher(
|
||||
func (fl *FileLoader) errIfArgEqualOrHigher(
|
||||
candidateRoot filesys.ConfirmedDir) error {
|
||||
if fl.root.HasPrefix(candidateRoot) {
|
||||
return fmt.Errorf(
|
||||
@@ -288,7 +273,7 @@ func (fl *fileLoader) errIfArgEqualOrHigher(
|
||||
// I.e. Allow a distinction between git URI with
|
||||
// path foo and tag bar and a git URI with the same
|
||||
// path but a different tag?
|
||||
func (fl *fileLoader) errIfRepoCycle(newRepoSpec *git.RepoSpec) error {
|
||||
func (fl *FileLoader) errIfRepoCycle(newRepoSpec *git.RepoSpec) error {
|
||||
// TODO(monopole): Use parsed data instead of Raw().
|
||||
if fl.repoSpec != nil &&
|
||||
strings.HasPrefix(fl.repoSpec.Raw(), newRepoSpec.Raw()) {
|
||||
@@ -305,7 +290,7 @@ func (fl *fileLoader) errIfRepoCycle(newRepoSpec *git.RepoSpec) error {
|
||||
// Load returns the content of file at the given path,
|
||||
// else an error. Relative paths are taken relative
|
||||
// to the root.
|
||||
func (fl *fileLoader) Load(path string) ([]byte, error) {
|
||||
func (fl *FileLoader) Load(path string) ([]byte, error) {
|
||||
if IsRemoteFile(path) {
|
||||
return fl.httpClientGetContent(path)
|
||||
}
|
||||
@@ -319,7 +304,7 @@ func (fl *fileLoader) Load(path string) ([]byte, error) {
|
||||
return fl.fSys.ReadFile(path)
|
||||
}
|
||||
|
||||
func (fl *fileLoader) httpClientGetContent(path string) ([]byte, error) {
|
||||
func (fl *FileLoader) httpClientGetContent(path string) ([]byte, error) {
|
||||
var hc *http.Client
|
||||
if fl.http != nil {
|
||||
hc = fl.http
|
||||
@@ -344,6 +329,6 @@ func (fl *fileLoader) httpClientGetContent(path string) ([]byte, error) {
|
||||
}
|
||||
|
||||
// Cleanup runs the cleaner.
|
||||
func (fl *fileLoader) Cleanup() error {
|
||||
func (fl *FileLoader) Cleanup() error {
|
||||
return fl.cleaner()
|
||||
}
|
||||
@@ -93,8 +93,9 @@ func MakeFakeFs(td []testData) filesys.FileSystem {
|
||||
return fSys
|
||||
}
|
||||
|
||||
func makeLoader() *fileLoader {
|
||||
return NewFileLoaderAtRoot(MakeFakeFs(testCases))
|
||||
func makeLoader() *FileLoader {
|
||||
return NewLoaderOrDie(
|
||||
RestrictionRootOnly, MakeFakeFs(testCases), filesys.Separator)
|
||||
}
|
||||
|
||||
func TestLoaderLoad(t *testing.T) {
|
||||
@@ -226,7 +227,7 @@ func TestLoaderLocalScheme(t *testing.T) {
|
||||
dir.Join(filepath.Join(parts...)),
|
||||
[]byte(content),
|
||||
))
|
||||
actualContent, err := newLoaderOrDie(RestrictionRootOnly,
|
||||
actualContent, err := NewLoaderOrDie(RestrictionRootOnly,
|
||||
fSys,
|
||||
dir.String(),
|
||||
).Load(strings.Join(parts, "//"))
|
||||
@@ -240,7 +241,7 @@ func TestLoaderLocalScheme(t *testing.T) {
|
||||
"root",
|
||||
}
|
||||
require.NoError(t, fSys.MkdirAll(dir.Join(filepath.Join(parts...))))
|
||||
ldr, err := newLoaderOrDie(RestrictionRootOnly,
|
||||
ldr, err := NewLoaderOrDie(RestrictionRootOnly,
|
||||
fSys,
|
||||
dir.String(),
|
||||
).New(strings.Join(parts, "//"))
|
||||
@@ -322,7 +323,7 @@ func TestRestrictionRootOnlyInRealLoader(t *testing.T) {
|
||||
|
||||
var l ifc.Loader
|
||||
|
||||
l = newLoaderOrDie(RestrictionRootOnly, fSys, dir)
|
||||
l = NewLoaderOrDie(RestrictionRootOnly, fSys, dir)
|
||||
|
||||
l = doSanityChecksAndDropIntoBase(t, l)
|
||||
|
||||
@@ -343,7 +344,7 @@ func TestRestrictionNoneInRealLoader(t *testing.T) {
|
||||
|
||||
var l ifc.Loader
|
||||
|
||||
l = newLoaderOrDie(RestrictionNone, fSys, dir)
|
||||
l = NewLoaderOrDie(RestrictionNone, fSys, dir)
|
||||
|
||||
l = doSanityChecksAndDropIntoBase(t, l)
|
||||
|
||||
@@ -442,7 +443,7 @@ func TestLoaderDisallowsLocalBaseFromRemoteOverlay(t *testing.T) {
|
||||
|
||||
// Establish that a local overlay can navigate
|
||||
// to the local bases.
|
||||
l1 = newLoaderOrDie(
|
||||
l1 = NewLoaderOrDie(
|
||||
RestrictionRootOnly, fSys, cloneRoot+"/foo/overlay")
|
||||
require.Equal(cloneRoot+"/foo/overlay", l1.Root())
|
||||
|
||||
@@ -600,7 +601,8 @@ func TestLoaderHTTP(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
l1 := NewFileLoaderAtRoot(MakeFakeFs(testCasesFile))
|
||||
l1 := NewLoaderOrDie(
|
||||
RestrictionRootOnly, MakeFakeFs(testCasesFile), filesys.Separator)
|
||||
require.Equal("/", l1.Root())
|
||||
|
||||
for _, x := range testCasesFile {
|
||||
@@ -11,8 +11,8 @@ import (
|
||||
|
||||
"sigs.k8s.io/kustomize/api/ifc"
|
||||
"sigs.k8s.io/kustomize/api/internal/generators"
|
||||
"sigs.k8s.io/kustomize/api/internal/loader"
|
||||
"sigs.k8s.io/kustomize/api/internal/target"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/provider"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"sigs.k8s.io/kustomize/api/ifc"
|
||||
"sigs.k8s.io/kustomize/api/internal/git"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/internal/loader"
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
)
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/internal/loader"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||
|
||||
@@ -10,10 +10,10 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
fLdr "sigs.k8s.io/kustomize/api/internal/loader"
|
||||
. "sigs.k8s.io/kustomize/api/internal/plugins/execplugin"
|
||||
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
||||
"sigs.k8s.io/kustomize/api/internal/plugins/utils"
|
||||
fLdr "sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/provider"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"sigs.k8s.io/kustomize/api/internal/loader"
|
||||
. "sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/provider"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||
|
||||
@@ -13,12 +13,12 @@ import (
|
||||
"sigs.k8s.io/kustomize/api/internal/accumulator"
|
||||
"sigs.k8s.io/kustomize/api/internal/builtins"
|
||||
"sigs.k8s.io/kustomize/api/internal/kusterr"
|
||||
load "sigs.k8s.io/kustomize/api/internal/loader"
|
||||
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||
"sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers"
|
||||
"sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
||||
"sigs.k8s.io/kustomize/api/internal/utils"
|
||||
"sigs.k8s.io/kustomize/api/konfig"
|
||||
load "sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
"sigs.k8s.io/kustomize/api/resource"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"sigs.k8s.io/kustomize/api/ifc"
|
||||
. "sigs.k8s.io/kustomize/api/internal/target"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/pkg/loader"
|
||||
"sigs.k8s.io/kustomize/api/provider"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
"sigs.k8s.io/kustomize/api/resource"
|
||||
|
||||
@@ -6,9 +6,9 @@ package target_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
fLdr "sigs.k8s.io/kustomize/api/internal/loader"
|
||||
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
||||
"sigs.k8s.io/kustomize/api/internal/target"
|
||||
fLdr "sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/provider"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/internal/loader"
|
||||
"sigs.k8s.io/kustomize/api/konfig"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||
)
|
||||
|
||||
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
"log"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/internal/builtins"
|
||||
fLdr "sigs.k8s.io/kustomize/api/internal/loader"
|
||||
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
||||
"sigs.k8s.io/kustomize/api/internal/target"
|
||||
"sigs.k8s.io/kustomize/api/internal/utils"
|
||||
"sigs.k8s.io/kustomize/api/konfig"
|
||||
fLdr "sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/provenance"
|
||||
"sigs.k8s.io/kustomize/api/provider"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
|
||||
@@ -16,8 +16,8 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"sigs.k8s.io/kustomize/api/internal/loader"
|
||||
"sigs.k8s.io/kustomize/api/krusty"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
ldr "sigs.k8s.io/kustomize/api/loader"
|
||||
ldr "sigs.k8s.io/kustomize/api/pkg/loader"
|
||||
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
|
||||
24
api/pkg/loader/loader.go
Normal file
24
api/pkg/loader/loader.go
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright 2023 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package pkg has all the helpers to interact with the api.
|
||||
package loader
|
||||
|
||||
import (
|
||||
"sigs.k8s.io/kustomize/api/internal/loader"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
)
|
||||
|
||||
// NewFileLoaderAtCwd returns a loader that loads from PWD.
|
||||
// A convenience for kustomize edit commands.
|
||||
func NewFileLoaderAtCwd(fSys filesys.FileSystem) *loader.FileLoader {
|
||||
return loader.NewLoaderOrDie(
|
||||
loader.RestrictionRootOnly, fSys, filesys.SelfDir)
|
||||
}
|
||||
|
||||
// NewFileLoaderAtRoot returns a loader that loads from "/".
|
||||
// A convenience for tests.
|
||||
func NewFileLoaderAtRoot(fSys filesys.FileSystem) *loader.FileLoader {
|
||||
return loader.NewLoaderOrDie(
|
||||
loader.RestrictionRootOnly, fSys, filesys.Separator)
|
||||
}
|
||||
@@ -9,8 +9,9 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"sigs.k8s.io/kustomize/api/ifc"
|
||||
loader "sigs.k8s.io/kustomize/api/internal/loader"
|
||||
"sigs.k8s.io/kustomize/api/kv"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
ldrpkg "sigs.k8s.io/kustomize/api/pkg/loader"
|
||||
. "sigs.k8s.io/kustomize/api/resmap"
|
||||
resmaptest_test "sigs.k8s.io/kustomize/api/testutils/resmaptest"
|
||||
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||
@@ -249,7 +250,7 @@ func TestNewResMapFromSecretArgs(t *testing.T) {
|
||||
|
||||
actual, err := rmF.NewResMapFromSecretArgs(
|
||||
kv.NewLoader(
|
||||
loader.NewFileLoaderAtRoot(fSys),
|
||||
ldrpkg.NewFileLoaderAtRoot(fSys),
|
||||
valtest_test.MakeFakeValidator()), secrets)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/internal/loader"
|
||||
. "sigs.k8s.io/kustomize/api/resource"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
"testing"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/ifc"
|
||||
fLdr "sigs.k8s.io/kustomize/api/internal/loader"
|
||||
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
||||
"sigs.k8s.io/kustomize/api/konfig"
|
||||
fLdr "sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/provider"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||
|
||||
11
go.work.sum
11
go.work.sum
@@ -7,6 +7,7 @@ github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCv
|
||||
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
@@ -31,20 +32,28 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
|
||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.starlark.net v0.0.0-20190528202925-30ae18b8564f/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
|
||||
|
||||
BIN
images/base.jpg
BIN
images/base.jpg
Binary file not shown.
|
Before Width: | Height: | Size: 40 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 73 KiB |
@@ -11,7 +11,7 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/api/konfig"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
ldrhelper "sigs.k8s.io/kustomize/api/pkg/loader"
|
||||
"sigs.k8s.io/kustomize/api/resource"
|
||||
"sigs.k8s.io/kustomize/kustomize/v5/commands/internal/kustfile"
|
||||
"sigs.k8s.io/kustomize/kustomize/v5/commands/internal/util"
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"log"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/pkg/loader"
|
||||
"sigs.k8s.io/kustomize/kustomize/v5/commands/internal/kustfile"
|
||||
"sigs.k8s.io/kustomize/kustomize/v5/commands/internal/util"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
|
||||
@@ -34,10 +34,11 @@ func (k kindOfAdd) String() string {
|
||||
}
|
||||
|
||||
type addMetadataOptions struct {
|
||||
force bool
|
||||
metadata map[string]string
|
||||
mapValidator func(map[string]string) error
|
||||
kind kindOfAdd
|
||||
force bool
|
||||
metadata map[string]string
|
||||
mapValidator func(map[string]string) error
|
||||
kind kindOfAdd
|
||||
labelsWithoutSelector bool
|
||||
}
|
||||
|
||||
// newCmdAddAnnotation adds one or more commonAnnotations to the kustomization file.
|
||||
@@ -79,6 +80,9 @@ func newCmdAddLabel(fSys filesys.FileSystem, v func(map[string]string) error) *c
|
||||
cmd.Flags().BoolVarP(&o.force, "force", "f", false,
|
||||
"overwrite commonLabel if it already exists",
|
||||
)
|
||||
cmd.Flags().BoolVar(&o.labelsWithoutSelector, "without-selector", false,
|
||||
"using add labels without selector option",
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
|
||||
@@ -127,6 +131,10 @@ func (o *addMetadataOptions) addAnnotations(m *types.Kustomization) error {
|
||||
}
|
||||
|
||||
func (o *addMetadataOptions) addLabels(m *types.Kustomization) error {
|
||||
if o.labelsWithoutSelector {
|
||||
m.Labels = append(m.Labels, types.Label{Pairs: make(map[string]string), IncludeSelectors: false})
|
||||
return o.writeToMap(m.Labels[len(m.Labels)-1].Pairs, label)
|
||||
}
|
||||
if m.CommonLabels == nil {
|
||||
m.CommonLabels = make(map[string]string)
|
||||
}
|
||||
|
||||
@@ -274,3 +274,27 @@ func TestAddLabelForce(t *testing.T) {
|
||||
assert.NoError(t, cmd.RunE(cmd, args))
|
||||
v.VerifyCall()
|
||||
}
|
||||
|
||||
func TestAddLabelWithoutSelector(t *testing.T) {
|
||||
var o addMetadataOptions
|
||||
o.labelsWithoutSelector = true
|
||||
m := makeKustomization(t)
|
||||
o.metadata = map[string]string{"new": "label"}
|
||||
assert.NoError(t, o.addLabels(m))
|
||||
assert.Equal(t, m.Labels[0], types.Label{Pairs: map[string]string{"new": "label"}})
|
||||
}
|
||||
|
||||
func TestAddLabelWithoutSelectorAddLabel(t *testing.T) {
|
||||
var o addMetadataOptions
|
||||
o.metadata = map[string]string{"owls": "cute", "otters": "adorable"}
|
||||
o.labelsWithoutSelector = true
|
||||
|
||||
m := makeKustomization(t)
|
||||
assert.NoError(t, o.addLabels(m))
|
||||
// adding new labels should work
|
||||
o.metadata = map[string]string{"new": "label"}
|
||||
assert.NoError(t, o.addLabels(m))
|
||||
|
||||
assert.Equal(t, m.Labels[0], types.Label{Pairs: map[string]string{"owls": "cute", "otters": "adorable"}})
|
||||
assert.Equal(t, m.Labels[1], types.Label{Pairs: map[string]string{"new": "label"}})
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"log"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
ldrhelper "sigs.k8s.io/kustomize/api/pkg/loader"
|
||||
"sigs.k8s.io/kustomize/kustomize/v5/commands/internal/kustfile"
|
||||
"sigs.k8s.io/kustomize/kustomize/v5/commands/internal/util"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
package add
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/api/ifc"
|
||||
"sigs.k8s.io/kustomize/api/resource"
|
||||
@@ -16,8 +18,9 @@ import (
|
||||
func newCmdAddConfigMap(
|
||||
fSys filesys.FileSystem,
|
||||
ldr ifc.KvLoader,
|
||||
rf *resource.Factory) *cobra.Command {
|
||||
var flags flagsAndArgs
|
||||
rf *resource.Factory,
|
||||
) *cobra.Command {
|
||||
var flags configmapSecretFlagsAndArgs
|
||||
cmd := &cobra.Command{
|
||||
Use: "configmap NAME [--behavior={create|merge|replace}] [--from-file=[key=]source] [--from-literal=key1=value1]",
|
||||
Short: "Adds a configmap to the kustomization file",
|
||||
@@ -36,63 +39,35 @@ func newCmdAddConfigMap(
|
||||
kustomize edit add configmap my-configmap --behavior=merge --from-env-file=env/path.env
|
||||
`,
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
err := flags.ExpandFileSource(fSys)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = flags.Validate(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Load the kustomization file.
|
||||
mf, err := kustfile.NewKustomizationFile(fSys)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
kustomization, err := mf.Read()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add the flagsAndArgs map to the kustomization file.
|
||||
err = addConfigMap(ldr, kustomization, flags, rf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write out the kustomization file with added configmap.
|
||||
return mf.Write(kustomization)
|
||||
return runEditAddConfigMap(flags, fSys, args, ldr, rf)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringSliceVar(
|
||||
&flags.FileSources,
|
||||
"from-file",
|
||||
fromFileFlag,
|
||||
[]string{},
|
||||
"Key file can be specified using its file path, in which case file basename will be used as configmap "+
|
||||
"key, or optionally with a key and file path, in which case the given key will be used. Specifying a "+
|
||||
"directory will iterate each named file in the directory whose basename is a valid configmap key.")
|
||||
cmd.Flags().StringArrayVar(
|
||||
&flags.LiteralSources,
|
||||
"from-literal",
|
||||
fromLiteralFlag,
|
||||
[]string{},
|
||||
"Specify a key and literal value to insert in configmap (i.e. mykey=somevalue)")
|
||||
cmd.Flags().StringVar(
|
||||
&flags.EnvFileSource,
|
||||
"from-env-file",
|
||||
fromEnvFileFlag,
|
||||
"",
|
||||
"Specify the path to a file to read lines of key=val pairs to create a configmap (i.e. a Docker .env file).")
|
||||
cmd.Flags().BoolVar(
|
||||
&flags.DisableNameSuffixHash,
|
||||
"disableNameSuffixHash",
|
||||
flagDisableNameSuffixHash,
|
||||
false,
|
||||
"Disable the name suffix for the configmap")
|
||||
cmd.Flags().StringVar(
|
||||
&flags.Behavior,
|
||||
"behavior",
|
||||
flagBehavior,
|
||||
"",
|
||||
"Specify the behavior for config map generation, i.e whether to create a new configmap (the default), "+
|
||||
"to merge with a previously defined one, or to replace an existing one. Merge and replace should be used only "+
|
||||
@@ -101,15 +76,60 @@ func newCmdAddConfigMap(
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runEditAddConfigMap(
|
||||
flags configmapSecretFlagsAndArgs,
|
||||
fSys filesys.FileSystem,
|
||||
args []string,
|
||||
ldr ifc.KvLoader,
|
||||
rf *resource.Factory,
|
||||
) error {
|
||||
err := flags.ExpandFileSource(fSys)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to expand file source: %w", err)
|
||||
}
|
||||
|
||||
err = flags.Validate(args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to validate flags: %w", err)
|
||||
}
|
||||
|
||||
// Load the kustomization file.
|
||||
mf, err := kustfile.NewKustomizationFile(fSys)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load kustomization file: %w", err)
|
||||
}
|
||||
|
||||
kustomization, err := mf.Read()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read kustomization file: %w", err)
|
||||
}
|
||||
|
||||
// Add the configmapSecretFlagsAndArgs map to the kustomization file.
|
||||
err = addConfigMap(ldr, kustomization, flags, rf)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create configmap: %w", err)
|
||||
}
|
||||
|
||||
// Write out the kustomization file with added configmap.
|
||||
err = mf.Write(kustomization)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write kustomization file: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// addConfigMap adds a configmap to a kustomization file.
|
||||
// Note: error may leave kustomization file in an undefined state.
|
||||
// Suggest passing a copy of kustomization file.
|
||||
func addConfigMap(
|
||||
ldr ifc.KvLoader,
|
||||
k *types.Kustomization,
|
||||
flags flagsAndArgs, rf *resource.Factory) error {
|
||||
flags configmapSecretFlagsAndArgs,
|
||||
rf *resource.Factory,
|
||||
) error {
|
||||
args := findOrMakeConfigMapArgs(k, flags.Name)
|
||||
mergeFlagsIntoCmArgs(args, flags)
|
||||
mergeFlagsIntoGeneratorArgs(&args.GeneratorArgs, flags)
|
||||
// Validate by trying to create corev1.configmap.
|
||||
args.Options = types.MergeGlobalOptionsIntoLocal(
|
||||
args.Options, k.GeneratorOptions)
|
||||
@@ -124,30 +144,9 @@ func findOrMakeConfigMapArgs(m *types.Kustomization, name string) *types.ConfigM
|
||||
}
|
||||
}
|
||||
// config map not found, create new one and add it to the kustomization file.
|
||||
cm := &types.ConfigMapArgs{GeneratorArgs: types.GeneratorArgs{Name: name}}
|
||||
cm := &types.ConfigMapArgs{
|
||||
GeneratorArgs: types.GeneratorArgs{Name: name},
|
||||
}
|
||||
m.ConfigMapGenerator = append(m.ConfigMapGenerator, *cm)
|
||||
return &m.ConfigMapGenerator[len(m.ConfigMapGenerator)-1]
|
||||
}
|
||||
|
||||
func mergeFlagsIntoCmArgs(args *types.ConfigMapArgs, flags flagsAndArgs) {
|
||||
if len(flags.LiteralSources) > 0 {
|
||||
args.LiteralSources = append(
|
||||
args.LiteralSources, flags.LiteralSources...)
|
||||
}
|
||||
if len(flags.FileSources) > 0 {
|
||||
args.FileSources = append(
|
||||
args.FileSources, flags.FileSources...)
|
||||
}
|
||||
if flags.EnvFileSource != "" {
|
||||
args.EnvSources = append(
|
||||
args.EnvSources, flags.EnvFileSource)
|
||||
}
|
||||
if flags.DisableNameSuffixHash {
|
||||
args.Options = &types.GeneratorOptions{
|
||||
DisableNameSuffixHash: true,
|
||||
}
|
||||
}
|
||||
if flags.Behavior != "" {
|
||||
args.Behavior = flags.Behavior
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,17 @@ import (
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
)
|
||||
|
||||
// flagsAndArgs encapsulates the options for add secret/configmap commands.
|
||||
type flagsAndArgs struct {
|
||||
const (
|
||||
fromFileFlag = "from-file"
|
||||
fromLiteralFlag = "from-literal"
|
||||
fromEnvFileFlag = "from-env-file"
|
||||
flagDisableNameSuffixHash = "disableNameSuffixHash"
|
||||
flagBehavior = "behavior"
|
||||
flagFormat = "--%s=%s"
|
||||
)
|
||||
|
||||
// configmapSecretFlagsAndArgs encapsulates the options for add secret/configmap commands.
|
||||
type configmapSecretFlagsAndArgs struct {
|
||||
// Name of configMap/Secret (required)
|
||||
Name string
|
||||
// FileSources to derive the configMap/Secret from (optional)
|
||||
@@ -35,7 +44,7 @@ type flagsAndArgs struct {
|
||||
}
|
||||
|
||||
// Validate validates required fields are set to support structured generation.
|
||||
func (a *flagsAndArgs) Validate(args []string) error {
|
||||
func (a *configmapSecretFlagsAndArgs) Validate(args []string) error {
|
||||
if len(args) != 1 {
|
||||
return fmt.Errorf("name must be specified once")
|
||||
}
|
||||
@@ -71,7 +80,7 @@ func (a *flagsAndArgs) Validate(args []string) error {
|
||||
// and the key, if missing, is the same as the value.
|
||||
// In the case where the key is explicitly declared,
|
||||
// the globbing, if present, must have exactly one match.
|
||||
func (a *flagsAndArgs) ExpandFileSource(fSys filesys.FileSystem) error {
|
||||
func (a *configmapSecretFlagsAndArgs) ExpandFileSource(fSys filesys.FileSystem) error {
|
||||
var results []string
|
||||
for _, pattern := range a.FileSources {
|
||||
var patterns []string
|
||||
@@ -105,3 +114,26 @@ func (a *flagsAndArgs) ExpandFileSource(fSys filesys.FileSystem) error {
|
||||
a.FileSources = results
|
||||
return nil
|
||||
}
|
||||
|
||||
func mergeFlagsIntoGeneratorArgs(args *types.GeneratorArgs, flags configmapSecretFlagsAndArgs) {
|
||||
if len(flags.LiteralSources) > 0 {
|
||||
args.LiteralSources = append(
|
||||
args.LiteralSources, flags.LiteralSources...)
|
||||
}
|
||||
if len(flags.FileSources) > 0 {
|
||||
args.FileSources = append(
|
||||
args.FileSources, flags.FileSources...)
|
||||
}
|
||||
if flags.EnvFileSource != "" {
|
||||
args.EnvSources = append(
|
||||
args.EnvSources, flags.EnvFileSource)
|
||||
}
|
||||
if flags.DisableNameSuffixHash {
|
||||
args.Options = &types.GeneratorOptions{
|
||||
DisableNameSuffixHash: true,
|
||||
}
|
||||
}
|
||||
if flags.Behavior != "" {
|
||||
args.Behavior = flags.Behavior
|
||||
}
|
||||
}
|
||||
@@ -7,31 +7,30 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
)
|
||||
|
||||
func TestDataValidation_NoName(t *testing.T) {
|
||||
fa := flagsAndArgs{}
|
||||
assert.Error(t, fa.Validate([]string{}))
|
||||
fa := configmapSecretFlagsAndArgs{}
|
||||
require.Error(t, fa.Validate([]string{}))
|
||||
}
|
||||
|
||||
func TestDataValidation_MoreThanOneName(t *testing.T) {
|
||||
fa := flagsAndArgs{}
|
||||
fa := configmapSecretFlagsAndArgs{}
|
||||
|
||||
assert.Error(t, fa.Validate([]string{"name", "othername"}))
|
||||
require.Error(t, fa.Validate([]string{"name", "othername"}))
|
||||
}
|
||||
|
||||
func TestDataConfigValidation_Flags(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
fa flagsAndArgs
|
||||
fa configmapSecretFlagsAndArgs
|
||||
shouldFail bool
|
||||
}{
|
||||
{
|
||||
name: "env-file-source and literal are both set",
|
||||
fa: flagsAndArgs{
|
||||
fa: configmapSecretFlagsAndArgs{
|
||||
LiteralSources: []string{"one", "two"},
|
||||
EnvFileSource: "three",
|
||||
},
|
||||
@@ -39,7 +38,7 @@ func TestDataConfigValidation_Flags(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "env-file-source and from-file are both set",
|
||||
fa: flagsAndArgs{
|
||||
fa: configmapSecretFlagsAndArgs{
|
||||
FileSources: []string{"one", "two"},
|
||||
EnvFileSource: "three",
|
||||
},
|
||||
@@ -47,12 +46,12 @@ func TestDataConfigValidation_Flags(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "we don't have any option set",
|
||||
fa: flagsAndArgs{},
|
||||
fa: configmapSecretFlagsAndArgs{},
|
||||
shouldFail: true,
|
||||
},
|
||||
{
|
||||
name: "we have from-file and literal ",
|
||||
fa: flagsAndArgs{
|
||||
fa: configmapSecretFlagsAndArgs{
|
||||
LiteralSources: []string{"one", "two"},
|
||||
FileSources: []string{"three", "four"},
|
||||
},
|
||||
@@ -60,7 +59,7 @@ func TestDataConfigValidation_Flags(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "correct behavior",
|
||||
fa: flagsAndArgs{
|
||||
fa: configmapSecretFlagsAndArgs{
|
||||
EnvFileSource: "foo",
|
||||
Behavior: "merge",
|
||||
},
|
||||
@@ -68,7 +67,7 @@ func TestDataConfigValidation_Flags(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "incorrect behavior",
|
||||
fa: flagsAndArgs{
|
||||
fa: configmapSecretFlagsAndArgs{
|
||||
EnvFileSource: "foo",
|
||||
Behavior: "merge-unknown",
|
||||
},
|
||||
@@ -79,9 +78,9 @@ func TestDataConfigValidation_Flags(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
err := test.fa.Validate([]string{"name"})
|
||||
if test.shouldFail {
|
||||
assert.Error(t, err)
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,7 +93,7 @@ func TestExpandFileSource(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
_, err = fSys.Create("dir/readme")
|
||||
require.NoError(t, err)
|
||||
fa := flagsAndArgs{
|
||||
fa := configmapSecretFlagsAndArgs{
|
||||
FileSources: []string{"dir/fa*"},
|
||||
}
|
||||
err = fa.ExpandFileSource(fSys)
|
||||
@@ -118,7 +117,7 @@ func TestExpandFileSourceWithKey(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
_, err = fSys.Create("dir/readme")
|
||||
require.NoError(t, err)
|
||||
fa := flagsAndArgs{
|
||||
fa := configmapSecretFlagsAndArgs{
|
||||
FileSources: []string{"foo-key=dir/fa*", "bar-key=dir/foobar", "dir/simplebar"},
|
||||
}
|
||||
err = fa.ExpandFileSource(fSys)
|
||||
@@ -141,7 +140,7 @@ func TestExpandFileSourceWithKeyAndError(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
_, err = fSys.Create("dir/readme")
|
||||
require.NoError(t, err)
|
||||
fa := flagsAndArgs{
|
||||
fa := configmapSecretFlagsAndArgs{
|
||||
FileSources: []string{"foo-key=dir/fa*"},
|
||||
}
|
||||
err = fa.ExpandFileSource(fSys)
|
||||
@@ -4,13 +4,18 @@
|
||||
package add
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"sigs.k8s.io/kustomize/api/kv"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/pkg/loader"
|
||||
"sigs.k8s.io/kustomize/api/provider"
|
||||
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kustomize/v5/commands/internal/kustfile"
|
||||
testutils_test "sigs.k8s.io/kustomize/kustomize/v5/commands/internal/testutils"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
)
|
||||
|
||||
@@ -47,10 +52,10 @@ func TestMergeFlagsIntoConfigMapArgs_LiteralSources(t *testing.T) {
|
||||
args := findOrMakeConfigMapArgs(k, "foo")
|
||||
mergeFlagsIntoGeneratorArgs(
|
||||
&args.GeneratorArgs,
|
||||
flagsAndArgs{LiteralSources: []string{"k1=v1"}})
|
||||
configmapSecretFlagsAndArgs{LiteralSources: []string{"k1=v1"}})
|
||||
mergeFlagsIntoGeneratorArgs(
|
||||
&args.GeneratorArgs,
|
||||
flagsAndArgs{LiteralSources: []string{"k2=v2"}})
|
||||
configmapSecretFlagsAndArgs{LiteralSources: []string{"k2=v2"}})
|
||||
assert.Equal(t, "k1=v1", k.ConfigMapGenerator[0].LiteralSources[0])
|
||||
assert.Equal(t, "k2=v2", k.ConfigMapGenerator[0].LiteralSources[1])
|
||||
}
|
||||
@@ -60,10 +65,10 @@ func TestMergeFlagsIntoConfigMapArgs_FileSources(t *testing.T) {
|
||||
args := findOrMakeConfigMapArgs(k, "foo")
|
||||
mergeFlagsIntoGeneratorArgs(
|
||||
&args.GeneratorArgs,
|
||||
flagsAndArgs{FileSources: []string{"file1"}})
|
||||
configmapSecretFlagsAndArgs{FileSources: []string{"file1"}})
|
||||
mergeFlagsIntoGeneratorArgs(
|
||||
&args.GeneratorArgs,
|
||||
flagsAndArgs{FileSources: []string{"file2"}})
|
||||
configmapSecretFlagsAndArgs{FileSources: []string{"file2"}})
|
||||
assert.Equal(t, "file1", k.ConfigMapGenerator[0].FileSources[0])
|
||||
assert.Equal(t, "file2", k.ConfigMapGenerator[0].FileSources[1])
|
||||
}
|
||||
@@ -73,10 +78,10 @@ func TestMergeFlagsIntoConfigMapArgs_EnvSource(t *testing.T) {
|
||||
args := findOrMakeConfigMapArgs(k, "foo")
|
||||
mergeFlagsIntoGeneratorArgs(
|
||||
&args.GeneratorArgs,
|
||||
flagsAndArgs{EnvFileSource: "env1"})
|
||||
configmapSecretFlagsAndArgs{EnvFileSource: "env1"})
|
||||
mergeFlagsIntoGeneratorArgs(
|
||||
&args.GeneratorArgs,
|
||||
flagsAndArgs{EnvFileSource: "env2"})
|
||||
configmapSecretFlagsAndArgs{EnvFileSource: "env2"})
|
||||
assert.Equal(t, "env1", k.ConfigMapGenerator[0].EnvSources[0])
|
||||
assert.Equal(t, "env2", k.ConfigMapGenerator[0].EnvSources[1])
|
||||
}
|
||||
@@ -85,7 +90,7 @@ func TestMergeFlagsIntoConfigMapArgs_Behavior(t *testing.T) {
|
||||
k := &types.Kustomization{}
|
||||
args := findOrMakeConfigMapArgs(k, "foo")
|
||||
|
||||
createBehaviorFlags := flagsAndArgs{
|
||||
createBehaviorFlags := configmapSecretFlagsAndArgs{
|
||||
Behavior: "create",
|
||||
EnvFileSource: "env1",
|
||||
}
|
||||
@@ -94,7 +99,7 @@ func TestMergeFlagsIntoConfigMapArgs_Behavior(t *testing.T) {
|
||||
createBehaviorFlags)
|
||||
assert.Equal(t, "create", k.ConfigMapGenerator[0].Behavior)
|
||||
|
||||
mergeBehaviorFlags := flagsAndArgs{
|
||||
mergeBehaviorFlags := configmapSecretFlagsAndArgs{
|
||||
Behavior: "merge",
|
||||
EnvFileSource: "env1",
|
||||
}
|
||||
@@ -103,7 +108,7 @@ func TestMergeFlagsIntoConfigMapArgs_Behavior(t *testing.T) {
|
||||
mergeBehaviorFlags)
|
||||
assert.Equal(t, "merge", k.ConfigMapGenerator[0].Behavior)
|
||||
|
||||
replaceBehaviorFlags := flagsAndArgs{
|
||||
replaceBehaviorFlags := configmapSecretFlagsAndArgs{
|
||||
Behavior: "replace",
|
||||
EnvFileSource: "env1",
|
||||
}
|
||||
@@ -112,3 +117,144 @@ func TestMergeFlagsIntoConfigMapArgs_Behavior(t *testing.T) {
|
||||
replaceBehaviorFlags)
|
||||
assert.Equal(t, "replace", k.ConfigMapGenerator[0].Behavior)
|
||||
}
|
||||
|
||||
// TestEditAddConfigMapWithLiteralSource executes the same command flow as the CLI invocation
|
||||
// with a --from-literal flag
|
||||
func TestEditAddConfigMapWithLiteralSource(t *testing.T) {
|
||||
const (
|
||||
configMapName = "test-kustomization"
|
||||
literalSource = "test-key=test-value"
|
||||
)
|
||||
|
||||
fSys := filesys.MakeEmptyDirInMemory()
|
||||
testutils_test.WriteTestKustomization(fSys)
|
||||
|
||||
pvd := provider.NewDefaultDepProvider()
|
||||
ldr := kv.NewLoader(loader.NewFileLoaderAtCwd(fSys), pvd.GetFieldValidator())
|
||||
|
||||
args := []string{
|
||||
configMapName,
|
||||
fmt.Sprintf(flagFormat, fromLiteralFlag, literalSource),
|
||||
}
|
||||
cmd := newCmdAddConfigMap(fSys, ldr, pvd.GetResourceFactory())
|
||||
cmd.SetArgs(args)
|
||||
require.NoError(t, cmd.Execute())
|
||||
|
||||
_, err := testutils_test.ReadTestKustomization(fSys)
|
||||
require.NoError(t, err)
|
||||
|
||||
mf, err := kustfile.NewKustomizationFile(fSys)
|
||||
require.NoError(t, err)
|
||||
|
||||
kustomization, err := mf.Read()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotNil(t, kustomization)
|
||||
require.NotEmpty(t, kustomization.ConfigMapGenerator)
|
||||
require.Equal(t, 1, len(kustomization.ConfigMapGenerator))
|
||||
|
||||
newCmGenerator := kustomization.ConfigMapGenerator[0]
|
||||
require.NotNil(t, newCmGenerator)
|
||||
require.Equal(t, configMapName, newCmGenerator.Name)
|
||||
require.Contains(t, newCmGenerator.LiteralSources, literalSource)
|
||||
}
|
||||
|
||||
// TestEditAddConfigMapWithEnvSource executes the same command flow as the CLI invocation
|
||||
// with a --from-env-file flag
|
||||
func TestEditAddConfigMapWithEnvSource(t *testing.T) {
|
||||
const (
|
||||
configMapName = "test-kustomization"
|
||||
envSource = "test-env-source"
|
||||
)
|
||||
|
||||
fSys := filesys.MakeEmptyDirInMemory()
|
||||
testutils_test.WriteTestKustomization(fSys)
|
||||
|
||||
pvd := provider.NewDefaultDepProvider()
|
||||
ldr := kv.NewLoader(loader.NewFileLoaderAtCwd(fSys), pvd.GetFieldValidator())
|
||||
|
||||
envFileContent, err := fSys.Create("test-env-source")
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = envFileContent.Write([]byte("TEST=value"))
|
||||
require.NoError(t, err)
|
||||
|
||||
err = envFileContent.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
args := []string{
|
||||
configMapName,
|
||||
fmt.Sprintf(flagFormat, fromEnvFileFlag, envSource),
|
||||
}
|
||||
cmd := newCmdAddConfigMap(fSys, ldr, pvd.GetResourceFactory())
|
||||
cmd.SetArgs(args)
|
||||
require.NoError(t, cmd.Execute())
|
||||
|
||||
_, err = testutils_test.ReadTestKustomization(fSys)
|
||||
require.NoError(t, err)
|
||||
|
||||
mf, err := kustfile.NewKustomizationFile(fSys)
|
||||
require.NoError(t, err)
|
||||
|
||||
kustomization, err := mf.Read()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotNil(t, kustomization)
|
||||
require.NotEmpty(t, kustomization.ConfigMapGenerator)
|
||||
require.Equal(t, 1, len(kustomization.ConfigMapGenerator))
|
||||
|
||||
newCmGenerator := kustomization.ConfigMapGenerator[0]
|
||||
require.NotNil(t, newCmGenerator)
|
||||
require.Equal(t, configMapName, newCmGenerator.Name)
|
||||
require.Contains(t, newCmGenerator.EnvSources, envSource)
|
||||
}
|
||||
|
||||
// TestEditAddConfigMapWithFileSource executes the same command flow as the CLI invocation
|
||||
// with a --from-file flag
|
||||
func TestEditAddConfigMapWithFileSource(t *testing.T) {
|
||||
const (
|
||||
configMapName = "test-kustomization"
|
||||
fileSource = "test-file-source"
|
||||
)
|
||||
|
||||
fSys := filesys.MakeEmptyDirInMemory()
|
||||
testutils_test.WriteTestKustomization(fSys)
|
||||
|
||||
pvd := provider.NewDefaultDepProvider()
|
||||
ldr := kv.NewLoader(loader.NewFileLoaderAtCwd(fSys), pvd.GetFieldValidator())
|
||||
|
||||
fileContent, err := fSys.Create("test-file-source")
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = fileContent.Write([]byte("any content here"))
|
||||
require.NoError(t, err)
|
||||
|
||||
err = fileContent.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
args := []string{
|
||||
configMapName,
|
||||
fmt.Sprintf(flagFormat, fromFileFlag, fileSource),
|
||||
}
|
||||
cmd := newCmdAddConfigMap(fSys, ldr, pvd.GetResourceFactory())
|
||||
cmd.SetArgs(args)
|
||||
require.NoError(t, cmd.Execute())
|
||||
|
||||
_, err = testutils_test.ReadTestKustomization(fSys)
|
||||
require.NoError(t, err)
|
||||
|
||||
mf, err := kustfile.NewKustomizationFile(fSys)
|
||||
require.NoError(t, err)
|
||||
|
||||
kustomization, err := mf.Read()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotNil(t, kustomization)
|
||||
require.NotEmpty(t, kustomization.ConfigMapGenerator)
|
||||
require.Equal(t, 1, len(kustomization.ConfigMapGenerator))
|
||||
|
||||
newCmGenerator := kustomization.ConfigMapGenerator[0]
|
||||
require.NotNil(t, newCmGenerator)
|
||||
require.Equal(t, configMapName, newCmGenerator.Name)
|
||||
require.Contains(t, newCmGenerator.FileSources, fileSource)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
package add
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/api/ifc"
|
||||
"sigs.k8s.io/kustomize/api/resource"
|
||||
@@ -16,8 +18,9 @@ import (
|
||||
func newCmdAddSecret(
|
||||
fSys filesys.FileSystem,
|
||||
ldr ifc.KvLoader,
|
||||
rf *resource.Factory) *cobra.Command {
|
||||
var flags flagsAndArgs
|
||||
rf *resource.Factory,
|
||||
) *cobra.Command {
|
||||
var flags configmapSecretFlagsAndArgs
|
||||
cmd := &cobra.Command{
|
||||
Use: "secret NAME [--from-file=[key=]source] [--from-literal=key1=value1] [--type=Opaque|kubernetes.io/tls]",
|
||||
Short: "Adds a secret to the kustomization file.",
|
||||
@@ -33,53 +36,25 @@ func newCmdAddSecret(
|
||||
kustomize edit add secret my-secret --from-env-file=env/path.env
|
||||
`,
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
err := flags.ExpandFileSource(fSys)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = flags.Validate(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Load the kustomization file.
|
||||
mf, err := kustfile.NewKustomizationFile(fSys)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
kustomization, err := mf.Read()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add the flagsAndArgs map to the kustomization file.
|
||||
err = addSecret(ldr, kustomization, flags, rf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write out the kustomization file with added secret.
|
||||
return mf.Write(kustomization)
|
||||
return runEditAddSecret(flags, fSys, args, ldr, rf)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringSliceVar(
|
||||
&flags.FileSources,
|
||||
"from-file",
|
||||
fromFileFlag,
|
||||
[]string{},
|
||||
"Key file can be specified using its file path, in which case file basename will be used as secret "+
|
||||
"key, or optionally with a key and file path, in which case the given key will be used. Specifying a "+
|
||||
"directory will iterate each named file in the directory whose basename is a valid secret key.")
|
||||
cmd.Flags().StringArrayVar(
|
||||
&flags.LiteralSources,
|
||||
"from-literal",
|
||||
fromLiteralFlag,
|
||||
[]string{},
|
||||
"Specify a key and literal value to insert in secret (i.e. mykey=somevalue)")
|
||||
cmd.Flags().StringVar(
|
||||
&flags.EnvFileSource,
|
||||
"from-env-file",
|
||||
fromEnvFileFlag,
|
||||
"",
|
||||
"Specify the path to a file to read lines of key=val pairs to create a secret (i.e. a Docker .env file).")
|
||||
cmd.Flags().StringVar(
|
||||
@@ -94,20 +69,63 @@ func newCmdAddSecret(
|
||||
"Specify the namespace of the secret")
|
||||
cmd.Flags().BoolVar(
|
||||
&flags.DisableNameSuffixHash,
|
||||
"disableNameSuffixHash",
|
||||
flagDisableNameSuffixHash,
|
||||
false,
|
||||
"Disable the name suffix for the secret")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runEditAddSecret(
|
||||
flags configmapSecretFlagsAndArgs,
|
||||
fSys filesys.FileSystem,
|
||||
args []string,
|
||||
ldr ifc.KvLoader,
|
||||
rf *resource.Factory,
|
||||
) error {
|
||||
err := flags.ExpandFileSource(fSys)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to expand file source: %w", err)
|
||||
}
|
||||
|
||||
err = flags.Validate(args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to validate flags: %w", err)
|
||||
}
|
||||
|
||||
// Load the kustomization file.
|
||||
mf, err := kustfile.NewKustomizationFile(fSys)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load kustomization file: %w", err)
|
||||
}
|
||||
|
||||
kustomization, err := mf.Read()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read kustomization file: %w", err)
|
||||
}
|
||||
|
||||
// Add the configmapSecretFlagsAndArgs map to the kustomization file.
|
||||
err = addSecret(ldr, kustomization, flags, rf)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create secret: %w", err)
|
||||
}
|
||||
|
||||
// Write out the kustomization file with added secret.
|
||||
err = mf.Write(kustomization)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write kustomization file: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// addSecret adds a secret to a kustomization file.
|
||||
// Note: error may leave kustomization file in an undefined state.
|
||||
// Suggest passing a copy of kustomization file.
|
||||
func addSecret(
|
||||
ldr ifc.KvLoader,
|
||||
k *types.Kustomization,
|
||||
flags flagsAndArgs, rf *resource.Factory) error {
|
||||
flags configmapSecretFlagsAndArgs, rf *resource.Factory) error {
|
||||
args := findOrMakeSecretArgs(k, flags.Name, flags.Namespace, flags.Type)
|
||||
mergeFlagsIntoGeneratorArgs(&args.GeneratorArgs, flags)
|
||||
// Validate by trying to create corev1.secret.
|
||||
@@ -131,26 +149,3 @@ func findOrMakeSecretArgs(m *types.Kustomization, name, namespace, secretType st
|
||||
m.SecretGenerator = append(m.SecretGenerator, *secret)
|
||||
return &m.SecretGenerator[len(m.SecretGenerator)-1]
|
||||
}
|
||||
|
||||
func mergeFlagsIntoGeneratorArgs(args *types.GeneratorArgs, flags flagsAndArgs) {
|
||||
if len(flags.LiteralSources) > 0 {
|
||||
args.LiteralSources = append(
|
||||
args.LiteralSources, flags.LiteralSources...)
|
||||
}
|
||||
if len(flags.FileSources) > 0 {
|
||||
args.FileSources = append(
|
||||
args.FileSources, flags.FileSources...)
|
||||
}
|
||||
if flags.EnvFileSource != "" {
|
||||
args.EnvSources = append(
|
||||
args.EnvSources, flags.EnvFileSource)
|
||||
}
|
||||
if flags.DisableNameSuffixHash {
|
||||
args.Options = &types.GeneratorOptions{
|
||||
DisableNameSuffixHash: true,
|
||||
}
|
||||
}
|
||||
if flags.Behavior != "" {
|
||||
args.Behavior = flags.Behavior
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,18 @@
|
||||
package add
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"sigs.k8s.io/kustomize/api/kv"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/pkg/loader"
|
||||
"sigs.k8s.io/kustomize/api/provider"
|
||||
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kustomize/v5/commands/internal/kustfile"
|
||||
testutils_test "sigs.k8s.io/kustomize/kustomize/v5/commands/internal/testutils"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
)
|
||||
|
||||
@@ -48,10 +53,10 @@ func TestMergeFlagsIntoSecretArgs_LiteralSources(t *testing.T) {
|
||||
args := findOrMakeSecretArgs(k, "foo", "bar", "forbidden")
|
||||
mergeFlagsIntoGeneratorArgs(
|
||||
&args.GeneratorArgs,
|
||||
flagsAndArgs{LiteralSources: []string{"k1=v1"}})
|
||||
configmapSecretFlagsAndArgs{LiteralSources: []string{"k1=v1"}})
|
||||
mergeFlagsIntoGeneratorArgs(
|
||||
&args.GeneratorArgs,
|
||||
flagsAndArgs{LiteralSources: []string{"k2=v2"}})
|
||||
configmapSecretFlagsAndArgs{LiteralSources: []string{"k2=v2"}})
|
||||
assert.Equal(t, "k1=v1", k.SecretGenerator[0].LiteralSources[0])
|
||||
assert.Equal(t, "k2=v2", k.SecretGenerator[0].LiteralSources[1])
|
||||
}
|
||||
@@ -61,10 +66,10 @@ func TestMergeFlagsIntoSecretArgs_FileSources(t *testing.T) {
|
||||
args := findOrMakeSecretArgs(k, "foo", "bar", "forbidden")
|
||||
mergeFlagsIntoGeneratorArgs(
|
||||
&args.GeneratorArgs,
|
||||
flagsAndArgs{FileSources: []string{"file1"}})
|
||||
configmapSecretFlagsAndArgs{FileSources: []string{"file1"}})
|
||||
mergeFlagsIntoGeneratorArgs(
|
||||
&args.GeneratorArgs,
|
||||
flagsAndArgs{FileSources: []string{"file2"}})
|
||||
configmapSecretFlagsAndArgs{FileSources: []string{"file2"}})
|
||||
assert.Equal(t, "file1", k.SecretGenerator[0].FileSources[0])
|
||||
assert.Equal(t, "file2", k.SecretGenerator[0].FileSources[1])
|
||||
}
|
||||
@@ -74,10 +79,10 @@ func TestMergeFlagsIntoSecretArgs_EnvSource(t *testing.T) {
|
||||
args := findOrMakeSecretArgs(k, "foo", "bar", "forbidden")
|
||||
mergeFlagsIntoGeneratorArgs(
|
||||
&args.GeneratorArgs,
|
||||
flagsAndArgs{EnvFileSource: "env1"})
|
||||
configmapSecretFlagsAndArgs{EnvFileSource: "env1"})
|
||||
mergeFlagsIntoGeneratorArgs(
|
||||
&args.GeneratorArgs,
|
||||
flagsAndArgs{EnvFileSource: "env2"})
|
||||
configmapSecretFlagsAndArgs{EnvFileSource: "env2"})
|
||||
assert.Equal(t, "env1", k.SecretGenerator[0].EnvSources[0])
|
||||
assert.Equal(t, "env2", k.SecretGenerator[0].EnvSources[1])
|
||||
}
|
||||
@@ -87,6 +92,147 @@ func TestMergeFlagsIntoSecretArgs_DisableNameSuffixHash(t *testing.T) {
|
||||
args := findOrMakeSecretArgs(k, "foo", "bar", "forbidden")
|
||||
mergeFlagsIntoGeneratorArgs(
|
||||
&args.GeneratorArgs,
|
||||
flagsAndArgs{DisableNameSuffixHash: true})
|
||||
configmapSecretFlagsAndArgs{DisableNameSuffixHash: true})
|
||||
assert.True(t, k.SecretGenerator[0].Options.DisableNameSuffixHash)
|
||||
}
|
||||
|
||||
// TestEditAddSecretWithLiteralSource executes the same command flow as the CLI invocation
|
||||
// with a --from-literal flag
|
||||
func TestEditAddSecretWithLiteralSource(t *testing.T) {
|
||||
const (
|
||||
secretName = "test-kustomization"
|
||||
literalSource = "test-key=test-value"
|
||||
)
|
||||
|
||||
fSys := filesys.MakeEmptyDirInMemory()
|
||||
testutils_test.WriteTestKustomization(fSys)
|
||||
|
||||
pvd := provider.NewDefaultDepProvider()
|
||||
ldr := kv.NewLoader(loader.NewFileLoaderAtCwd(fSys), pvd.GetFieldValidator())
|
||||
|
||||
args := []string{
|
||||
secretName,
|
||||
fmt.Sprintf(flagFormat, fromLiteralFlag, literalSource),
|
||||
}
|
||||
cmd := newCmdAddSecret(fSys, ldr, pvd.GetResourceFactory())
|
||||
cmd.SetArgs(args)
|
||||
require.NoError(t, cmd.Execute())
|
||||
|
||||
_, err := testutils_test.ReadTestKustomization(fSys)
|
||||
require.NoError(t, err)
|
||||
|
||||
mf, err := kustfile.NewKustomizationFile(fSys)
|
||||
require.NoError(t, err)
|
||||
|
||||
kustomization, err := mf.Read()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotNil(t, kustomization)
|
||||
require.NotEmpty(t, kustomization.SecretGenerator)
|
||||
require.Equal(t, 1, len(kustomization.SecretGenerator))
|
||||
|
||||
newSecretGenerator := kustomization.SecretGenerator[0]
|
||||
require.NotNil(t, newSecretGenerator)
|
||||
require.Equal(t, secretName, newSecretGenerator.Name)
|
||||
require.Contains(t, newSecretGenerator.LiteralSources, literalSource)
|
||||
}
|
||||
|
||||
// TestEditAddSecretWithEnvSource executes the same command flow as the CLI invocation
|
||||
// with a --from-env-file flag
|
||||
func TestEditAddSecretWithEnvSource(t *testing.T) {
|
||||
const (
|
||||
secretName = "test-kustomization"
|
||||
envSource = "test-env-source"
|
||||
)
|
||||
|
||||
fSys := filesys.MakeEmptyDirInMemory()
|
||||
testutils_test.WriteTestKustomization(fSys)
|
||||
|
||||
pvd := provider.NewDefaultDepProvider()
|
||||
ldr := kv.NewLoader(loader.NewFileLoaderAtCwd(fSys), pvd.GetFieldValidator())
|
||||
|
||||
envFileContent, err := fSys.Create("test-env-source")
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = envFileContent.Write([]byte("TEST=value"))
|
||||
require.NoError(t, err)
|
||||
|
||||
err = envFileContent.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
args := []string{
|
||||
secretName,
|
||||
fmt.Sprintf(flagFormat, fromEnvFileFlag, envSource),
|
||||
}
|
||||
cmd := newCmdAddSecret(fSys, ldr, pvd.GetResourceFactory())
|
||||
cmd.SetArgs(args)
|
||||
require.NoError(t, cmd.Execute())
|
||||
|
||||
_, err = testutils_test.ReadTestKustomization(fSys)
|
||||
require.NoError(t, err)
|
||||
|
||||
mf, err := kustfile.NewKustomizationFile(fSys)
|
||||
require.NoError(t, err)
|
||||
|
||||
kustomization, err := mf.Read()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotNil(t, kustomization)
|
||||
require.NotEmpty(t, kustomization.SecretGenerator)
|
||||
require.Equal(t, 1, len(kustomization.SecretGenerator))
|
||||
|
||||
newSecretGenerator := kustomization.SecretGenerator[0]
|
||||
require.NotNil(t, newSecretGenerator)
|
||||
require.Equal(t, secretName, newSecretGenerator.Name)
|
||||
require.Contains(t, newSecretGenerator.EnvSources, envSource)
|
||||
}
|
||||
|
||||
// TestEditAddSecretWithFileSource executes the same command flow as the CLI invocation
|
||||
// with a --from-file flag
|
||||
func TestEditAddSecretWithFileSource(t *testing.T) {
|
||||
const (
|
||||
secretName = "test-kustomization"
|
||||
fileSource = "test-file-source"
|
||||
)
|
||||
|
||||
fSys := filesys.MakeEmptyDirInMemory()
|
||||
testutils_test.WriteTestKustomization(fSys)
|
||||
|
||||
pvd := provider.NewDefaultDepProvider()
|
||||
ldr := kv.NewLoader(loader.NewFileLoaderAtCwd(fSys), pvd.GetFieldValidator())
|
||||
|
||||
fileContent, err := fSys.Create("test-file-source")
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = fileContent.Write([]byte("any content here"))
|
||||
require.NoError(t, err)
|
||||
|
||||
err = fileContent.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
args := []string{
|
||||
secretName,
|
||||
fmt.Sprintf(flagFormat, fromFileFlag, fileSource),
|
||||
}
|
||||
cmd := newCmdAddSecret(fSys, ldr, pvd.GetResourceFactory())
|
||||
cmd.SetArgs(args)
|
||||
require.NoError(t, cmd.Execute())
|
||||
|
||||
_, err = testutils_test.ReadTestKustomization(fSys)
|
||||
require.NoError(t, err)
|
||||
|
||||
mf, err := kustfile.NewKustomizationFile(fSys)
|
||||
require.NoError(t, err)
|
||||
|
||||
kustomization, err := mf.Read()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotNil(t, kustomization)
|
||||
require.NotEmpty(t, kustomization.SecretGenerator)
|
||||
require.Equal(t, 1, len(kustomization.SecretGenerator))
|
||||
|
||||
newSecretGenerator := kustomization.SecretGenerator[0]
|
||||
require.NotNil(t, newSecretGenerator)
|
||||
require.Equal(t, secretName, newSecretGenerator.Name)
|
||||
require.Contains(t, newSecretGenerator.FileSources, fileSource)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/api/ifc"
|
||||
"sigs.k8s.io/kustomize/api/kv"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
ldrhelper "sigs.k8s.io/kustomize/api/pkg/loader"
|
||||
"sigs.k8s.io/kustomize/api/resource"
|
||||
"sigs.k8s.io/kustomize/kustomize/v5/commands/edit/add"
|
||||
"sigs.k8s.io/kustomize/kustomize/v5/commands/edit/fix"
|
||||
@@ -43,11 +43,11 @@ func NewCmdEdit(
|
||||
c.AddCommand(
|
||||
add.NewCmdAdd(
|
||||
fSys,
|
||||
kv.NewLoader(loader.NewFileLoaderAtCwd(fSys), v),
|
||||
kv.NewLoader(ldrhelper.NewFileLoaderAtCwd(fSys), v),
|
||||
rf),
|
||||
set.NewCmdSet(
|
||||
fSys,
|
||||
kv.NewLoader(loader.NewFileLoaderAtCwd(fSys), v),
|
||||
kv.NewLoader(ldrhelper.NewFileLoaderAtCwd(fSys), v),
|
||||
v),
|
||||
fix.NewCmdFix(fSys, w),
|
||||
remove.NewCmdRemove(fSys, v),
|
||||
|
||||
@@ -22,6 +22,12 @@ func NewCmdRemove(
|
||||
kustomize edit remove resource {filepath} {filepath}
|
||||
kustomize edit remove resource {pattern}
|
||||
|
||||
# Removes one or more configmap from the kustomization file
|
||||
kustomize edit remove configmap {name1},{name2}
|
||||
|
||||
# Removes one or more secret from the kustomization file
|
||||
kustomize edit remove secret {name1},{name2}
|
||||
|
||||
# Removes one or more patches from the kustomization file
|
||||
kustomize edit remove patch --path {filepath} --group {target group name} --version {target version}
|
||||
|
||||
@@ -37,6 +43,8 @@ func NewCmdRemove(
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
}
|
||||
c.AddCommand(
|
||||
newCmdRemoveConfigMap(fSys),
|
||||
newCmdRemoveSecret(fSys),
|
||||
newCmdRemoveResource(fSys),
|
||||
newCmdRemoveLabel(fSys, v.MakeLabelNameValidator()),
|
||||
newCmdRemoveAnnotation(fSys, v.MakeAnnotationNameValidator()),
|
||||
|
||||
99
kustomize/commands/edit/remove/removeconfigmap.go
Normal file
99
kustomize/commands/edit/remove/removeconfigmap.go
Normal file
@@ -0,0 +1,99 @@
|
||||
// Copyright 2023 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package remove
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/api/konfig"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kustomize/v5/commands/internal/kustfile"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
)
|
||||
|
||||
type removeConfigMapOptions struct {
|
||||
configMapNamesToRemove []string
|
||||
}
|
||||
|
||||
// newCmdRemoveConfigMap removes configMapGenerator(s) with the specified name(s).
|
||||
func newCmdRemoveConfigMap(fSys filesys.FileSystem) *cobra.Command {
|
||||
var o removeConfigMapOptions
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "configmap",
|
||||
Short: "Removes the specified configmap(s) from " +
|
||||
konfig.DefaultKustomizationFileName(),
|
||||
Long: "",
|
||||
Example: `
|
||||
remove configmap my-configmap
|
||||
`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
err := o.Validate(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return o.RunRemoveConfigMap(fSys)
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Validate validates removeConfigMap command.
|
||||
func (o *removeConfigMapOptions) Validate(args []string) error {
|
||||
switch {
|
||||
case len(args) == 0:
|
||||
return errors.New("at least one configmap name must be specified")
|
||||
case len(args) > 1:
|
||||
return fmt.Errorf("too many arguments: %s; to provide multiple configmaps to remove, please separate configmap names by commas", args)
|
||||
}
|
||||
|
||||
o.configMapNamesToRemove = strings.Split(args[0], ",")
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunRemoveConfigMap runs ConfigMap command (do real work).
|
||||
func (o *removeConfigMapOptions) RunRemoveConfigMap(fSys filesys.FileSystem) error {
|
||||
mf, err := kustfile.NewKustomizationFile(fSys)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read kustomization file: %w", err)
|
||||
}
|
||||
|
||||
m, err := mf.Read()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read kustomization file contents: %w", err)
|
||||
}
|
||||
|
||||
foundConfigMaps := make(map[string]struct{})
|
||||
|
||||
newConfigMaps := make([]types.ConfigMapArgs, 0, len(m.ConfigMapGenerator))
|
||||
for _, currentConfigMap := range m.ConfigMapGenerator {
|
||||
if kustfile.StringInSlice(currentConfigMap.Name, o.configMapNamesToRemove) {
|
||||
foundConfigMaps[currentConfigMap.Name] = struct{}{}
|
||||
continue
|
||||
}
|
||||
newConfigMaps = append(newConfigMaps, currentConfigMap)
|
||||
}
|
||||
|
||||
if len(foundConfigMaps) == 0 {
|
||||
return fmt.Errorf("no specified configmap(s) were found in the %s file",
|
||||
konfig.DefaultKustomizationFileName())
|
||||
}
|
||||
|
||||
for _, name := range o.configMapNamesToRemove {
|
||||
if _, found := foundConfigMaps[name]; !found {
|
||||
log.Printf("configmap %s doesn't exist in kustomization file", name)
|
||||
}
|
||||
}
|
||||
|
||||
m.ConfigMapGenerator = newConfigMaps
|
||||
err = mf.Write(m)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write kustomization file: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
116
kustomize/commands/edit/remove/removeconfigmap_test.go
Normal file
116
kustomize/commands/edit/remove/removeconfigmap_test.go
Normal file
@@ -0,0 +1,116 @@
|
||||
// Copyright 2023 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package remove //nolint:testpackage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
testutils_test "sigs.k8s.io/kustomize/kustomize/v5/commands/internal/testutils"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
)
|
||||
|
||||
func TestRemoveConfigMap(t *testing.T) {
|
||||
const configMapName01 = "example-configmap-01"
|
||||
const configMapName02 = "example-configmap-02"
|
||||
|
||||
tests := map[string]struct {
|
||||
input string
|
||||
args []string
|
||||
expectedOutput string
|
||||
expectedErr string
|
||||
}{
|
||||
"happy path": {
|
||||
input: fmt.Sprintf(`
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
configMapGenerator:
|
||||
- name: %s
|
||||
files:
|
||||
- application.properties
|
||||
`, configMapName01),
|
||||
args: []string{configMapName01},
|
||||
expectedOutput: `
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
`,
|
||||
},
|
||||
"multiple": {
|
||||
input: fmt.Sprintf(`
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
configMapGenerator:
|
||||
- name: %s
|
||||
files:
|
||||
- application.properties
|
||||
- name: %s
|
||||
files:
|
||||
- application.properties
|
||||
`, configMapName01, configMapName02),
|
||||
args: []string{
|
||||
fmt.Sprintf("%s,%s", configMapName01, configMapName02),
|
||||
},
|
||||
expectedOutput: `
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
`,
|
||||
},
|
||||
"miss": {
|
||||
input: fmt.Sprintf(`
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
configMapGenerator:
|
||||
- name: %s
|
||||
files:
|
||||
- application.properties
|
||||
`, configMapName01),
|
||||
args: []string{"foo"},
|
||||
expectedErr: "no specified configmap(s) were found",
|
||||
},
|
||||
"no configmap name specified": {
|
||||
args: []string{},
|
||||
expectedErr: "at least one configmap name must be specified",
|
||||
},
|
||||
"too many configmap names specified": {
|
||||
args: []string{"test1", "test2"},
|
||||
expectedErr: "too many arguments",
|
||||
},
|
||||
"one existing and one non-existing": {
|
||||
input: fmt.Sprintf(`
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
configMapGenerator:
|
||||
- name: %s
|
||||
files:
|
||||
- application.properties
|
||||
`, configMapName01),
|
||||
args: []string{fmt.Sprintf("%s,%s", configMapName01, "foo")},
|
||||
expectedOutput: `
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
fSys := filesys.MakeFsInMemory()
|
||||
testutils_test.WriteTestKustomizationWith(fSys, []byte(tc.input))
|
||||
cmd := newCmdRemoveConfigMap(fSys)
|
||||
err := cmd.RunE(cmd, tc.args)
|
||||
|
||||
if tc.expectedErr != "" {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tc.expectedErr)
|
||||
return
|
||||
}
|
||||
|
||||
require.NoError(t, err)
|
||||
content, err := testutils_test.ReadTestKustomization(fSys)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.expectedOutput, string(content))
|
||||
})
|
||||
}
|
||||
}
|
||||
99
kustomize/commands/edit/remove/removesecret.go
Normal file
99
kustomize/commands/edit/remove/removesecret.go
Normal file
@@ -0,0 +1,99 @@
|
||||
// Copyright 2023 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package remove
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/api/konfig"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kustomize/v5/commands/internal/kustfile"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
)
|
||||
|
||||
type removeSecretOptions struct {
|
||||
secretNamesToRemove []string
|
||||
}
|
||||
|
||||
// newCmdRemoveSecret removes secretGenerator(s) with the specified name(s).
|
||||
func newCmdRemoveSecret(fSys filesys.FileSystem) *cobra.Command {
|
||||
var o removeSecretOptions
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "secret",
|
||||
Short: "Removes the specified secret(s) from " +
|
||||
konfig.DefaultKustomizationFileName(),
|
||||
Long: "",
|
||||
Example: `
|
||||
remove secret my-secret
|
||||
`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
err := o.Validate(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return o.RunRemoveSecret(fSys)
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Validate validates removeSecret command.
|
||||
func (o *removeSecretOptions) Validate(args []string) error {
|
||||
switch {
|
||||
case len(args) == 0:
|
||||
return errors.New("at least one secret name must be specified")
|
||||
case len(args) > 1:
|
||||
return fmt.Errorf("too many arguments: %s; to provide multiple secrets to remove, please separate secret names by commas", args)
|
||||
}
|
||||
|
||||
o.secretNamesToRemove = strings.Split(args[0], ",")
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunRemoveSecret runs Secret command (do real work).
|
||||
func (o *removeSecretOptions) RunRemoveSecret(fSys filesys.FileSystem) error {
|
||||
mf, err := kustfile.NewKustomizationFile(fSys)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read kustomization file: %w", err)
|
||||
}
|
||||
|
||||
m, err := mf.Read()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read kustomization file contents: %w", err)
|
||||
}
|
||||
|
||||
foundSecrets := make(map[string]struct{})
|
||||
|
||||
newSecrets := make([]types.SecretArgs, 0, len(m.SecretGenerator))
|
||||
for _, currentSecret := range m.SecretGenerator {
|
||||
if kustfile.StringInSlice(currentSecret.Name, o.secretNamesToRemove) {
|
||||
foundSecrets[currentSecret.Name] = struct{}{}
|
||||
continue
|
||||
}
|
||||
newSecrets = append(newSecrets, currentSecret)
|
||||
}
|
||||
|
||||
if len(foundSecrets) == 0 {
|
||||
return fmt.Errorf("no specified secret(s) were found in the %s file",
|
||||
konfig.DefaultKustomizationFileName())
|
||||
}
|
||||
|
||||
for _, name := range o.secretNamesToRemove {
|
||||
if _, found := foundSecrets[name]; !found {
|
||||
log.Printf("secret %s doesn't exist in kustomization file", name)
|
||||
}
|
||||
}
|
||||
m.SecretGenerator = newSecrets
|
||||
|
||||
err = mf.Write(m)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write kustomization file: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
116
kustomize/commands/edit/remove/removesecret_test.go
Normal file
116
kustomize/commands/edit/remove/removesecret_test.go
Normal file
@@ -0,0 +1,116 @@
|
||||
// Copyright 2023 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package remove //nolint:testpackage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
testutils_test "sigs.k8s.io/kustomize/kustomize/v5/commands/internal/testutils"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
)
|
||||
|
||||
func TestRemoveSecret(t *testing.T) {
|
||||
const secretName01 = "example-secret-01"
|
||||
const secretName02 = "example-secret-02"
|
||||
|
||||
tests := map[string]struct {
|
||||
input string
|
||||
args []string
|
||||
expectedOutput string
|
||||
expectedErr string
|
||||
}{
|
||||
"happy path": {
|
||||
input: fmt.Sprintf(`
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
secretGenerator:
|
||||
- name: %s
|
||||
files:
|
||||
- longsecret.txt
|
||||
`, secretName01),
|
||||
args: []string{secretName01},
|
||||
expectedOutput: `
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
`,
|
||||
},
|
||||
"multiple": {
|
||||
input: fmt.Sprintf(`
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
secretGenerator:
|
||||
- name: %s
|
||||
files:
|
||||
- longsecret.txt
|
||||
- name: %s
|
||||
files:
|
||||
- longsecret.txt
|
||||
`, secretName01, secretName02),
|
||||
args: []string{
|
||||
fmt.Sprintf("%s,%s", secretName01, secretName02),
|
||||
},
|
||||
expectedOutput: `
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
`,
|
||||
},
|
||||
"miss": {
|
||||
input: fmt.Sprintf(`
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
secretGenerator:
|
||||
- name: %s
|
||||
files:
|
||||
- longsecret.txt
|
||||
`, secretName01),
|
||||
args: []string{"foo"},
|
||||
expectedErr: "no specified secret(s) were found",
|
||||
},
|
||||
"no secret name specified": {
|
||||
args: []string{},
|
||||
expectedErr: "at least one secret name must be specified",
|
||||
},
|
||||
"too many secret names specified": {
|
||||
args: []string{"test1", "test2"},
|
||||
expectedErr: "too many arguments",
|
||||
},
|
||||
"one existing and one non-existing": {
|
||||
input: fmt.Sprintf(`
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
secretGenerator:
|
||||
- name: %s
|
||||
files:
|
||||
- application.properties
|
||||
`, secretName01),
|
||||
args: []string{fmt.Sprintf("%s,%s", secretName01, "foo")},
|
||||
expectedOutput: `
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
fSys := filesys.MakeFsInMemory()
|
||||
testutils_test.WriteTestKustomizationWith(fSys, []byte(tc.input))
|
||||
cmd := newCmdRemoveSecret(fSys)
|
||||
err := cmd.RunE(cmd, tc.args)
|
||||
|
||||
if tc.expectedErr != "" {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tc.expectedErr)
|
||||
return
|
||||
}
|
||||
|
||||
require.NoError(t, err)
|
||||
content, err := testutils_test.ReadTestKustomization(fSys)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.expectedOutput, string(content))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/xlab/treeprint v1.2.0 // indirect
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
|
||||
golang.org/x/sys v0.8.0 // indirect
|
||||
golang.org/x/sys v0.12.0 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
gopkg.in/evanphx/json-patch.v5 v5.6.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
|
||||
@@ -67,8 +67,8 @@ github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc=
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=
|
||||
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: "Kustomization File"
|
||||
linkTitle: "Kustomization File"
|
||||
weight: 1
|
||||
date: 2023-07-28
|
||||
date: 2023-09-17
|
||||
description: >
|
||||
The Kustomization file is the entry point for Kustomize execution.
|
||||
---
|
||||
---
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "bases"
|
||||
linkTitle: "bases"
|
||||
type: docs
|
||||
weight: 1
|
||||
description: >
|
||||
Add resources from a kustomization dir.
|
||||
---
|
||||
|
||||
{{% pageinfo color="warning" %}}
|
||||
The `bases` field was deprecated in v2.1.0. This field will never be removed from the
|
||||
kustomize.config.k8s.io/v1beta1 Kustomization API, but it will not be included
|
||||
in the kustomize.config.k8s.io/v1 Kustomization API. When Kustomization v1 is available,
|
||||
we will announce the deprecation of the v1beta1 version. There will be at least
|
||||
two releases between deprecation and removal of Kustomization v1beta1 support from the
|
||||
kustomize CLI, and removal itself will happen in a future major version bump.
|
||||
|
||||
You can run `kustomize edit fix` to automatically convert `bases` to `resources`.
|
||||
{{% /pageinfo %}}
|
||||
|
||||
Move entries into the [resources](/docs/reference/api/kustomization-file/resources)
|
||||
field. This allows bases - which are still a
|
||||
[central concept](/docs/concepts/bases) - to be
|
||||
ordered relative to other input resources.
|
||||
@@ -0,0 +1,316 @@
|
||||
---
|
||||
title: "buildMetadata"
|
||||
linkTitle: "buildMetadata"
|
||||
type: docs
|
||||
weight: 2
|
||||
description: >
|
||||
Specify options for including information about the build in annotations or labels.
|
||||
---
|
||||
|
||||
The `buildMetadata` field is a list of strings. The strings can be one of three builtin
|
||||
options that add some metadata to each resource about how the resource was built.
|
||||
|
||||
These options are:
|
||||
|
||||
- `managedByLabel`
|
||||
- `originAnnotations`
|
||||
- `transformerAnnotations`
|
||||
|
||||
It is possible to set one or all of these options in the kustomization file:
|
||||
|
||||
```yaml
|
||||
buildMetadata: [managedByLabel, originAnnotations, transformerAnnotations]
|
||||
```
|
||||
|
||||
### Managed By Label
|
||||
To mark the resource as having been managed by kustomize, you can specify the `managedByLabel`
|
||||
option in the `buildMetadata` field of the kustomization:
|
||||
|
||||
```yaml
|
||||
buildMetadata: [managedByLabel]
|
||||
```
|
||||
|
||||
This will add the label `app.kubernetes.io/managed-by` to each resource with the version of kustomize
|
||||
that has built it. For example, given the following input:
|
||||
|
||||
kustomization.yaml
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- service.yaml
|
||||
buildMetadata: [managedByLabel]
|
||||
```
|
||||
|
||||
service.yaml
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: myService
|
||||
spec:
|
||||
ports:
|
||||
- port: 7002
|
||||
```
|
||||
|
||||
`kustomize build` will produce a resource with an output like the following:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/managed-by: kustomize-v4.4.1
|
||||
name: myService
|
||||
spec:
|
||||
ports:
|
||||
- port: 7002
|
||||
```
|
||||
|
||||
|
||||
### Origin Annotation
|
||||
To annotate resources with information about their origin, you can specify the `originAnnotations`:
|
||||
|
||||
```yaml
|
||||
buildMetadata: [originAnnotations]
|
||||
```
|
||||
|
||||
When this option is set, generated resources will receive an annotation with key `config.kubernetes.io/origin`,
|
||||
containing data about the generator that produced it. If the resource is from the `resources` field, this annotation
|
||||
contains data about the file it originated from.
|
||||
|
||||
The possible fields of these annotations are:
|
||||
|
||||
- `path`: The path to a resource file itself
|
||||
- `ref`: If from a remote file or generator, the ref of the repo URL.
|
||||
- `repo`: If from a remote file or generator, the repo source
|
||||
- `configuredIn`: If a generated resource, the path to the generator config. If a generator is invoked via a field
|
||||
in the kustomization file, this would point to the kustomization file itself.
|
||||
- `configuredBy`: If a generated resource, the ObjectReference of the generator config.
|
||||
|
||||
|
||||
All local file paths are relative to the top-level kustomization, i.e. the kustomization file in the directory upon
|
||||
which `kustomize build` was invoked. For example, if someone were to run `kustomize build foo`, all file paths
|
||||
in the annotation output would be relative to`foo/kustomization.yaml`. All remote file paths are relative to the root of the
|
||||
remote repository. Any fields that are not applicable would be omitted from the final output.
|
||||
|
||||
Here is an example of what this would look like:
|
||||
```yaml
|
||||
config.kubernetes.io/origin: |
|
||||
path: path.yaml
|
||||
ref: v0.0.0
|
||||
repo: http://github.com/examplerepo
|
||||
configuredIn: path/to/generatorconfig
|
||||
configuredBy:
|
||||
kind: Generator
|
||||
apiVersion: builtin
|
||||
name: foo
|
||||
namespace: default
|
||||
```
|
||||
|
||||
#### Examples
|
||||
|
||||
##### Resource declared from `resources`
|
||||
A kustomization such as the following:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- deployment.yaml
|
||||
|
||||
buildMetadata: [originAnnotations]
|
||||
```
|
||||
|
||||
would produce a resource with an annotation like the following:
|
||||
|
||||
```yaml
|
||||
config.kubernetes.io/origin: |
|
||||
path: deployment.yaml
|
||||
```
|
||||
|
||||
##### Local custom generator
|
||||
A kustomization such as the following:
|
||||
|
||||
```yaml
|
||||
generators:
|
||||
- generator.yaml
|
||||
|
||||
buildMetadata: [originAnnotations]
|
||||
```
|
||||
|
||||
would produce a resource with an annotation like the following:
|
||||
|
||||
```yaml
|
||||
config.kubernetes.io/origin: |
|
||||
configuredIn: generator.yaml
|
||||
configuredBy:
|
||||
kind: MyGenerator
|
||||
apiVersion: v1
|
||||
name: generator
|
||||
```
|
||||
|
||||
##### Remote builtin generator
|
||||
We have a top-level kustomization such as the following:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- github.com/examplerepo/?ref=v1.0.6
|
||||
|
||||
buildMetadata: [originAnnotations]
|
||||
```
|
||||
|
||||
which uses `github.com/examplerepo/?ref=v1.0.6` as a remote base. This remote base has the following kustomization
|
||||
defined in `github.com/examplerepo/kustomization.yaml`:
|
||||
|
||||
```yaml
|
||||
configMapGenerator:
|
||||
- name: my-java-server-env-vars
|
||||
literals:
|
||||
- JAVA_HOME=/opt/java/jdk
|
||||
- JAVA_TOOL_OPTIONS=-agentlib:hprof
|
||||
```
|
||||
|
||||
Running `kustomize build` on the top-level kustomization would produce the following output:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
data:
|
||||
JAVA_HOME: /opt/java/jdk
|
||||
JAVA_TOOL_OPTIONS: -agentlib:hprof
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: my-java-server-env-vars-44k658k8gk
|
||||
annotations:
|
||||
config.kubernetes.io/origin: |
|
||||
ref: v1.0.6
|
||||
repo: github.com/examplerepo
|
||||
configuredIn: kustomization.yaml
|
||||
configuredBy:
|
||||
kind: ConfigMapGenerator
|
||||
apiVersion: builtin
|
||||
```
|
||||
|
||||
### Transformer Annotations [Alpha]
|
||||
|
||||
To annotate resources with information about the transformers that have acted on them, you can add the
|
||||
`transformerAnnotations` option to the `buildMetadata` field of the kustomization:
|
||||
|
||||
```yaml
|
||||
buildMetadata: [transformerAnnotations]
|
||||
```
|
||||
|
||||
When the `transformerAnnotations` option is set, kustomize will add annotations with information about what transformers
|
||||
have acted on each resource. Transformers can be invoked either through various fields in the kustomization file
|
||||
(e.g. the `replacements` field will invoke the ReplacementTransformer), or through the `transformers` field.
|
||||
|
||||
The annotation key for transformer annotations will be `config.kubernetes.io/transformations`, which will contain a list of
|
||||
transformer data. The possible fields in each item in this list is identical to the possible fields in `config.kubernetes.io/origin`,
|
||||
except that the transformer annotation does not have a `path` field:
|
||||
|
||||
The possible fields of these annotations are:
|
||||
|
||||
- `path`: The path to a resource file itself
|
||||
- `ref`: If from a remote file or generator, the ref of the repo URL.
|
||||
- `repo`: If from a remote file or generator, the repo source
|
||||
- `configuredIn`: The path to the transformer config. If a transformer is invoked via a field
|
||||
in the kustomization file, this would point to the kustomization file itself.
|
||||
- `configuredBy`: The ObjectReference of the transformer config.
|
||||
|
||||
All local file paths are relative to the top-level kustomization, i.e. the kustomization file in the directory upon
|
||||
which `kustomize build` was invoked. For example, if someone were to run `kustomize build foo`, all file paths
|
||||
in the annotation output would be relative to`foo/kustomization.yaml`. All remote file paths are relative to the root of the
|
||||
remote repository. Any fields that are not applicable would be omitted from the final output.
|
||||
|
||||
Here is an example of what this would look like:
|
||||
```yaml
|
||||
config.kubernetes.io/transformations: |
|
||||
- ref: v0.0.0
|
||||
repo: http://github.com/examplerepo
|
||||
configuredIn: path/to/transformerconfig
|
||||
configuredBy:
|
||||
kind: Transformer
|
||||
apiVersion: builtin
|
||||
name: foo
|
||||
namespace: default
|
||||
```
|
||||
|
||||
|
||||
While this field is in alpha, it will receive the `alpha` prefix, so you will see the annotation key
|
||||
`alpha.config.kubernetes.io/transformations` instead. We are not guaranteeing that the annotation content will be stable during
|
||||
alpha, and reserve the right to make changes as we evolve the feature.
|
||||
|
||||
|
||||
#### Examples
|
||||
|
||||
#### Local custom transformer
|
||||
A kustomization such as the following:
|
||||
|
||||
```yaml
|
||||
transformers:
|
||||
- transformer.yaml
|
||||
|
||||
buildMetadata: [transformerAnnotations]
|
||||
|
||||
```
|
||||
|
||||
would produce a resource with an annotation like the following:
|
||||
|
||||
```yaml
|
||||
config.kubernetes.io/transformations: |
|
||||
- configuredIn: transformer.yaml
|
||||
configuredBy:
|
||||
kind: MyTransformer
|
||||
apiVersion: v1
|
||||
name: transformer
|
||||
```
|
||||
|
||||
##### Remote builtin transformer + local builtin transformer
|
||||
We have a top-level kustomization such as the following:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- github.com/examplerepo/?ref=v1.0.6
|
||||
|
||||
buildMetadata: [transformerAnnotations]
|
||||
|
||||
namespace: my-ns
|
||||
```
|
||||
|
||||
which uses `github.com/examplerepo/?ref=v1.0.6` as a remote base. This remote base has the following kustomization
|
||||
defined in `github.com/examplerepo/kustomization.yaml`:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- deployment.yaml
|
||||
|
||||
namePrefix: pre-
|
||||
```
|
||||
|
||||
`deployment.yaml` contains the following:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy
|
||||
```
|
||||
|
||||
Running `kustomize build` on the top-level kustomization would produce the following output:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: pre-deploy
|
||||
annotations:
|
||||
config.kubernetes.io/transformations: |
|
||||
- ref: v1.0.6
|
||||
repo: github.com/examplerepo
|
||||
configuredIn: kustomization.yaml
|
||||
configuredBy:
|
||||
kind: PrefixSuffixTransformer
|
||||
apiVersion: builtin
|
||||
- configuredIn: kustomization.yaml
|
||||
configuredBy:
|
||||
kind: NamespaceTransformer
|
||||
apiVersion: builtin
|
||||
```
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
title: "commonAnnotations"
|
||||
linkTitle: "commonAnnotations"
|
||||
type: docs
|
||||
weight: 3
|
||||
description: >
|
||||
Add annotations to add all resources.
|
||||
---
|
||||
|
||||
Add annotations to all resources. If the annotation key already is present on the resource,
|
||||
the value will be overridden.
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
commonAnnotations:
|
||||
oncallPager: 800-555-1212
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
### File Input
|
||||
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
commonAnnotations:
|
||||
oncallPager: 800-555-1212
|
||||
|
||||
resources:
|
||||
- deploy.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# deploy.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: example
|
||||
spec:
|
||||
...
|
||||
```
|
||||
|
||||
### Build Output
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: example
|
||||
annotations:
|
||||
oncallPager: 800-555-1212
|
||||
spec:
|
||||
...
|
||||
```
|
||||
@@ -0,0 +1,107 @@
|
||||
---
|
||||
title: "commonLabels"
|
||||
linkTitle: "commonLabels"
|
||||
type: docs
|
||||
weight: 4
|
||||
description: >
|
||||
Add labels and selectors to add all resources.
|
||||
---
|
||||
|
||||
[labels]: /docs/reference/api/kustomization-file/labels/
|
||||
|
||||
Add labels and selectors to all resources. If the label key already is present on the resource,
|
||||
the value will be overridden.
|
||||
|
||||
An alternative to this field is the [labels] field, which allows adding labels without also automatically
|
||||
injecting corresponding selectors.
|
||||
|
||||
{{% pageinfo color="warning" %}}
|
||||
Selectors for resources such as Deployments and Services shouldn't be changed once the
|
||||
resource has been applied to a cluster.
|
||||
|
||||
Changing commonLabels to live resources could result in failures.
|
||||
{{% /pageinfo %}}
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
commonLabels:
|
||||
someName: someValue
|
||||
owner: alice
|
||||
app: bingo
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
### File Input
|
||||
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
commonLabels:
|
||||
someName: someValue
|
||||
owner: alice
|
||||
app: bingo
|
||||
|
||||
resources:
|
||||
- deploy.yaml
|
||||
- service.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# deploy.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: example
|
||||
```
|
||||
|
||||
```yaml
|
||||
# service.yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: example
|
||||
```
|
||||
|
||||
### Build Output
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
app: bingo
|
||||
owner: alice
|
||||
someName: someValue
|
||||
name: example
|
||||
spec:
|
||||
selector:
|
||||
app: bingo
|
||||
owner: alice
|
||||
someName: someValue
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app: bingo
|
||||
owner: alice
|
||||
someName: someValue
|
||||
name: example
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: bingo
|
||||
owner: alice
|
||||
someName: someValue
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: bingo
|
||||
owner: alice
|
||||
someName: someValue
|
||||
```
|
||||
@@ -0,0 +1,385 @@
|
||||
---
|
||||
title: "Components"
|
||||
linkTitle: "Components"
|
||||
type: docs
|
||||
weight: 5
|
||||
description: >
|
||||
Compose kustomizations.
|
||||
---
|
||||
|
||||
As of ``v3.7.0`` Kustomize supports a special type of kustomization that allows
|
||||
one to define reusable pieces of configuration logic that can be included from
|
||||
multiple overlays.
|
||||
|
||||
Components come in handy when dealing with applications that support multiple
|
||||
optional features and you wish to enable only a subset of them in different
|
||||
overlays, i.e., different features for different environments or audiences.
|
||||
|
||||
For more details regarding this feature you can read the
|
||||
[Kustomize Components KEP](https://github.com/kubernetes/enhancements/tree/master/keps/sig-cli/1802-kustomize-components)
|
||||
and the [components concept](/docs/concepts/components/) page.
|
||||
|
||||
## Use case
|
||||
|
||||
Suppose you've written a very simple Web application:
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: example
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: example
|
||||
image: example:1.0
|
||||
```
|
||||
|
||||
You want to deploy a **community** edition of this application as SaaS, so you
|
||||
add support for persistence (e.g. an external database), and bot detection
|
||||
(e.g. Google reCAPTCHA).
|
||||
|
||||
You've now attracted **enterprise** customers who want to deploy it
|
||||
on-premises, so you add LDAP support, and disable Google reCAPTCHA. At the same
|
||||
time, the **devs** need to be able to test parts of the application, so they
|
||||
want to deploy it with some features enabled and others not.
|
||||
|
||||
Here's a matrix with the deployments of this application and the features
|
||||
enabled for each one:
|
||||
|
||||
| | External DB | LDAP | reCAPTCHA |
|
||||
|------------|:------------------:|:------------------:|:------------------:|
|
||||
| Community | ✔️ | | ✔️ |
|
||||
| Enterprise | ✔️ | ✔️ | |
|
||||
| Dev | ✅ | ✅ | ✅ |
|
||||
|
||||
(✔️ enabled, ✅: optional)
|
||||
|
||||
So, you want to make it easy to deploy your application in any of the above
|
||||
three environments. Here's how you can do this with Kustomize components: each
|
||||
opt-in feature gets packaged as a component, so that it can be referred to from
|
||||
multiple higher-level overlays.
|
||||
|
||||
First, define a place to work:
|
||||
|
||||
```shell
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
Define a common **base** that has a `Deployment` and a simple `ConfigMap`, that
|
||||
is mounted on the application's container.
|
||||
|
||||
```bash
|
||||
BASE=$DEMO_HOME/base
|
||||
mkdir $BASE
|
||||
```
|
||||
|
||||
```bash
|
||||
# $BASE/kustomization.yaml
|
||||
resources:
|
||||
- deployment.yaml
|
||||
|
||||
configMapGenerator:
|
||||
- name: conf
|
||||
literals:
|
||||
- main.conf=|
|
||||
color=cornflower_blue
|
||||
log_level=info
|
||||
```
|
||||
|
||||
```bash
|
||||
# $BASE/deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: example
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: example
|
||||
image: example:1.0
|
||||
volumeMounts:
|
||||
- name: conf
|
||||
mountPath: /etc/config
|
||||
volumes:
|
||||
- name: conf
|
||||
configMap:
|
||||
name: conf
|
||||
```
|
||||
|
||||
Define an `external_db` component, using `kind: Component`, that creates a
|
||||
`Secret` for the DB password and a new entry in the `ConfigMap`:
|
||||
|
||||
```shell
|
||||
EXT_DB=$DEMO_HOME/components/external_db
|
||||
mkdir -p $EXT_DB
|
||||
```
|
||||
|
||||
```bash
|
||||
# $EXT_DB/kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1alpha1 # <-- Component notation
|
||||
kind: Component
|
||||
|
||||
secretGenerator:
|
||||
- name: dbpass
|
||||
files:
|
||||
- dbpass.txt
|
||||
|
||||
patchesStrategicMerge:
|
||||
- configmap.yaml
|
||||
|
||||
patchesJson6902:
|
||||
- target:
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: example
|
||||
path: deployment.yaml
|
||||
```
|
||||
|
||||
```bash
|
||||
# $EXT_DB/deployment.yaml
|
||||
- op: add
|
||||
path: /spec/template/spec/volumes/0
|
||||
value:
|
||||
name: dbpass
|
||||
secret:
|
||||
secretName: dbpass
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/volumeMounts/0
|
||||
value:
|
||||
mountPath: /var/run/secrets/db/
|
||||
name: dbpass
|
||||
```
|
||||
|
||||
```bash
|
||||
# $EXT_DB/configmap.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: conf
|
||||
data:
|
||||
db.conf: |
|
||||
endpoint=127.0.0.1:1234
|
||||
name=app
|
||||
user=admin
|
||||
pass=/var/run/secrets/db/dbpass.txt
|
||||
```
|
||||
|
||||
Define an `ldap` component, that creates a `Secret` for the LDAP password
|
||||
and a new entry in the `ConfigMap`:
|
||||
|
||||
```shell
|
||||
LDAP=$DEMO_HOME/components/ldap
|
||||
mkdir -p $LDAP
|
||||
```
|
||||
|
||||
```bash
|
||||
# $LDAP/kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1alpha1
|
||||
kind: Component
|
||||
|
||||
secretGenerator:
|
||||
- name: ldappass
|
||||
files:
|
||||
- ldappass.txt
|
||||
|
||||
patchesStrategicMerge:
|
||||
- configmap.yaml
|
||||
|
||||
patchesJson6902:
|
||||
- target:
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: example
|
||||
path: deployment.yaml
|
||||
```
|
||||
|
||||
```bash
|
||||
# $LDAP/deployment.yaml
|
||||
- op: add
|
||||
path: /spec/template/spec/volumes/0
|
||||
value:
|
||||
name: ldappass
|
||||
secret:
|
||||
secretName: ldappass
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/volumeMounts/0
|
||||
value:
|
||||
mountPath: /var/run/secrets/ldap/
|
||||
name: ldappass
|
||||
```
|
||||
|
||||
```bash
|
||||
# $LDAP/configmap.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: conf
|
||||
data:
|
||||
ldap.conf: |
|
||||
endpoint=ldap://ldap.example.com
|
||||
bindDN=cn=admin,dc=example,dc=com
|
||||
pass=/var/run/secrets/ldap/ldappass.txt
|
||||
```
|
||||
|
||||
Define a `recaptcha` component, that creates a `Secret` for the reCAPTCHA
|
||||
site/secret keys and a new entry in the `ConfigMap`:
|
||||
|
||||
```shell
|
||||
RECAPTCHA=$DEMO_HOME/components/recaptcha
|
||||
mkdir -p $RECAPTCHA
|
||||
```
|
||||
|
||||
```bash
|
||||
# $RECAPTCHA/kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1alpha1
|
||||
kind: Component
|
||||
|
||||
secretGenerator:
|
||||
- name: recaptcha
|
||||
files:
|
||||
- site_key.txt
|
||||
- secret_key.txt
|
||||
|
||||
# Updating the ConfigMap works with generators as well.
|
||||
configMapGenerator:
|
||||
- name: conf
|
||||
behavior: merge
|
||||
literals:
|
||||
- recaptcha.conf=|
|
||||
enabled=true
|
||||
site_key=/var/run/secrets/recaptcha/site_key.txt
|
||||
secret_key=/var/run/secrets/recaptcha/secret_key.txt
|
||||
|
||||
patchesJson6902:
|
||||
- target:
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: example
|
||||
path: deployment.yaml
|
||||
```
|
||||
|
||||
```bash
|
||||
# $RECAPTCHA/deployment.yaml
|
||||
- op: add
|
||||
path: /spec/template/spec/volumes/0
|
||||
value:
|
||||
name: recaptcha
|
||||
secret:
|
||||
secretName: recaptcha
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/volumeMounts/0
|
||||
value:
|
||||
mountPath: /var/run/secrets/recaptcha/
|
||||
name: recaptcha
|
||||
```
|
||||
|
||||
Define a `community` variant, that bundles the external DB and reCAPTCHA
|
||||
components:
|
||||
|
||||
```shell
|
||||
COMMUNITY=$DEMO_HOME/overlays/community
|
||||
mkdir -p $COMMUNITY
|
||||
```
|
||||
|
||||
```bash
|
||||
|
||||
# $COMMUNITY/kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
|
||||
components:
|
||||
- ../../components/external_db
|
||||
- ../../components/recaptcha
|
||||
```
|
||||
|
||||
Define an `enterprise` overlay, that bundles the external DB and LDAP
|
||||
components:
|
||||
|
||||
```shell
|
||||
ENTERPRISE=$DEMO_HOME/overlays/enterprise
|
||||
mkdir -p $ENTERPRISE
|
||||
```
|
||||
|
||||
```bash
|
||||
# $ENTERPRISE/kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
|
||||
components:
|
||||
- ../../components/external_db
|
||||
- ../../components/ldap
|
||||
```
|
||||
|
||||
Define a `dev` overlay, that points to all the components and has LDAP
|
||||
disabled:
|
||||
|
||||
```shell
|
||||
DEV=$DEMO_HOME/overlays/dev
|
||||
mkdir -p $DEV
|
||||
```
|
||||
|
||||
```bash
|
||||
# $DEV/kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
|
||||
components:
|
||||
- ../../components/external_db
|
||||
#- ../../components/ldap
|
||||
- ../../components/recaptcha
|
||||
```
|
||||
|
||||
Now, the workspace has the following directories:
|
||||
|
||||
```shell
|
||||
├── base
|
||||
│ ├── deployment.yaml
|
||||
│ └── kustomization.yaml
|
||||
├── components
|
||||
│ ├── external_db
|
||||
│ │ ├── configmap.yaml
|
||||
│ │ ├── dbpass.txt
|
||||
│ │ ├── deployment.yaml
|
||||
│ │ └── kustomization.yaml
|
||||
│ ├── ldap
|
||||
│ │ ├── configmap.yaml
|
||||
│ │ ├── deployment.yaml
|
||||
│ │ ├── kustomization.yaml
|
||||
│ │ └── ldappass.txt
|
||||
│ └── recaptcha
|
||||
│ ├── deployment.yaml
|
||||
│ ├── kustomization.yaml
|
||||
│ ├── secret_key.txt
|
||||
│ └── site_key.txt
|
||||
└── overlays
|
||||
├── community
|
||||
│ └── kustomization.yaml
|
||||
├── dev
|
||||
│ └── kustomization.yaml
|
||||
└── enterprise
|
||||
└── kustomization.yaml
|
||||
```
|
||||
|
||||
With this structure, you can generate the YAML manifests for each deployment
|
||||
using `kustomize build`:
|
||||
|
||||
```shell
|
||||
kustomize build overlays/community
|
||||
kustomize build overlays/enterprise
|
||||
kustomize build overlays/dev
|
||||
```
|
||||
@@ -0,0 +1,359 @@
|
||||
---
|
||||
title: "configMapGenerator"
|
||||
linkTitle: "configMapGenerator"
|
||||
type: docs
|
||||
weight: 6
|
||||
description: >
|
||||
Generate ConfigMap resources.
|
||||
---
|
||||
|
||||
Each entry in this list results in the creation of
|
||||
one ConfigMap resource (it's a generator of n maps).
|
||||
|
||||
The example below creates four ConfigMaps:
|
||||
|
||||
- first, with the names and contents of the given files
|
||||
- second, with key/value as data using key/value pairs from files
|
||||
- third, also with key/value as data, directly specified using `literals`
|
||||
- and a fourth, which sets an annotation and label via `options` for that single ConfigMap
|
||||
|
||||
Each configMapGenerator item accepts a parameter of
|
||||
`behavior: [create|replace|merge]`.
|
||||
This allows an overlay to modify or
|
||||
replace an existing configMap from the parent.
|
||||
|
||||
Also, each entry has an `options` field, that has the
|
||||
same subfields as the kustomization file's `generatorOptions` field.
|
||||
|
||||
This `options` field allows one to add labels and/or
|
||||
annotations to the generated instance, or to individually
|
||||
disable the name suffix hash for that instance.
|
||||
Labels and annotations added here will not be overwritten
|
||||
by the global options associated with the kustomization
|
||||
file `generatorOptions` field. However, due to how
|
||||
booleans behave, if the global `generatorOptions` field
|
||||
specifies `disableNameSuffixHash: true`, this will
|
||||
trump any attempt to locally override it.
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
# These labels are added to all configmaps and secrets.
|
||||
generatorOptions:
|
||||
labels:
|
||||
fruit: apple
|
||||
|
||||
configMapGenerator:
|
||||
- name: my-java-server-props
|
||||
behavior: merge
|
||||
files:
|
||||
- application.properties
|
||||
- more.properties
|
||||
- name: my-java-server-env-file-vars
|
||||
envs:
|
||||
- my-server-env.properties
|
||||
- more-server-props.env
|
||||
- name: my-java-server-env-vars
|
||||
literals:
|
||||
- JAVA_HOME=/opt/java/jdk
|
||||
- JAVA_TOOL_OPTIONS=-agentlib:hprof
|
||||
options:
|
||||
disableNameSuffixHash: true
|
||||
labels:
|
||||
pet: dog
|
||||
- name: dashboards
|
||||
files:
|
||||
- mydashboard.json
|
||||
options:
|
||||
annotations:
|
||||
dashboard: "1"
|
||||
labels:
|
||||
app.kubernetes.io/name: "app1"
|
||||
```
|
||||
|
||||
It is also possible to
|
||||
[define a key](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#define-the-key-to-use-when-creating-a-configmap-from-a-file)
|
||||
to set a name different than the filename.
|
||||
|
||||
The example below creates a ConfigMap
|
||||
with the name of file as `myFileName.ini`
|
||||
while the _actual_ filename from which the
|
||||
configmap is created is `whatever.ini`.
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
configMapGenerator:
|
||||
- name: app-whatever
|
||||
files:
|
||||
- myFileName.ini=whatever.ini
|
||||
```
|
||||
|
||||
## ConfigMap `from File`
|
||||
|
||||
ConfigMap Resources may be generated from files - such as a java `.properties` file. To generate a ConfigMap
|
||||
Resource for a file, add an entry to `configMapGenerator` with the filename.
|
||||
|
||||
**Example:** Generate a ConfigMap with a data item containing the contents of a file.
|
||||
|
||||
The ConfigMaps will have data values populated from the file contents. The contents of each file will
|
||||
appear as a single data item in the ConfigMap keyed by the filename.
|
||||
|
||||
The example illustrates how you can create ConfigMaps from File using Generators.
|
||||
|
||||
### File Input
|
||||
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
configMapGenerator:
|
||||
- name: my-application-properties
|
||||
files:
|
||||
- application.properties
|
||||
|
||||
```
|
||||
|
||||
```yaml
|
||||
# application.properties
|
||||
FOO=Bar
|
||||
```
|
||||
|
||||
### Build Output
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
data:
|
||||
application.properties: |-
|
||||
FOO=Bar
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: my-application-properties-f7mm6mhf59
|
||||
```
|
||||
|
||||
## ConfigMap `from Literals`
|
||||
|
||||
ConfigMap Resources may be generated from literal key-value pairs - such as `JAVA_HOME=/opt/java/jdk`.
|
||||
To generate a ConfigMap Resource from literal key-value pairs, add an entry to `configMapGenerator` with a
|
||||
list of `literals`.
|
||||
|
||||
{{< alert color="success" title="Literal Syntax" >}}
|
||||
- The key/value are separated by a `=` sign (left side is the key)
|
||||
- The value of each literal will appear as a data item in the ConfigMap keyed by its key.
|
||||
{{< /alert >}}
|
||||
|
||||
**Example:** Create a ConfigMap with 2 data items generated from literals.
|
||||
|
||||
The example illustrates how you can create ConfigMaps from Literals using Generators.
|
||||
|
||||
### File Input
|
||||
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
configMapGenerator:
|
||||
- name: my-java-server-env-vars
|
||||
literals:
|
||||
- JAVA_HOME=/opt/java/jdk
|
||||
- JAVA_TOOL_OPTIONS=-agentlib:hprof
|
||||
|
||||
```
|
||||
|
||||
### Build Output
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
data:
|
||||
JAVA_HOME: /opt/java/jdk
|
||||
JAVA_TOOL_OPTIONS: -agentlib:hprof
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: my-java-server-env-vars-44k658k8gk
|
||||
```
|
||||
|
||||
## ConfigMap `from env file`
|
||||
|
||||
ConfigMap Resources may be generated from key-value pairs much the same as using the literals option
|
||||
but taking the key-value pairs from an environment file. These generally end in `.env`.
|
||||
To generate a ConfigMap Resource from an environment file, add an entry to `configMapGenerator` with a
|
||||
single `envs` entry, e.g. `envs: [ 'config.env' ]`.
|
||||
|
||||
{{< alert color="success" title="Environment File Syntax" >}}
|
||||
- The key/value pairs inside of the environment file are separated by a `=` sign (left side is the key)
|
||||
- The value of each line will appear as a data item in the ConfigMap keyed by its key.
|
||||
- Pairs may span a single line only.
|
||||
{{< /alert >}}
|
||||
|
||||
**Example:** Create a ConfigMap with 3 data items generated from an environment file.
|
||||
|
||||
### File Input
|
||||
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
configMapGenerator:
|
||||
- name: tracing-options
|
||||
envs:
|
||||
- tracing.env
|
||||
```
|
||||
|
||||
```bash
|
||||
# tracing.env
|
||||
ENABLE_TRACING=true
|
||||
SAMPLER_TYPE=probabilistic
|
||||
SAMPLER_PARAMETERS=0.1
|
||||
```
|
||||
|
||||
### Build Output
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
# The name has had a suffix applied
|
||||
name: tracing-options-6bh8gkdf7k
|
||||
# The data has been populated from each literal pair
|
||||
data:
|
||||
ENABLE_TRACING: "true"
|
||||
SAMPLER_TYPE: "probabilistic"
|
||||
SAMPLER_PARAMETERS: "0.1"
|
||||
```
|
||||
|
||||
## Overriding Base ConfigMap Values
|
||||
|
||||
ConfigMap values from bases may be overridden by adding another generator for the ConfigMap
|
||||
in the overlay and specifying the `behavior` field. `behavior` may be
|
||||
one of:
|
||||
* `create` (default value): used to create a new ConfigMap. A name conflict error will be thrown if a ConfigMap with the same name and namespace already exists.
|
||||
* `replace`: replace an existing ConfigMap from the base.
|
||||
* `merge`: add or update the values in an existing ConfigMap from the base.
|
||||
|
||||
When updating an existing ConfigMap with the `merge` or `replace` strategies, you must ensure that both the name and namespace match the ConfigMap you're targeting. For example, if the namespace is unspecified in the base, you should not specify it in the overlay. Conversely, if it is specified in the base, you must specify it in the overlay as well. This is true even if the overlay Kustomization includes a namespace, because configMapGenerator runs before the namespace transformer.
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: my-new-namespace
|
||||
|
||||
resources:
|
||||
- ../base
|
||||
|
||||
configMapGenerator:
|
||||
- name: existing-name
|
||||
namespace: existing-ns # needs to match target ConfigMap from base
|
||||
behavior: replace
|
||||
literals:
|
||||
- ENV=dev
|
||||
```
|
||||
|
||||
{{< alert color="warning" title="Name suffixing with overlay configMapGenerator" >}}
|
||||
When using configMapGenerator to override values of an existing ConfigMap, the overlay configMapGenerator does not cause suffixing of the existing ConfigMap's name to occur. To take advantage of name suffixing, use configMapGenerator in the base, and the overlay generator will correctly update the suffix based on the new content.
|
||||
{{< /alert >}}
|
||||
|
||||
## Propagating the Name Suffix
|
||||
|
||||
Workloads that reference the ConfigMap or Secret will need to know the name of the generated Resource,
|
||||
including the suffix. Kustomize takes care of this automatically by identifying
|
||||
references to generated ConfigMaps and Secrets, and updating them.
|
||||
|
||||
In the following example, the generated ConfigMap name will be `my-java-server-env-vars` with a suffix unique to its contents.
|
||||
Changes to the contents will change the name suffix, resulting in the creation of a new ConfigMap,
|
||||
which Kustomize will transform Workloads to point to.
|
||||
|
||||
The PodTemplate volume references the ConfigMap by the name specified in the generator (excluding the suffix).
|
||||
Kustomize will update the name to include the suffix applied to the ConfigMap name.
|
||||
|
||||
**Input:** The kustomization.yaml and deployment.yaml files
|
||||
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
configMapGenerator:
|
||||
- name: my-java-server-env-vars
|
||||
literals:
|
||||
- JAVA_HOME=/opt/java/jdk
|
||||
- JAVA_TOOL_OPTIONS=-agentlib:hprof
|
||||
resources:
|
||||
- deployment.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: test-deployment
|
||||
labels:
|
||||
app: test
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: test
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: test
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
image: registry.k8s.io/busybox
|
||||
command: [ "/bin/sh", "-c", "ls /etc/config/" ]
|
||||
volumeMounts:
|
||||
- name: config-volume
|
||||
mountPath: /etc/config
|
||||
volumes:
|
||||
- name: config-volume
|
||||
configMap:
|
||||
name: my-java-server-env-vars
|
||||
```
|
||||
|
||||
**Result:** The output of the Kustomize build.
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
# The name has been updated to include the suffix
|
||||
name: my-java-server-env-vars-k44mhd6h5f
|
||||
data:
|
||||
JAVA_HOME: /opt/java/jdk
|
||||
JAVA_TOOL_OPTIONS: -agentlib:hprof
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app: test
|
||||
name: test-deployment
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: test
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: test
|
||||
spec:
|
||||
containers:
|
||||
- command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- ls /etc/config/
|
||||
image: registry.k8s.io/busybox
|
||||
name: container
|
||||
volumeMounts:
|
||||
- mountPath: /etc/config
|
||||
name: config-volume
|
||||
volumes:
|
||||
- configMap:
|
||||
# The name has been updated to include the
|
||||
# suffix matching the ConfigMap
|
||||
name: my-java-server-env-vars-k44mhd6h5f
|
||||
name: config-volume
|
||||
```
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
title: "crds"
|
||||
linkTitle: "crds"
|
||||
type: docs
|
||||
weight: 7
|
||||
description: >
|
||||
Adding CRD support
|
||||
---
|
||||
|
||||
Each entry in this list should be a relative path to
|
||||
a file for custom resource definition (CRD).
|
||||
|
||||
The presence of this field is to allow kustomize be
|
||||
aware of CRDs and apply proper
|
||||
transformation for any objects in those types.
|
||||
|
||||
Typical use case: A CRD object refers to a
|
||||
ConfigMap object. In a kustomization, the ConfigMap
|
||||
object name may change by adding namePrefix,
|
||||
nameSuffix, or hashing. The name reference for this
|
||||
ConfigMap object in CRD object need to be updated
|
||||
with namePrefix, nameSuffix, or hashing in the
|
||||
same way.
|
||||
|
||||
The annotations can be put into openAPI definitions are:
|
||||
|
||||
- "x-kubernetes-annotation": ""
|
||||
- "x-kubernetes-label-selector": ""
|
||||
- "x-kubernetes-identity": ""
|
||||
- "x-kubernetes-object-ref-api-version": "v1",
|
||||
- "x-kubernetes-object-ref-kind": "Secret",
|
||||
- "x-kubernetes-object-ref-name-key": "name",
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
crds:
|
||||
- crds/typeA.yaml
|
||||
- crds/typeB.yaml
|
||||
```
|
||||
@@ -0,0 +1,115 @@
|
||||
---
|
||||
title: "generatorOptions"
|
||||
linkTitle: "generatorOptions"
|
||||
type: docs
|
||||
weight: 8
|
||||
description: >
|
||||
Control behavior of [ConfigMap](https://kubernetes.io/docs/concepts/configuration/configmap/) and
|
||||
[Secret](https://kubernetes.io/docs/concepts/configuration/secret/) generators.
|
||||
---
|
||||
|
||||
Additionally, generatorOptions can be set on a per resource level within each
|
||||
generator. For details on per-resource generatorOptions usage see
|
||||
[configMapGenerator](/docs/reference/api/kustomization-file/configmapgenerator/) and see [secretGenerator](/docs/reference/api/kustomization-file/secretgenerator/).
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
generatorOptions:
|
||||
# labels to add to all generated resources
|
||||
labels:
|
||||
kustomize.generated.resources: somevalue
|
||||
# annotations to add to all generated resources
|
||||
annotations:
|
||||
kustomize.generated.resource: somevalue
|
||||
# disableNameSuffixHash is true disables the default behavior of adding a
|
||||
# suffix to the names of generated resources that is a hash of
|
||||
# the resource contents.
|
||||
disableNameSuffixHash: true
|
||||
# if set to true, the immutable property is added to generated resources
|
||||
immutable: true
|
||||
```
|
||||
|
||||
## Example I
|
||||
|
||||
Using ConfigMap
|
||||
|
||||
### Input Files
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
configMapGenerator:
|
||||
- name: my-application-properties
|
||||
files:
|
||||
- application.properties
|
||||
generatorOptions:
|
||||
labels:
|
||||
kustomize.generated.resources: config-label
|
||||
annotations:
|
||||
kustomize.generated.resource: config-annotation
|
||||
```
|
||||
|
||||
```yaml
|
||||
# application.properties
|
||||
FOO=Bar
|
||||
```
|
||||
|
||||
### Output File
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
data:
|
||||
application.properties: |-
|
||||
# application.properties
|
||||
FOO=Bar
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
annotations:
|
||||
kustomize.generated.resource: config-annotation
|
||||
labels:
|
||||
kustomize.generated.resources: config-label
|
||||
name: my-application-properties-f7mm6mhf59
|
||||
```
|
||||
|
||||
## Example II
|
||||
|
||||
Using Secrets
|
||||
|
||||
### Input Files
|
||||
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
secretGenerator:
|
||||
- name: app-tls
|
||||
files:
|
||||
- "tls.cert"
|
||||
- "tls.key"
|
||||
type: "kubernetes.io/tls"
|
||||
generatorOptions:
|
||||
labels:
|
||||
kustomize.generated.resources: secret-label
|
||||
annotations:
|
||||
kustomize.generated.resource: secret-annotation
|
||||
disableNameSuffixHash: true
|
||||
```
|
||||
|
||||
### Output File
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
data:
|
||||
tls.cert: TFMwdExTMUNSVWQuLi50Q2c9PQ==
|
||||
tls.key: TFMwdExTMUNSVWQuLi4wdExRbz0=
|
||||
kind: Secret
|
||||
metadata:
|
||||
annotations:
|
||||
kustomize.generated.resource: secret-annotation
|
||||
labels:
|
||||
kustomize.generated.resources: secret-label
|
||||
name: app-tls
|
||||
type: kubernetes.io/tls
|
||||
```
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
title: "helmCharts"
|
||||
linkTitle: "helmCharts"
|
||||
type: docs
|
||||
weight: 8
|
||||
description: >
|
||||
Helm chart inflation generator.
|
||||
---
|
||||
|
||||
[kustomize builtins]: https://kubectl.docs.kubernetes.io/references/kustomize/builtins/#_helmchartinflationgenerator_
|
||||
[Helm support long term plan]: https://github.com/kubernetes-sigs/kustomize/issues/4401
|
||||
|
||||
## Helm Chart Inflation Generator
|
||||
|
||||
Kustomize has limited support for helm chart inflation through the `helmCharts` field.
|
||||
You can read a detailed description of this field in the docs about [kustomize builtins].
|
||||
|
||||
To enable the helm chart inflation generator, you have to specify the `enable-helm` flag as follows:
|
||||
|
||||
```sh
|
||||
kustomize build --enable-helm
|
||||
```
|
||||
|
||||
## Long term support
|
||||
|
||||
The helm chart inflation generator in kustomize is intended to be a limited subset of helm features to help with
|
||||
getting started with kustomize, and we cannot support the entire helm feature set.
|
||||
|
||||
### The current builtin
|
||||
For enhancements to the helm chart inflation generator feature, we will only support the following changes:
|
||||
|
||||
- bug fixes
|
||||
- critical security issues
|
||||
- additional fields that are analogous to flags passed to `helm template`, except for flags such as `post-renderer`
|
||||
that allow arbitrary commands to be executed
|
||||
|
||||
We will not add support for:
|
||||
|
||||
- private repository or registry authentication
|
||||
- OCI registries
|
||||
- other large features that increase the complexity of the feature and/or have significant security implications
|
||||
|
||||
### Future support
|
||||
The next iteration of the helm inflation generator will take the form of a KRM function, which will have
|
||||
no such restrictions on what types of features we can add and support. You can see more details in
|
||||
the [Helm support long term plan].
|
||||
169
site/content/en/docs/Reference/API/Kustomization File/images.md
Normal file
169
site/content/en/docs/Reference/API/Kustomization File/images.md
Normal file
@@ -0,0 +1,169 @@
|
||||
---
|
||||
title: "images"
|
||||
linkTitle: "images"
|
||||
type: docs
|
||||
weight: 9
|
||||
description: >
|
||||
Modify the name, tags and/or digest for images.
|
||||
---
|
||||
|
||||
Images modify the name, tags and/or digest for images without creating patches.
|
||||
|
||||
One can change the `image` in the following ways (Refer the following example to know exactly how this is done):
|
||||
|
||||
- `postgres:8` to `my-registry/my-postgres:v1`,
|
||||
- nginx tag `1.7.9` to `1.8.0`,
|
||||
- image name `my-demo-app` to `my-app`,
|
||||
- alpine's tag `3.7` to a digest value
|
||||
|
||||
It is possible to set image tags for container images through
|
||||
the `kustomization.yaml` using the `images` field. When `images` are
|
||||
specified, Apply will override the images whose image name matches `name` with a new
|
||||
tag.
|
||||
|
||||
|
||||
| Field | Description | Example Field | Example Result |
|
||||
|-----------|--------------------------------------------------------------------------|----------| --- |
|
||||
| `name` | Match images with this image name| `name: nginx`| |
|
||||
| `newTag` | Override the image **tag** or **digest** for images whose image name matches `name` | `newTag: new` | `nginx:old` -> `nginx:new` |
|
||||
| `newName` | Override the image **name** for images whose image name matches `name` | `newName: nginx-special` | `nginx:old` -> `nginx-special:old` |
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
### File Input
|
||||
|
||||
```yaml
|
||||
# deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: the-deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: mypostgresdb
|
||||
image: postgres:8
|
||||
- name: nginxapp
|
||||
image: nginx:1.7.9
|
||||
- name: myapp
|
||||
image: my-demo-app:latest
|
||||
- name: alpine-app
|
||||
image: alpine:3.7
|
||||
|
||||
```
|
||||
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
images:
|
||||
- name: postgres
|
||||
newName: my-registry/my-postgres
|
||||
newTag: v1
|
||||
- name: nginx
|
||||
newTag: 1.8.0
|
||||
- name: my-demo-app
|
||||
newName: my-app
|
||||
- name: alpine
|
||||
digest: sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3
|
||||
|
||||
resources:
|
||||
- deployment.yaml
|
||||
|
||||
```
|
||||
|
||||
### Build Output
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: the-deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- image: my-registry/my-postgres:v1
|
||||
name: mypostgresdb
|
||||
- image: nginx:1.8.0
|
||||
name: nginxapp
|
||||
- image: my-app:latest
|
||||
name: myapp
|
||||
- image: alpine@sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3
|
||||
name: alpine-app
|
||||
```
|
||||
|
||||
## Setting a Name
|
||||
|
||||
The name for an image may be set by specifying `newName` and the name of the old container image.
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
images:
|
||||
- name: mycontainerregistry/myimage
|
||||
newName: differentregistry/myimage
|
||||
```
|
||||
|
||||
## Setting a Tag
|
||||
|
||||
The tag for an image may be set by specifying `newTag` and the name of the container image.
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
images:
|
||||
- name: mycontainerregistry/myimage
|
||||
newTag: v1
|
||||
```
|
||||
|
||||
## Setting a Digest
|
||||
|
||||
The digest for an image may be set by specifying `digest` and the name of the container image.
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
images:
|
||||
- name: alpine
|
||||
digest: sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3
|
||||
```
|
||||
|
||||
|
||||
## Setting a Tag from the latest commit SHA
|
||||
|
||||
A common CI/CD pattern is to tag container images with the git commit SHA of source code. e.g. if
|
||||
the image name is `foo` and an image was built for the source code at commit `1bb359ccce344ca5d263cd257958ea035c978fd3`
|
||||
then the container image would be `foo:1bb359ccce344ca5d263cd257958ea035c978fd3`.
|
||||
|
||||
A simple way to push an image that was just built without manually updating the image tags is to
|
||||
[download the kustomize standalone](/docs/getting-started/installation/) tool and run
|
||||
`kustomize edit set image` command to update the tags for you.
|
||||
|
||||
**Example:** Set the latest git commit SHA as the image tag for `foo` images.
|
||||
|
||||
```bash
|
||||
kustomize edit set image foo:$(git log -n 1 --pretty=format:"%H")
|
||||
kubectl apply -f .
|
||||
```
|
||||
|
||||
## Setting a Tag from an Environment Variable
|
||||
|
||||
It is also possible to set a Tag from an environment variable using the same technique for setting from a commit SHA.
|
||||
|
||||
**Example:** Set the tag for the `foo` image to the value in the environment variable `FOO_IMAGE_TAG`.
|
||||
|
||||
```bash
|
||||
kustomize edit set image foo:$FOO_IMAGE_TAG
|
||||
kubectl apply -f .
|
||||
```
|
||||
|
||||
{{< alert color="success" title="Committing Image Tag Updates" >}}
|
||||
The `kustomization.yaml` changes *may* be committed back to git so that they
|
||||
can be audited. When committing the image tag updates that have already
|
||||
been pushed by a CI/CD system, be careful not to trigger new builds +
|
||||
deployments for these changes.
|
||||
{{< /alert >}}
|
||||
237
site/content/en/docs/Reference/API/Kustomization File/labels.md
Normal file
237
site/content/en/docs/Reference/API/Kustomization File/labels.md
Normal file
@@ -0,0 +1,237 @@
|
||||
---
|
||||
title: "labels"
|
||||
linkTitle: "labels"
|
||||
type: docs
|
||||
weight: 10
|
||||
description: >
|
||||
Add labels and optionally selectors to all resources.
|
||||
---
|
||||
|
||||
A field that allows adding labels without also automatically injecting corresponding selectors.
|
||||
This can be used instead of the `commonLabels` field, which always adds selectors.
|
||||
|
||||
{{% pageinfo color="warning" %}}
|
||||
Selectors for resources such as Deployments and Services shouldn't be changed once the
|
||||
resource has been applied to a cluster.
|
||||
|
||||
Changing `includeSelectors` to `true` or changing labels when `includeSelectors` is `true` in live resources
|
||||
is equivalent to changing `commonLabels` and could result in failures.
|
||||
{{% /pageinfo %}}
|
||||
|
||||
The following flags are available:
|
||||
* `includeTemplates`: When set will also apply labels to metadata/labels and spec/template/metadata/labels. This can be used to add labels to Pods from owner resources, such as Deployments and StatefulSets, without modifying selectors. False by default.
|
||||
* `includeSelectors`: When set will apply labels to metadata/labels, selectors, and spec/template/metadata/labels. False by default.
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
labels:
|
||||
- pairs:
|
||||
someName: someValue
|
||||
owner: alice
|
||||
app: bingo
|
||||
includeSelectors: true # <-- false by default
|
||||
includeTemplates: true # <-- false by default
|
||||
```
|
||||
|
||||
## Example 1 - selectors and templates NOT modified
|
||||
|
||||
### File Input
|
||||
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
labels:
|
||||
- pairs:
|
||||
someName: someValue
|
||||
owner: alice
|
||||
app: bingo
|
||||
|
||||
resources:
|
||||
- deploy.yaml
|
||||
- service.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# deploy.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: example
|
||||
```
|
||||
|
||||
```yaml
|
||||
# service.yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: example
|
||||
```
|
||||
|
||||
### Build Output
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
app: bingo
|
||||
owner: alice
|
||||
someName: someValue
|
||||
name: example
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app: bingo
|
||||
owner: alice
|
||||
someName: someValue
|
||||
name: example
|
||||
```
|
||||
|
||||
|
||||
## Example 2 - selectors modified
|
||||
|
||||
### File Input
|
||||
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
labels:
|
||||
- pairs:
|
||||
someName: someValue
|
||||
owner: alice
|
||||
app: bingo
|
||||
includeSelectors: true
|
||||
|
||||
resources:
|
||||
- deploy.yaml
|
||||
- service.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# deploy.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: example
|
||||
```
|
||||
|
||||
```yaml
|
||||
# service.yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: example
|
||||
```
|
||||
|
||||
### Build Output
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
app: bingo
|
||||
owner: alice
|
||||
someName: someValue
|
||||
name: example
|
||||
spec:
|
||||
selector:
|
||||
app: bingo
|
||||
owner: alice
|
||||
someName: someValue
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app: bingo
|
||||
owner: alice
|
||||
someName: someValue
|
||||
name: example
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: bingo
|
||||
owner: alice
|
||||
someName: someValue
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: bingo
|
||||
owner: alice
|
||||
someName: someValue
|
||||
```
|
||||
|
||||
## Example 3 - templates modified
|
||||
|
||||
### File Input
|
||||
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
labels:
|
||||
- pairs:
|
||||
someName: someValue
|
||||
owner: alice
|
||||
app: bingo
|
||||
includeTemplates: true
|
||||
|
||||
resources:
|
||||
- deploy.yaml
|
||||
- service.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# deploy.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: example
|
||||
```
|
||||
|
||||
```yaml
|
||||
# service.yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: example
|
||||
```
|
||||
|
||||
### Build Output
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
app: bingo
|
||||
owner: alice
|
||||
someName: someValue
|
||||
name: example
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app: bingo
|
||||
owner: alice
|
||||
someName: someValue
|
||||
name: example
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: bingo
|
||||
owner: alice
|
||||
someName: someValue
|
||||
```
|
||||
@@ -0,0 +1,64 @@
|
||||
---
|
||||
title: "namePrefix"
|
||||
linkTitle: "namePrefix"
|
||||
type: docs
|
||||
weight: 11
|
||||
description: >
|
||||
Prepends the value to the names of all resources and references.
|
||||
---
|
||||
|
||||
As `namePrefix` is self explanatory, it helps adding prefix to names in the defined yaml files.
|
||||
|
||||
## Example
|
||||
|
||||
### File Input
|
||||
|
||||
```yaml
|
||||
# deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: the-deployment
|
||||
spec:
|
||||
replicas: 5
|
||||
template:
|
||||
containers:
|
||||
- name: the-container
|
||||
image: registry/container:latest
|
||||
```
|
||||
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namePrefix: custom-prefix-
|
||||
|
||||
resources:
|
||||
- deployment.yaml
|
||||
|
||||
```
|
||||
|
||||
### Build Output
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: custom-prefix-the-deployment
|
||||
spec:
|
||||
replicas: 5
|
||||
template:
|
||||
containers:
|
||||
- image: registry/container:latest
|
||||
name: the-container
|
||||
```
|
||||
|
||||
{{< alert color="success" title="References" >}}
|
||||
Apply will propagate the `namePrefix` to any place Resources within the project are referenced by other Resources
|
||||
including:
|
||||
|
||||
- Service references from StatefulSets
|
||||
- ConfigMap references from PodSpecs
|
||||
- Secret references from PodSpecs
|
||||
{{< /alert >}}
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
title: "nameSuffix"
|
||||
linkTitle: "nameSuffix"
|
||||
type: docs
|
||||
weight: 13
|
||||
description: >
|
||||
Appends the value to the names of all resources and references.
|
||||
---
|
||||
|
||||
As `nameSuffix` is self explanatory, it helps adding suffix to names in the defined yaml files.
|
||||
|
||||
**Note:** The suffix is appended before the content hash if the resource type is ConfigMap or Secret.
|
||||
|
||||
## Example
|
||||
|
||||
### File Input
|
||||
|
||||
```yaml
|
||||
# deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: the-deployment
|
||||
spec:
|
||||
replicas: 5
|
||||
template:
|
||||
containers:
|
||||
- name: the-container
|
||||
image: registry/container:latest
|
||||
```
|
||||
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
nameSuffix: -custom-suffix
|
||||
|
||||
resources:
|
||||
- deployment.yaml
|
||||
|
||||
```
|
||||
|
||||
### Build Output
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: the-deployment-custom-suffix
|
||||
spec:
|
||||
replicas: 5
|
||||
template:
|
||||
containers:
|
||||
- image: registry/container:latest
|
||||
name: the-container
|
||||
```
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
title: "namespace"
|
||||
linkTitle: "namespace"
|
||||
type: docs
|
||||
weight: 12
|
||||
description: >
|
||||
Adds namespace to all resources.
|
||||
---
|
||||
|
||||
Will override the existing namespace if it is set on a resource, or add it
|
||||
if it is not set on a resource.
|
||||
|
||||
## Example
|
||||
|
||||
### File Input
|
||||
|
||||
```yaml
|
||||
# deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: the-deployment
|
||||
namespace: the-namespace
|
||||
spec:
|
||||
replicas: 5
|
||||
template:
|
||||
containers:
|
||||
- name: the-container
|
||||
image: registry/container:latest
|
||||
```
|
||||
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: kustomize-namespace
|
||||
|
||||
resources:
|
||||
- deployment.yaml
|
||||
|
||||
```
|
||||
|
||||
### Build Output
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: the-deployment
|
||||
namespace: kustomize-namespace
|
||||
spec:
|
||||
replicas: 5
|
||||
template:
|
||||
containers:
|
||||
- image: registry/container:latest
|
||||
name: the-container
|
||||
```
|
||||
217
site/content/en/docs/Reference/API/Kustomization File/openapi.md
Normal file
217
site/content/en/docs/Reference/API/Kustomization File/openapi.md
Normal file
@@ -0,0 +1,217 @@
|
||||
---
|
||||
title: "openapi"
|
||||
linkTitle: "openapi"
|
||||
type: docs
|
||||
weight: 14
|
||||
description: >
|
||||
Specify where kustomize gets its OpenAPI schema.
|
||||
---
|
||||
|
||||
Kustomize uses kubernetes OpenAPI data to get merge key and patch strategy
|
||||
information about resource types. Kustomize has an OpenAPI schema builtin,
|
||||
but this schema only has information about builtin kubernetes types. If
|
||||
you need to provide merge key and patch strategy information about custom
|
||||
resource types, you will have to provide your own OpenAPI schema to do so.
|
||||
|
||||
In your kustomization file, you can specify where kustomize should get
|
||||
its OpenAPI schema via an `openapi` field. For example:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- my_resource.yaml
|
||||
|
||||
openapi:
|
||||
path: my_schema.json
|
||||
```
|
||||
|
||||
The `openapi` field of a kustomization file can either a path to a custom schema
|
||||
file, as in the example above. It can also be used to explicitly tell kustomize to
|
||||
use a builtin kubernetes OpenAPI schema:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- my_resource.yaml
|
||||
|
||||
openapi:
|
||||
version: v1.20.4
|
||||
```
|
||||
|
||||
You can see what builtin kubernetes OpenAPI schemas are available with the command
|
||||
`kustomize openapi info`.
|
||||
|
||||
Here is an example of a custom resource we might want to edit with a custom OpenAPI schema
|
||||
file. It looks like this:
|
||||
|
||||
```yaml
|
||||
apiVersion: example.com/v1alpha1
|
||||
kind: MyResource
|
||||
metadata:
|
||||
name: service
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: server
|
||||
image: server
|
||||
command: example
|
||||
ports:
|
||||
- name: grpc
|
||||
protocol: TCP
|
||||
containerPort: 8080
|
||||
```
|
||||
|
||||
This resource has an image field. Let's change its value from `server`
|
||||
to `nginx` with a patch. You can get an OpenAPI document like this from
|
||||
your locally favored cluster with the command `kustomize openapi fetch`.
|
||||
Kustomize will use the OpenAPI extensions `x-kubernetes-patch-merge-key` and
|
||||
`x-kubernetes-patch-strategy` to perform a strategic merge.
|
||||
`x-kubernetes-patch-strategy` should be set to "merge", and you can set your
|
||||
merge key to whatever you like.
|
||||
|
||||
Below, our custom resource inherits merge keys from PodTemplateSpec. In the
|
||||
definition of "io.k8s.api.core.v1.Container", the `ports` field has its merge
|
||||
key set to "containerPort":
|
||||
|
||||
```json
|
||||
{
|
||||
"definitions": {
|
||||
"v1alpha1.MyResource": {
|
||||
"properties": {
|
||||
"apiVersion": {
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"type": "string"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object"
|
||||
},
|
||||
"spec": {
|
||||
"properties": {
|
||||
"template": {
|
||||
"\$ref": "#/definitions/io.k8s.api.core.v1.PodTemplateSpec"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"status": {
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"x-kubernetes-group-version-kind": [
|
||||
{
|
||||
"group": "example.com",
|
||||
"kind": "MyResource",
|
||||
"version": "v1alpha1"
|
||||
}
|
||||
]
|
||||
},
|
||||
"io.k8s.api.core.v1.PodTemplateSpec": {
|
||||
"properties": {
|
||||
"metadata": {
|
||||
"\$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"
|
||||
},
|
||||
"spec": {
|
||||
"\$ref": "#/definitions/io.k8s.api.core.v1.PodSpec"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"io.k8s.api.core.v1.PodSpec": {
|
||||
"properties": {
|
||||
"containers": {
|
||||
"items": {
|
||||
"\$ref": "#/definitions/io.k8s.api.core.v1.Container"
|
||||
},
|
||||
"type": "array",
|
||||
"x-kubernetes-patch-merge-key": "name",
|
||||
"x-kubernetes-patch-strategy": "merge"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"io.k8s.api.core.v1.Container": {
|
||||
"properties": {
|
||||
"command": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"image": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"ports": {
|
||||
"items": {
|
||||
"\$ref": "#/definitions/io.k8s.api.core.v1.ContainerPort"
|
||||
},
|
||||
"type": "array",
|
||||
"x-kubernetes-list-map-keys": [
|
||||
"containerPort",
|
||||
"protocol"
|
||||
],
|
||||
"x-kubernetes-list-type": "map",
|
||||
"x-kubernetes-patch-merge-key": "containerPort",
|
||||
"x-kubernetes-patch-strategy": "merge"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"io.k8s.api.core.v1.ContainerPort": {
|
||||
"properties": {
|
||||
"containerPort": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"protocol": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then, our kustomization file to do the patch can be as follows:
|
||||
```yaml
|
||||
resources:
|
||||
- my_resource.yaml
|
||||
|
||||
openapi:
|
||||
path: my_schema.json
|
||||
|
||||
patchesStrategicMerge:
|
||||
- |-
|
||||
apiVersion: example.com/v1alpha1
|
||||
kind: MyResource
|
||||
metadata:
|
||||
name: service
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: server
|
||||
image: nginx
|
||||
```
|
||||
|
||||
280
site/content/en/docs/Reference/API/Kustomization File/patches.md
Normal file
280
site/content/en/docs/Reference/API/Kustomization File/patches.md
Normal file
@@ -0,0 +1,280 @@
|
||||
---
|
||||
title: "patches"
|
||||
linkTitle: "patches"
|
||||
type: docs
|
||||
weight: 15
|
||||
description: >
|
||||
Patch resources
|
||||
---
|
||||
|
||||
[strategic merge]: /docs/reference/api/kustomization-file/patchesstrategicmerge/
|
||||
[JSON6902]: /docs/reference/api/kustomization-file/patchesjson6902/
|
||||
|
||||
Patches (also called overlays) add or override fields on resources. They are provided using the
|
||||
`patches` Kustomization field.
|
||||
|
||||
The `patches` field contains a list of patches to be applied in the order they are specified.
|
||||
|
||||
Each patch may:
|
||||
|
||||
- be either a [strategic merge] patch, or a [JSON6902] patch
|
||||
- be either a file, or an inline string
|
||||
- target a single resource or multiple resources
|
||||
|
||||
The patch target selects resources by `group`, `version`, `kind`, `name`, `namespace`, `labelSelector` and
|
||||
`annotationSelector`. Any resource which matches all the **specified** fields has the patch applied
|
||||
to it (regular expressions).
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
patches:
|
||||
- path: patch.yaml
|
||||
target:
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: deploy.*
|
||||
labelSelector: "env=dev"
|
||||
annotationSelector: "zone=west"
|
||||
- patch: |-
|
||||
- op: replace
|
||||
path: /some/existing/path
|
||||
value: new value
|
||||
target:
|
||||
kind: MyKind
|
||||
labelSelector: "env=dev"
|
||||
```
|
||||
|
||||
The `name` and `namespace` fields of the patch target selector are
|
||||
automatically anchored regular expressions. This means that the value `myapp`
|
||||
is equivalent to `^myapp$`.
|
||||
|
||||
## Name and kind changes
|
||||
|
||||
With `patches` it is possible to override the kind or name of the resource it is
|
||||
editing with the options `allowNameChange` and `allowKindChange`. For example:
|
||||
```yaml
|
||||
resources:
|
||||
- deployment.yaml
|
||||
patches:
|
||||
- path: patch.yaml
|
||||
target:
|
||||
kind: Deployment
|
||||
options:
|
||||
allowNameChange: true
|
||||
allowKindChange: true
|
||||
```
|
||||
By default, these fields are false and the patch will leave the kind and name of the resource untouched.
|
||||
|
||||
## Name references
|
||||
|
||||
A patch can refer to a resource by any of its previous names or kinds.
|
||||
For example, if a resource has gone through name-prefix transformations, it can refer to the
|
||||
resource by its current name, original name, or any intermediate name that it had.
|
||||
|
||||
## Patching custom resources
|
||||
|
||||
[Strategic merge] patches may require additional configuration via [openapi](../openapi) field to work as expected with custom resources. For example, if a resource uses a merge key other than `name` or needs a list to be merged rather than replaced, Kustomize needs openapi information informing it about this.
|
||||
|
||||
[JSON6902] patch usage is the same for built-in and custom resources.
|
||||
|
||||
## Examples
|
||||
|
||||
Consider the following `deployment.yaml` common for all examples:
|
||||
```yaml
|
||||
# deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: dummy-app
|
||||
labels:
|
||||
app.kubernetes.io/name: nginx
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:stable
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
```
|
||||
|
||||
### Intents
|
||||
|
||||
- Make the container image point to a specific version and not to the latest container in the registry.
|
||||
- Adding a standard label containing the deployed version.
|
||||
|
||||
There are multiple possible strategies that all achieve the same results.
|
||||
|
||||
### Patch using Inline Strategic Merge
|
||||
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
resources:
|
||||
- deployment.yaml
|
||||
patches:
|
||||
- patch: |-
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: dummy-app
|
||||
labels:
|
||||
app.kubernetes.io/version: 1.21.0
|
||||
- patch: |-
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: not-used
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.21.0
|
||||
target:
|
||||
labelSelector: "app.kubernetes.io/name=nginx"
|
||||
```
|
||||
|
||||
If a `target` is specified, the `name` contained in the metadata is required but not used.
|
||||
|
||||
### Patch using Inline JSON6902
|
||||
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
resources:
|
||||
- deployment.yaml
|
||||
patches:
|
||||
- patch: |-
|
||||
- op: add
|
||||
path: /metadata/labels/app.kubernetes.io~1version
|
||||
value: 1.21.0
|
||||
target:
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
- patch: |-
|
||||
- op: replace
|
||||
path: /spec/template/spec/containers/0/image
|
||||
value: nginx:1.21.0
|
||||
target:
|
||||
labelSelector: "app.kubernetes.io/name=nginx"
|
||||
```
|
||||
|
||||
The `target` field is always required for JSON6902 patches.
|
||||
A special replacement character `~1` is used to replace `/` in label name.
|
||||
|
||||
### Patch using Path Strategic Merge
|
||||
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
resources:
|
||||
- deployment.yaml
|
||||
patches:
|
||||
- path: add-label.patch.yaml
|
||||
- path: fix-version.patch.yaml
|
||||
target:
|
||||
labelSelector: "app.kubernetes.io/name=nginx"
|
||||
```
|
||||
|
||||
As with the Inline Strategic Merge, the `target` field can be omitted.
|
||||
In that case, the target resource is matched using
|
||||
the `apiVersion`, `kind` and `name` from the patch.
|
||||
|
||||
```yaml
|
||||
# add-label.patch.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: dummy-app
|
||||
labels:
|
||||
app.kubernetes.io/version: 1.21.0
|
||||
```
|
||||
|
||||
```yaml
|
||||
# fix-version.patch.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: not-used
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.21.0
|
||||
```
|
||||
|
||||
As with the Inline Strategic Merge, the `name` field in the patch is not used when a `target` is specified.
|
||||
|
||||
### Patch using Path JSON6902
|
||||
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
resources:
|
||||
- deployment.yaml
|
||||
patches:
|
||||
- path: add-label.patch.json
|
||||
target:
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
- path: fix-version.patch.yaml
|
||||
target:
|
||||
labelSelector: "app.kubernetes.io/name=nginx"
|
||||
```
|
||||
|
||||
As with Inline JSON6902, the `target` field is mandatory.
|
||||
|
||||
```yaml
|
||||
# add-label.patch.json
|
||||
[
|
||||
{"op": "add", "path": "/metadata/labels/app.kubernetes.io~1version", "value": "1.21.0"}
|
||||
]
|
||||
```
|
||||
|
||||
```yaml
|
||||
# fix-version.patch.yaml
|
||||
- op: replace
|
||||
path: /spec/template/spec/containers/0/image
|
||||
value: nginx:1.21.0
|
||||
```
|
||||
|
||||
External patch file can be written both as YAML or JSON.
|
||||
The content must follow the JSON6902 standard.
|
||||
|
||||
### Build Output
|
||||
|
||||
All four patches strategies lead to the exact same output:
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: nginx
|
||||
app.kubernetes.io/version: 1.21.0
|
||||
name: dummy-app
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: nginx
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx:1.21.0
|
||||
name: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
```
|
||||
@@ -0,0 +1,80 @@
|
||||
---
|
||||
title: "patchesStrategicMerge"
|
||||
linkTitle: "patchesStrategicMerge"
|
||||
type: docs
|
||||
weight: 17
|
||||
description: >
|
||||
Patch resources using the strategic merge patch standard.
|
||||
---
|
||||
|
||||
{{% pageinfo color="warning" %}}
|
||||
The `patchesStrategicMerge` field was deprecated in v5.0.0. This field will never be removed from the
|
||||
kustomize.config.k8s.io/v1beta1 Kustomization API, but it will not be included
|
||||
in the kustomize.config.k8s.io/v1 Kustomization API. When Kustomization v1 is available,
|
||||
we will announce the deprecation of the v1beta1 version. There will be at least
|
||||
two releases between deprecation and removal of Kustomization v1beta1 support from the
|
||||
kustomize CLI, and removal itself will happen in a future major version bump.
|
||||
|
||||
Please move your `patchesStrategicMerge` into
|
||||
the [patches](/docs/reference/api/kustomization-file/patches) field. This field supports patchesStrategicMerge,
|
||||
but with slightly different syntax. You can run `kustomize edit fix` to automatically convert
|
||||
`patchesStrategicMerge` to `patches`.
|
||||
{{% /pageinfo %}}
|
||||
|
||||
Each entry in this list should be either a relative
|
||||
file path or an inline content
|
||||
resolving to a partial or complete resource
|
||||
definition.
|
||||
|
||||
The names in these (possibly partial) resource
|
||||
files must match names already loaded via the
|
||||
`resources` field. These entries are used to
|
||||
_patch_ (modify) the known resources.
|
||||
|
||||
Small patches that do one thing are best, e.g. modify
|
||||
a memory request/limit, change an env var in a
|
||||
ConfigMap, etc. Small patches are easy to review and
|
||||
easy to mix together in overlays.
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
patchesStrategicMerge:
|
||||
- service_port_8888.yaml
|
||||
- deployment_increase_replicas.yaml
|
||||
- deployment_increase_memory.yaml
|
||||
```
|
||||
|
||||
The patch content can be a inline string as well.
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
patchesStrategicMerge:
|
||||
- |-
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nignx:latest
|
||||
```
|
||||
|
||||
Note that kustomize does not support more than one patch
|
||||
for the same object that contain a _delete_ directive. To remove
|
||||
several fields / slice elements from an object create a single
|
||||
patch that performs all the needed deletions.
|
||||
|
||||
A patch can refer to a resource by any of its previous names or kinds.
|
||||
For example, if a resource has gone through name-prefix transformations, it can refer to the
|
||||
resource by its current name, original name, or any intermediate name that it had.
|
||||
|
||||
## Patching custom resources
|
||||
|
||||
Strategic merge patches may require additional configuration via [openapi](../openapi) field to work as expected with custom resources. For example, if a resource uses a merge key other than `name` or needs a list to be merged rather than replaced, Kustomize needs openapi information informing it about this.
|
||||
@@ -0,0 +1,111 @@
|
||||
---
|
||||
title: "patchesJson6902"
|
||||
linkTitle: "patchesJson6902"
|
||||
type: docs
|
||||
weight: 16
|
||||
description: >
|
||||
Patch resources using the [json 6902 standard](https://tools.ietf.org/html/rfc6902)
|
||||
---
|
||||
|
||||
{{% pageinfo color="warning" %}}
|
||||
The `patchesJson6902` field was deprecated in v5.0.0. This field will never be removed from the
|
||||
kustomize.config.k8s.io/v1beta1 Kustomization API, but it will not be included
|
||||
in the kustomize.config.k8s.io/v1 Kustomization API. When Kustomization v1 is available,
|
||||
we will announce the deprecation of the v1beta1 version. There will be at least
|
||||
two releases between deprecation and removal of Kustomization v1beta1 support from the
|
||||
kustomize CLI, and removal itself will happen in a future major version bump.
|
||||
|
||||
Please move your `patchesJson6902` into
|
||||
the [patches](/docs/reference/api/kustomization-file/patches) field. This field supports patchesJson6902,
|
||||
but with slightly different syntax. You can run `kustomize edit fix` to automatically convert
|
||||
`patchesJson6902` to `patches`.
|
||||
{{% /pageinfo %}}
|
||||
|
||||
Each entry in this list should resolve to a kubernetes object and a JSON patch that will be applied
|
||||
to the object.
|
||||
The JSON patch is documented at <https://tools.ietf.org/html/rfc6902>
|
||||
|
||||
target field points to a kubernetes object within the same kustomization
|
||||
by the object's group, version, kind, name and namespace.
|
||||
path field is a relative file path of a JSON patch file.
|
||||
The content in this patch file can be either in JSON format as
|
||||
|
||||
```json
|
||||
[
|
||||
{"op": "add", "path": "/some/new/path", "value": "value"},
|
||||
{"op": "replace", "path": "/some/existing/path", "value": "new value"},
|
||||
{"op": "copy", "from": "/some/existing/path", "path": "/some/path"},
|
||||
{"op": "move", "from": "/some/existing/path", "path": "/some/existing/destination/path"},
|
||||
{"op": "remove", "path": "/some/existing/path"},
|
||||
{"op": "test", "path": "/some/path", "value": "my-node-value"}
|
||||
]
|
||||
```
|
||||
|
||||
or in YAML format as
|
||||
|
||||
```yaml
|
||||
# add: creates a new entry with a given value
|
||||
- op: add
|
||||
path: /some/new/path
|
||||
value: value
|
||||
# replace: replaces the value of the node with the new specified value
|
||||
- op: replace
|
||||
path: /some/existing/path
|
||||
value: new value
|
||||
# copy: copies the value specified in from to the destination path
|
||||
- op: copy
|
||||
from: /some/existing/path
|
||||
path: /some/path
|
||||
# move: moves the node specified in from to the destination path
|
||||
- op: move
|
||||
from: /some/existing/path
|
||||
path: /some/existing/destination/path
|
||||
# remove: delete's the node('s subtree)
|
||||
- op: remove
|
||||
path: /some/path
|
||||
# test: check if the specified node has the specified value, if the value differs it will throw an error
|
||||
- op: test
|
||||
path: /some/path
|
||||
value: "my-node-value"
|
||||
```
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
patchesJson6902:
|
||||
- target:
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: my-deployment
|
||||
path: add_init_container.yaml
|
||||
- target:
|
||||
version: v1
|
||||
kind: Service
|
||||
name: my-service
|
||||
path: add_service_annotation.yaml
|
||||
```
|
||||
|
||||
The patch content can be an inline string as well:
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
patchesJson6902:
|
||||
- target:
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: my-deployment
|
||||
patch: |-
|
||||
- op: add
|
||||
path: /some/new/path
|
||||
value: value
|
||||
- op: replace
|
||||
path: /some/existing/path
|
||||
value: "new value"
|
||||
```
|
||||
|
||||
A patch can refer to a resource by any of its previous names or kinds.
|
||||
For example, if a resource has gone through name-prefix transformations, it can refer to the
|
||||
resource by its current name, original name, or any intermediate name that it had.
|
||||
@@ -0,0 +1,387 @@
|
||||
---
|
||||
title: "replacements"
|
||||
linkTitle: "replacements"
|
||||
type: docs
|
||||
weight: 18
|
||||
description: >
|
||||
Substitute field(s) in N target(s) with a field from a source.
|
||||
---
|
||||
|
||||
Replacements are used to copy fields from one source into any
|
||||
number of specified targets.
|
||||
|
||||
\
|
||||
The `replacements` field can support a path to a replacement:
|
||||
|
||||
`kustomization.yaml`
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
replacements:
|
||||
- path: replacement.yaml
|
||||
```
|
||||
`replacement.yaml`
|
||||
```yaml
|
||||
source:
|
||||
kind: Deployment
|
||||
fieldPath: metadata.name
|
||||
targets:
|
||||
- select:
|
||||
name: my-resource
|
||||
```
|
||||
\
|
||||
Alternatively, `replacements` supports inline replacements:
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
replacements:
|
||||
- source:
|
||||
kind: Deployment
|
||||
fieldPath: metadata.name
|
||||
targets:
|
||||
- select:
|
||||
name: my-resource
|
||||
```
|
||||
|
||||
### Syntax
|
||||
|
||||
The full schema of `replacements` is as follows:
|
||||
|
||||
```yaml
|
||||
replacements:
|
||||
- source:
|
||||
group: string
|
||||
version: string
|
||||
kind: string
|
||||
name: string
|
||||
namespace: string
|
||||
fieldPath: string
|
||||
options:
|
||||
delimiter: string
|
||||
index: int
|
||||
create: bool
|
||||
targets:
|
||||
- select:
|
||||
group: string
|
||||
version: string
|
||||
kind: string
|
||||
name: string
|
||||
namespace: string
|
||||
reject:
|
||||
- group: string
|
||||
version: string
|
||||
kind: string
|
||||
name: string
|
||||
namespace: string
|
||||
fieldPaths:
|
||||
- string
|
||||
options:
|
||||
delimiter: string
|
||||
index: int
|
||||
create: bool
|
||||
```
|
||||
|
||||
### Field Descriptions
|
||||
|
||||
| Field | Required| Description | Default |
|
||||
| -----------: | :----: | ----------- | ---- |
|
||||
| `source`| ✔️ | The source of the value |
|
||||
| `target`| ✔️ | The N fields to write the value to |
|
||||
| `group` | | The group of the referent |
|
||||
| `version`| | The version of the referent
|
||||
|`kind` | | The kind of the referent
|
||||
|`name` | | The name of the referent
|
||||
|`namespace`| | The namespace of the referent
|
||||
|`select` | ✔️ |Include objects that match this
|
||||
|`reject`| |Exclude objects that match this
|
||||
|`fieldPath`| | The structured path to the source value | `metadata.name`
|
||||
|`fieldPaths`| | The structured path(s) to the target nodes | `metadata.name`
|
||||
|`options`| | Options used to refine interpretation of the field
|
||||
|`delimiter`| | Used to split/join the field
|
||||
|`index`| | Which position in the split to consider | `0`
|
||||
|`create`| | If target field is missing, add it | `false`
|
||||
|
||||
#### Source
|
||||
The source field is a selector that determines the source of the value by finding a
|
||||
match to the specified GVKNN. All the subfields of `source` are optional,
|
||||
but the source selection must resolve to a single resource.
|
||||
|
||||
#### Targets
|
||||
Replacements will be applied to all targets that are matched by the `select` field and
|
||||
are NOT matched by the `reject` field, and will be applied to all listed `fieldPaths`.
|
||||
|
||||
##### Select
|
||||
You can use any of the following fields to select the targets to replace:
|
||||
`group`, `version`, `kind`, `name`, `namespace`
|
||||
|
||||
For example, the following will select all the Deployments as targets of replacement.
|
||||
|
||||
```yaml
|
||||
select:
|
||||
kind: Deployment
|
||||
```
|
||||
|
||||
Also, you can use multiple fields together to select only the resources that match all the conditions.
|
||||
For example, the following will select only the Deployments that are named my-deploy:
|
||||
|
||||
```yaml
|
||||
select:
|
||||
- kind: Deployment
|
||||
name: my-deploy
|
||||
```
|
||||
|
||||
Moreover, when the selected target is going to be transformed during the kustomization process,
|
||||
you can use either the original or the transformed resource id to select it.
|
||||
|
||||
For example, the name of the target could be changed because of the `namePrefix` field, as below:
|
||||
|
||||
```yaml
|
||||
namePrefix: my-
|
||||
```
|
||||
|
||||
In this case, below will be enough if we wanted to select all the targets that were originally named deploy:
|
||||
|
||||
```yaml
|
||||
select:
|
||||
- name: deploy
|
||||
```
|
||||
|
||||
Alternatively, using the transformed name with the prefix will produce the same behaviour.
|
||||
So the following case will select all the resources that *will be* named my-deploy,
|
||||
along with all the resources that *were* originally named my-deploy.
|
||||
|
||||
```yaml
|
||||
select:
|
||||
- name: my-deploy
|
||||
```
|
||||
|
||||
##### Reject
|
||||
The reject field is a selector that drops targets selected by select, overruling their selection.
|
||||
|
||||
For example, if we wanted to reject all Deployments named my-deploy:
|
||||
|
||||
```yaml
|
||||
reject:
|
||||
- kind: Deployment
|
||||
name: my-deploy
|
||||
```
|
||||
|
||||
This is distinct from the following:
|
||||
|
||||
```yaml
|
||||
reject:
|
||||
- kind: Deployment
|
||||
- name: my-deploy
|
||||
```
|
||||
|
||||
The first case would only reject resources that are both of kind Deployment and named my-deploy. The second case would reject all Deployments, and all resources named my-deploy.
|
||||
|
||||
We can also reject more than one kind, name, etc. For example:
|
||||
|
||||
```yaml
|
||||
reject:
|
||||
- kind: Deployment
|
||||
- kind: StatefulSet
|
||||
```
|
||||
|
||||
Moreover, when the selected target is going to be transformed during the kustomization process,
|
||||
you can use either the original or the transformed resource id to reject it.
|
||||
|
||||
For example, the name of the target could be changed because of the `nameSuffix` field, as below:
|
||||
|
||||
```yaml
|
||||
nameSuffix: -dev
|
||||
```
|
||||
|
||||
You can use the original target name to prevent it from going through any replacement.
|
||||
|
||||
```yaml
|
||||
reject:
|
||||
- name: my-deploy
|
||||
```
|
||||
|
||||
Alternatively, using the transformed name with the suffix will produce the same behaviour.
|
||||
|
||||
```yaml
|
||||
reject:
|
||||
- name: my-deploy-dev
|
||||
```
|
||||
|
||||
#### Delimiter
|
||||
|
||||
This field is intended to be used in conjunction with the `index` field for partial string replacement.
|
||||
For example, say we have a value:
|
||||
|
||||
`path: my/path/VALUE`
|
||||
|
||||
In our replacement target, we can specify something like:
|
||||
|
||||
```yaml
|
||||
options:
|
||||
delimiter: '/'
|
||||
index: 2
|
||||
```
|
||||
|
||||
and it would replace VALUE, e.g. `path: my/path/NEW_VALUE`.
|
||||
|
||||
#### Index
|
||||
|
||||
This field is intended to be used in conjunction with the `delimiter` field described above for partial string
|
||||
replacement. The default value is 0.
|
||||
|
||||
If the index is out of bounds, behavior depends on whether it is in a source or target. In a source, an index out of bounds
|
||||
will throw an error. For a target, a value less than 0 will cause the target to be prefixed, and a value beyond
|
||||
the length of the split will cause the target to be suffixed.
|
||||
|
||||
If the fields `index` and `delimiter` are specified on sources or targets that are not scalar values (e.g. mapping or list values),
|
||||
kustomize will throw an error.
|
||||
|
||||
#### Field Path format
|
||||
The fieldPath and fieldPaths fields support a format of a '.'-separated path to a value. For example, the default:
|
||||
|
||||
`metadata.name`
|
||||
|
||||
You can escape the '.' one of two ways. For example, say we have the following resource:
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
config.kubernetes.io/local-config: true # this is what we want to target
|
||||
```
|
||||
|
||||
We can express our path:
|
||||
|
||||
1. With a '\\': `metadata.annotations.config\.kubernetes\.io/local-config`
|
||||
|
||||
2. With '[]': `metadata.annotations.[config.kubernetes.io/local-config]`
|
||||
|
||||
Strings are used for mapping nodes. For sequence nodes, we support three options:
|
||||
|
||||
1. Index by number: `spec.template.spec.containers.1.image`
|
||||
|
||||
2. Index by key-value pair: `spec.template.spec.containers.[name=nginx].image`. If the key-value pair matches multiple elements in the sequence node, all matching elements will be targetted.
|
||||
|
||||
3. Index with a wildcard match: `spec.template.spec.containers.*.env.[name=TARGET_ENV].value`. This will target every element in the list.
|
||||
|
||||
|
||||
### Example
|
||||
|
||||
For example, suppose one specifies the name of a k8s Secret object in a container's
|
||||
environment variable as follows:
|
||||
|
||||
`job.yaml`
|
||||
```yaml
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: hello
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- image: myimage
|
||||
name: hello
|
||||
env:
|
||||
- name: SECRET_TOKEN
|
||||
value: SOME_SECRET_NAME
|
||||
```
|
||||
|
||||
Suppose you have the following resources:
|
||||
|
||||
`resources.yaml`
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: my-pod
|
||||
spec:
|
||||
containers:
|
||||
- image: busybox
|
||||
name: myapp-container
|
||||
restartPolicy: OnFailure
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: my-secret
|
||||
```
|
||||
|
||||
To (1) replace the value of SOME_SECRET_NAME with the name of my-secret, and (2) to add
|
||||
a restartPolicy copied from my-pod, you can do the following:
|
||||
|
||||
`kustomization.yaml`
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- resources.yaml
|
||||
- job.yaml
|
||||
|
||||
replacements:
|
||||
- path: my-replacement.yaml
|
||||
- source:
|
||||
kind: Secret
|
||||
name: my-secret
|
||||
targets:
|
||||
- select:
|
||||
name: hello
|
||||
kind: Job
|
||||
fieldPaths:
|
||||
- spec.template.spec.containers.[name=hello].env.[name=SECRET_TOKEN].value
|
||||
```
|
||||
|
||||
`my-replacement.yaml`
|
||||
```yaml
|
||||
source:
|
||||
kind: Pod
|
||||
name: my-pod
|
||||
fieldPath: spec.restartPolicy
|
||||
targets:
|
||||
- select:
|
||||
name: hello
|
||||
kind: Job
|
||||
fieldPaths:
|
||||
- spec.template.spec.restartPolicy
|
||||
options:
|
||||
create: true
|
||||
```
|
||||
|
||||
The output of `kustomize build` will be:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: my-secret
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: hello
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- env:
|
||||
- name: SECRET_TOKEN
|
||||
value: my-secret # this value is copied from my-secret
|
||||
image: myimage
|
||||
name: hello
|
||||
restartPolicy: OnFailure # this value is copied from my-pod
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: my-pod
|
||||
spec:
|
||||
containers:
|
||||
- image: busybox
|
||||
name: myapp-container
|
||||
restartPolicy: OnFailure
|
||||
```
|
||||
@@ -0,0 +1,90 @@
|
||||
---
|
||||
title: "replicas"
|
||||
linkTitle: "replicas"
|
||||
type: docs
|
||||
weight: 19
|
||||
description: >
|
||||
Change the number of replicas for a resource.
|
||||
---
|
||||
|
||||
Given this kubernetes Deployment fragment:
|
||||
|
||||
```yaml
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deployment-name
|
||||
spec:
|
||||
replicas: 3
|
||||
```
|
||||
|
||||
one can change the number of replicas to 5
|
||||
by adding the following to your kustomization:
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
replicas:
|
||||
- name: deployment-name
|
||||
count: 5
|
||||
```
|
||||
|
||||
This field accepts a list, so many resources can
|
||||
be modified at the same time.
|
||||
|
||||
As this declaration does not take in a `kind:` nor a `group:`
|
||||
it will match any `group` and `kind` that has a matching name and
|
||||
that is one of:
|
||||
|
||||
- `Deployment`
|
||||
- `ReplicationController`
|
||||
- `ReplicaSet`
|
||||
- `StatefulSet`
|
||||
|
||||
For more complex use cases, revert to using a patch.
|
||||
|
||||
## Example
|
||||
|
||||
### Input File
|
||||
|
||||
```yaml
|
||||
# deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: the-deployment
|
||||
spec:
|
||||
replicas: 5
|
||||
template:
|
||||
containers:
|
||||
- name: the-container
|
||||
image: registry/container:latest
|
||||
```
|
||||
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
replicas:
|
||||
- name: the-deployment
|
||||
count: 10
|
||||
|
||||
resources:
|
||||
- deployment.yaml
|
||||
```
|
||||
|
||||
### Output
|
||||
```yaml
|
||||
# deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: the-deployment
|
||||
spec:
|
||||
replicas: 10
|
||||
template:
|
||||
containers:
|
||||
- name: the-container
|
||||
image: registry/container:latest
|
||||
```
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
title: "resources"
|
||||
linkTitle: "resources"
|
||||
type: docs
|
||||
weight: 20
|
||||
description: >
|
||||
Resources to include.
|
||||
---
|
||||
|
||||
Each entry in this list must be a path to a _file_, or a path (or URL) referring to another
|
||||
kustomization _directory_, e.g.
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- myNamespace.yaml
|
||||
- sub-dir/some-deployment.yaml
|
||||
- ../../commonbase
|
||||
- github.com/kubernetes-sigs/kustomize/examples/multibases?ref=v1.0.6
|
||||
- deployment.yaml
|
||||
- github.com/kubernets-sigs/kustomize/examples/helloWorld?ref=test-branch
|
||||
```
|
||||
|
||||
Resources will be read and processed in depth-first order.
|
||||
|
||||
Files should contain k8s resources in YAML form. A file may contain multiple resources separated by
|
||||
the document marker `---`. File paths should be specified _relative_ to the directory holding the
|
||||
kustomization file containing the `resources` field.
|
||||
|
||||
Directory specification can be relative, absolute, or part of a URL. URL specifications should
|
||||
follow the [hashicorp URL] format. The directory must contain a `kustomization.yaml` file.
|
||||
|
||||
[hashicorp URL]: https://github.com/hashicorp/go-getter#url-format
|
||||
@@ -0,0 +1,95 @@
|
||||
---
|
||||
title: "secretGenerator"
|
||||
linkTitle: "secretGenerator"
|
||||
type: docs
|
||||
weight: 21
|
||||
description: >
|
||||
Generate Secret resources.
|
||||
---
|
||||
|
||||
Each entry in the argument list results in the creation of one Secret resource (it's a generator of N secrets).
|
||||
|
||||
This works like the [configMapGenerator](/docs/reference/api/kustomization-file/configmapgenerator).
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
secretGenerator:
|
||||
- name: app-tls
|
||||
files:
|
||||
- secret/tls.crt
|
||||
- secret/tls.key
|
||||
type: "kubernetes.io/tls"
|
||||
- name: app-tls-namespaced
|
||||
# you can define a namespace to generate
|
||||
# a secret in, defaults to: "default"
|
||||
namespace: apps
|
||||
files:
|
||||
- tls.crt=catsecret/tls.crt
|
||||
- tls.key=secret/tls.key
|
||||
type: "kubernetes.io/tls"
|
||||
- name: env_file_secret
|
||||
envs:
|
||||
- env.txt
|
||||
type: Opaque
|
||||
- name: secret-with-annotation
|
||||
files:
|
||||
- app-config.yaml
|
||||
type: Opaque
|
||||
options:
|
||||
annotations:
|
||||
app_config: "true"
|
||||
labels:
|
||||
app.kubernetes.io/name: "app2"
|
||||
```
|
||||
|
||||
Secret Resources may be generated much like ConfigMaps can. This includes generating them
|
||||
from literals, files or environment files.
|
||||
|
||||
{{< alert color="success" title="Secret Syntax" >}}
|
||||
Secret type is set using the `type` field.
|
||||
{{< /alert >}}
|
||||
|
||||
## Example
|
||||
|
||||
### File Input
|
||||
|
||||
```yaml
|
||||
# kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
secretGenerator:
|
||||
- name: app-tls
|
||||
files:
|
||||
- "tls.crt"
|
||||
- "tls.key"
|
||||
type: "kubernetes.io/tls"
|
||||
```
|
||||
|
||||
```yaml
|
||||
# tls.crt
|
||||
LS0tLS1CRUd...tCg==
|
||||
```
|
||||
|
||||
```yaml
|
||||
# tls.key
|
||||
LS0tLS1CRUd...0tLQo=
|
||||
```
|
||||
|
||||
### Build Output
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
data:
|
||||
tls.crt: TFMwdExTMUNSVWQuLi50Q2c9PQ==
|
||||
tls.key: TFMwdExTMUNSVWQuLi4wdExRbz0=
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: app-tls-c888dfbhf8
|
||||
type: kubernetes.io/tls
|
||||
```
|
||||
|
||||
{{< alert color="warning" title="Important" >}}
|
||||
It is important to note that the secrets are `base64` encoded
|
||||
{{< /alert >}}
|
||||
@@ -0,0 +1,118 @@
|
||||
---
|
||||
title: "sortOptions"
|
||||
linkTitle: "sortOptions"
|
||||
type: docs
|
||||
weight: 22
|
||||
description: >
|
||||
Change the strategy used to sort resources at the end of the Kustomize build.
|
||||
---
|
||||
|
||||
The `sortOptions` field is used to sort the resources kustomize outputs. It is
|
||||
available in kustomize v5.0.0+.
|
||||
|
||||
IMPORTANT:
|
||||
- Currently, this field is respected only in the top-level Kustomization (that
|
||||
is, the immediate target of `kustomize build`). Any instances of the field in
|
||||
Kustomizations further down the build chain (for example, in bases included
|
||||
through the `resources` field) will be ignored.
|
||||
- This field is the endorsed way to sort resources. It should be used instead of
|
||||
the `--reorder` CLI flag, which is deprecated.
|
||||
|
||||
Currently, we support the following sort options:
|
||||
- `legacy`
|
||||
- `fifo`
|
||||
|
||||
```yaml
|
||||
kind: Kustomization
|
||||
sortOptions:
|
||||
order: legacy | fifo # "legacy" is the default
|
||||
```
|
||||
|
||||
## FIFO Sorting
|
||||
|
||||
In `fifo` order, kustomize does not change the order of resources. They appear
|
||||
in the order they are loaded in `resources`.
|
||||
|
||||
### Example 1: FIFO Sorting
|
||||
|
||||
```yaml
|
||||
kind: Kustomization
|
||||
sortOptions:
|
||||
order: fifo
|
||||
```
|
||||
|
||||
## Legacy Sorting
|
||||
|
||||
The `legacy` sort is the default order, and is used when the sortOrder field is
|
||||
unspecified.
|
||||
|
||||
In `legacy` order, kustomize sorts resources by using two priority lists:
|
||||
- An `orderFirst` list for resources which should be first in the output.
|
||||
- An `orderLast` list for resources which should be last in the output.
|
||||
- Resources not on the lists will appear in between, sorted using their apiVersion and kind fields.
|
||||
|
||||
### Example 2: Legacy Sorting with orderFirst / orderLast lists
|
||||
|
||||
In this example, we use the `legacy` sort order to output `Namespace` objects
|
||||
first and `Deployment` objects last.
|
||||
|
||||
```yaml
|
||||
kind: Kustomization
|
||||
sortOptions:
|
||||
order: legacy
|
||||
legacySortOptions:
|
||||
orderFirst:
|
||||
- Namespace
|
||||
orderLast:
|
||||
- Deployment
|
||||
```
|
||||
|
||||
### Example 3: Default Legacy Sorting
|
||||
|
||||
If you specify `legacy` sort order without any arguments for the lists,
|
||||
kustomize will fall back to the lists we were using before introducing this
|
||||
feature. Since legacy sort is the default, this is also equivalent to not
|
||||
specifying the field at all.
|
||||
|
||||
These two configs are equivalent:
|
||||
|
||||
```yaml
|
||||
kind: Kustomization
|
||||
sortOptions:
|
||||
order: legacy
|
||||
```
|
||||
|
||||
is equivalent to:
|
||||
|
||||
```yaml
|
||||
kind: Kustomization
|
||||
sortOptions:
|
||||
order: legacy
|
||||
legacySortOptions:
|
||||
orderFirst:
|
||||
- Namespace
|
||||
- ResourceQuota
|
||||
- StorageClass
|
||||
- CustomResourceDefinition
|
||||
- ServiceAccount
|
||||
- PodSecurityPolicy
|
||||
- Role
|
||||
- ClusterRole
|
||||
- RoleBinding
|
||||
- ClusterRoleBinding
|
||||
- ConfigMap
|
||||
- Secret
|
||||
- Endpoints
|
||||
- Service
|
||||
- LimitRange
|
||||
- PriorityClass
|
||||
- PersistentVolume
|
||||
- PersistentVolumeClaim
|
||||
- Deployment
|
||||
- StatefulSet
|
||||
- CronJob
|
||||
- PodDisruptionBudget
|
||||
orderLast:
|
||||
- MutatingWebhookConfiguration
|
||||
- ValidatingWebhookConfiguration
|
||||
```
|
||||
335
site/content/en/docs/Reference/API/Kustomization File/vars.md
Normal file
335
site/content/en/docs/Reference/API/Kustomization File/vars.md
Normal file
@@ -0,0 +1,335 @@
|
||||
---
|
||||
title: "vars"
|
||||
linkTitle: "vars"
|
||||
type: docs
|
||||
weight: 23
|
||||
description: >
|
||||
Substitute name references.
|
||||
---
|
||||
|
||||
[replacements]: /docs/reference/api/kustomization-file/replacements/
|
||||
|
||||
{{% pageinfo color="warning" %}}
|
||||
The `vars` field was deprecated in v5.0.0. This field will never be removed from the
|
||||
kustomize.config.k8s.io/v1beta1 Kustomization API, but it will not be included
|
||||
in the kustomize.config.k8s.io/v1 Kustomization API. When Kustomization v1 is available,
|
||||
we will announce the deprecation of the v1beta1 version. There will be at least
|
||||
two releases between deprecation and removal of Kustomization v1beta1 support from the
|
||||
kustomize CLI, and removal itself will happen in a future major version bump.
|
||||
|
||||
Please try to migrate to the
|
||||
the [replacements](/docs/reference/api/kustomization-file/replacements) field. If you are
|
||||
unable to restructure your configuration to use replacements instead of vars, please
|
||||
ask for help in slack or file an issue for guidance.
|
||||
|
||||
We are experimentally attempting to
|
||||
automatically convert `vars` to `replacements` with `kustomize edit fix --vars`. However,
|
||||
converting vars to replacements in this way will potentially overwrite many resource files
|
||||
and the resulting files may not produce the same output when `kustomize build` is run.
|
||||
We recommend doing this in a clean git repository where the change is easy to undo.
|
||||
{{% /pageinfo %}}
|
||||
|
||||
Vars are used to capture text from one resource's field
|
||||
and insert that text elsewhere - a reflection feature.
|
||||
|
||||
For example, suppose one specifies the name of a k8s Service
|
||||
object in a container's command line, and the name of a
|
||||
k8s Secret object in a container's environment variable,
|
||||
so that the following would work:
|
||||
|
||||
```yaml
|
||||
containers:
|
||||
- image: myimage
|
||||
command: ["start", "--host", "$(MY_SERVICE_NAME)"]
|
||||
env:
|
||||
- name: SECRET_TOKEN
|
||||
value: $(SOME_SECRET_NAME)
|
||||
```
|
||||
|
||||
To do so, add an entry to `vars:` as follows:
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
vars:
|
||||
- name: SOME_SECRET_NAME
|
||||
objref:
|
||||
kind: Secret
|
||||
name: my-secret
|
||||
apiVersion: v1
|
||||
- name: MY_SERVICE_NAME
|
||||
objref:
|
||||
kind: Service
|
||||
name: my-service
|
||||
apiVersion: v1
|
||||
fieldref:
|
||||
fieldpath: metadata.name
|
||||
- name: ANOTHER_DEPLOYMENTS_POD_RESTART_POLICY
|
||||
objref:
|
||||
kind: Deployment
|
||||
name: my-deployment
|
||||
apiVersion: apps/v1
|
||||
fieldref:
|
||||
fieldpath: spec.template.spec.restartPolicy
|
||||
```
|
||||
|
||||
A var is a tuple of variable name, object
|
||||
reference and field reference within that object.
|
||||
That's where the text is found.
|
||||
|
||||
The field reference is optional; it defaults to
|
||||
`metadata.name`, a normal default, since kustomize
|
||||
is used to generate or modify the names of
|
||||
resources.
|
||||
|
||||
At time of writing, only string type fields are
|
||||
supported. No ints, bools, arrays etc. It's not
|
||||
possible to, say, extract the name of the image in
|
||||
container number 2 of some pod template.
|
||||
|
||||
A variable reference, i.e. the string '$(FOO)',
|
||||
can only be placed in particular fields of
|
||||
particular objects as specified by kustomize's
|
||||
configuration data.
|
||||
|
||||
The default config data for vars is at [/api/konfig/builtinpluginconsts/varreference.go](https://github.com/kubernetes-sigs/kustomize/blob/master/api/konfig/builtinpluginconsts/varreference.go)
|
||||
Long story short, the default targets are all
|
||||
container command args and env value fields.
|
||||
|
||||
Vars should _not_ be used for inserting names in
|
||||
places where kustomize is already handling that
|
||||
job. E.g., a Deployment may reference a ConfigMap
|
||||
by name, and if kustomize changes the name of a
|
||||
ConfigMap, it knows to change the name reference
|
||||
in the Deployment.
|
||||
|
||||
### Convert vars to replacements
|
||||
|
||||
There are plans to deprecate vars, so we recommend migration to [replacements] as early as possible.
|
||||
|
||||
#### Simple migration example
|
||||
Let's first take a simple example of how to manually do this conversion. Suppose we have a container
|
||||
referencing secret (similar to the above example):
|
||||
|
||||
`pod.yaml`
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: my-pod
|
||||
spec:
|
||||
containers:
|
||||
- image: myimage
|
||||
name: hello
|
||||
env:
|
||||
- name: SECRET_TOKEN
|
||||
value: $(SOME_SECRET_NAME)
|
||||
```
|
||||
|
||||
and we are using vars as follows:
|
||||
|
||||
`kustomization.yaml`
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- pod.yaml
|
||||
- secret.yaml
|
||||
|
||||
vars:
|
||||
- name: SOME_SECRET_NAME
|
||||
objref:
|
||||
kind: Secret
|
||||
name: my-secret
|
||||
apiVersion: v1
|
||||
```
|
||||
|
||||
In order to convert `vars` to `replacements`, we have to:
|
||||
1. Replace every instance of $(SOME_SECRET_NAME) with any arbitrary placeholder value.
|
||||
2. Convert the vars `objref` field to a [replacements] `source` field.
|
||||
3. Replace the vars `name` fied with a [replacements] `targets` field that points to
|
||||
every instance of the placeholder value in step 1.
|
||||
|
||||
In our simple example here, this would look like the following:
|
||||
|
||||
`pod.yaml`
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: my-pod
|
||||
spec:
|
||||
containers:
|
||||
- image: myimage
|
||||
name: hello
|
||||
env:
|
||||
- name: SECRET_TOKEN
|
||||
value: SOME_PLACEHOLDER_VALUE
|
||||
```
|
||||
|
||||
`kustomization.yaml`
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- pod.yaml
|
||||
- secret.yaml
|
||||
|
||||
replacements:
|
||||
- source:
|
||||
kind: Secret
|
||||
name: my-secret
|
||||
version: v1
|
||||
targets:
|
||||
- select:
|
||||
kind: Pod
|
||||
name: my-pod
|
||||
fieldPaths:
|
||||
- spec.containers.[name=hello].env.[name=SECRET_TOKEN].value
|
||||
```
|
||||
|
||||
#### More complex migration example
|
||||
|
||||
Let's take a more complex usage of vars and convert it to [replacements]. We are going
|
||||
to convert the vars in the [wordpress example](https://github.com/kubernetes-sigs/kustomize/tree/master/examples/wordpress)
|
||||
to replacements.
|
||||
|
||||
The wordpress example has the following directory structure:
|
||||
|
||||
```
|
||||
.
|
||||
├── README.md
|
||||
├── kustomization.yaml
|
||||
├── mysql
|
||||
│ ├── deployment.yaml
|
||||
│ ├── kustomization.yaml
|
||||
│ ├── secret.yaml
|
||||
│ └── service.yaml
|
||||
├── patch.yaml
|
||||
└── wordpress
|
||||
├── deployment.yaml
|
||||
├── kustomization.yaml
|
||||
└── service.yaml
|
||||
```
|
||||
|
||||
where `patch.yaml` has the following contents:
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: wordpress
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
initContainers:
|
||||
- name: init-command
|
||||
image: debian
|
||||
command: ["/bin/sh"]
|
||||
args: ["-c", "echo $(WORDPRESS_SERVICE); echo $(MYSQL_SERVICE)"]
|
||||
containers:
|
||||
- name: wordpress
|
||||
env:
|
||||
- name: WORDPRESS_DB_HOST
|
||||
value: $(MYSQL_SERVICE)
|
||||
- name: WORDPRESS_DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: mysql-pass
|
||||
key: password
|
||||
```
|
||||
|
||||
and the top level `kustomization.yaml` has the following contents:
|
||||
|
||||
```
|
||||
resources:
|
||||
- wordpress
|
||||
- mysql
|
||||
patchesStrategicMerge:
|
||||
- patch.yaml
|
||||
namePrefix: demo-
|
||||
|
||||
vars:
|
||||
- name: WORDPRESS_SERVICE
|
||||
objref:
|
||||
kind: Service
|
||||
name: wordpress
|
||||
apiVersion: v1
|
||||
- name: MYSQL_SERVICE
|
||||
objref:
|
||||
kind: Service
|
||||
name: mysql
|
||||
apiVersion: v1
|
||||
```
|
||||
|
||||
In this example, the patch is used to:
|
||||
- Add an initial container to show the mysql service name
|
||||
- Add environment variable that allow wordpress to find the mysql database
|
||||
|
||||
We can convert vars to replacements in this more complex case too, by taking the same steps as
|
||||
the previous example. To do this, we can change the contents of `patch.yaml` to:
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: wordpress
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
initContainers:
|
||||
- name: init-command
|
||||
image: debian
|
||||
command: ["/bin/sh"]
|
||||
args: ["-c", "echo", "WORDPRESS_SERVICE", ";", "echo", "MYSQL_SERVICE"]
|
||||
containers:
|
||||
- name: wordpress
|
||||
env:
|
||||
- name: WORDPRESS_DB_HOST
|
||||
value: MYSQL_SERVICE
|
||||
- name: WORDPRESS_DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: mysql-pass
|
||||
key: password
|
||||
|
||||
```
|
||||
|
||||
Then, in our kustomization, we can have our replacements:
|
||||
|
||||
`kustomization.yaml`
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- wordpress
|
||||
- mysql
|
||||
patchesStrategicMerge:
|
||||
- patch.yaml
|
||||
namePrefix: demo-
|
||||
|
||||
replacements:
|
||||
- source:
|
||||
name: demo-wordpress
|
||||
kind: Service
|
||||
version: v1
|
||||
targets:
|
||||
- select:
|
||||
kind: Deployment
|
||||
name: demo-wordpress
|
||||
fieldPaths:
|
||||
- spec.template.spec.initContainers.[name=init-command].args.2
|
||||
- source:
|
||||
name: demo-mysql
|
||||
kind: Service
|
||||
version: v1
|
||||
targets:
|
||||
- select:
|
||||
kind: Deployment
|
||||
name: demo-wordpress
|
||||
fieldPaths:
|
||||
- spec.template.spec.initContainers.[name=init-command].args.5
|
||||
- spec.template.spec.containers.[name=wordpress].env.[name=WORDPRESS_DB_HOST].value
|
||||
```
|
||||
@@ -4,5 +4,75 @@ linkTitle: "CLI"
|
||||
weight: 3
|
||||
date: 2023-07-28
|
||||
description: >
|
||||
The command line tools to interact with Kustomize.
|
||||
---
|
||||
Reference for the Command Line Interface.
|
||||
---
|
||||
|
||||
This overview covers `kustomize` syntax, describes the command operations, and provides common examples.
|
||||
|
||||
## Syntax
|
||||
Use the following syntax to run `kustomize` commands from your terminal window:
|
||||
|
||||
```bash
|
||||
kustomize [command]
|
||||
```
|
||||
|
||||
The `command` flag specifies the operation that you want to perform, for example `create`, `build`, `cfg`.
|
||||
|
||||
If you need help, run `kustomize help` from the terminal window.
|
||||
|
||||
## Operations
|
||||
The following table includes short descriptions and the general syntax for all the `kustomize` operations.
|
||||
|
||||
Operation | Syntax | Description
|
||||
--- | --- | ---
|
||||
build | `kustomize build DIR [flags]` | Build a kustomization target from a directory or URL.
|
||||
cfg | `kustomize cfg [command]` | Commands for reading and writing configuration.
|
||||
completion | `kustomize completion` [bash\|zsh\|fish\|powershell] | Generate shell completion script.
|
||||
create | `kustomize create [flags]` | Create a new kustomization in the current directory.
|
||||
edit | `kustomize edit [command]` | Edits a kustomization file.
|
||||
fn | `kustomize fn [command]` | Commands for running functions against configuration.
|
||||
localize | `kustomize localize [target [destination]] [flags]` | [Alpha] Creates localized copy of target kustomization root at destination.
|
||||
version | `kustomize version [flags]` | Prints the kustomize version.
|
||||
|
||||
## Examples: Common Operations
|
||||
Use the following set of examples to help you familiarize yourself with running the commonly used `kustomize` operations:
|
||||
|
||||
`kustomize build` - Build a kustomization target from a directory or URL.
|
||||
|
||||
```bash
|
||||
# Build the current working directory
|
||||
kustomize build
|
||||
|
||||
# Build some shared configuration directory
|
||||
kustomize build /home/config/production
|
||||
|
||||
# Build from github
|
||||
kustomize build https://github.com/kubernetes-sigs/kustomize.git/examples/helloWorld?ref=v1.0.6
|
||||
```
|
||||
|
||||
`kustomize create` - Create a new kustomization in the current directory.
|
||||
```bash
|
||||
# Create an empty kustomization.yaml file
|
||||
kustomize create
|
||||
|
||||
# Create a new overlay from the base '../base".
|
||||
kustomize create --resources ../base
|
||||
|
||||
# Create a new kustomization detecting resources in the current directory.
|
||||
kustomize create --autodetect
|
||||
|
||||
# Create a new kustomization with multiple resources and fields set.
|
||||
kustomize create --resources deployment.yaml,service.yaml,../base --namespace staging --nameprefix acme-
|
||||
```
|
||||
|
||||
`kustomize edit` - Edits a kustomization file.
|
||||
```bash
|
||||
# Adds a configmap to the kustomization file
|
||||
kustomize edit add configmap NAME --from-literal=k=v
|
||||
|
||||
# Sets the nameprefix field
|
||||
kustomize edit set nameprefix <prefix-value>
|
||||
|
||||
# Sets the namesuffix field
|
||||
kustomize edit set namesuffix <suffix-value>
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user