├── CONTRIBUTING.md ├── LICENSE ├── LICENSE_TEMPLATE ├── Makefile ├── OWNERS ├── OWNERS_ALIASES ├── README.md ├── RELEASING.md ├── SECURITY.md ├── SECURITY_CONTACTS ├── code-of-conduct.md ├── krm-functions ├── Makefile ├── README.md ├── scripts │ ├── build-local.sh │ └── unit-test.sh └── sig-cli │ ├── OWNERS │ ├── README.md │ └── render-helm-chart │ ├── Dockerfile │ ├── README.md │ ├── examples │ ├── render-helm-chart-kustomize-inline-values │ │ ├── .expected │ │ │ ├── diff.patch │ │ │ └── exec.sh │ │ ├── README.md │ │ └── kustomization.yaml │ └── render-helm-chart-kustomize-values-files │ │ ├── .expected │ │ ├── diff.patch │ │ └── exec.sh │ │ ├── .krmignore │ │ ├── README.md │ │ └── kustomization.yaml │ ├── go.mod │ ├── go.sum │ ├── main.go │ ├── main_test.go │ └── third_party │ ├── README.md │ └── sigs.k8s.io │ └── kustomize │ └── api │ ├── builtins │ └── HelmChartInflationGenerator.go │ └── types │ └── helmchartargs.go ├── publishers ├── README.md └── sig-cli │ ├── OWNERS │ ├── README.md │ ├── catalogs │ └── v20220225.yaml │ └── functions │ └── render-helm-chart.yaml ├── site └── README.md ├── test.sh └── tests ├── e2e_test.go ├── go.mod ├── go.sum ├── testutils.go └── validate-metadata_test.go /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Welcome to Kubernetes. We are excited about the prospect of you joining our [community](https://git.k8s.io/community)! The Kubernetes community abides by the CNCF [code of conduct](code-of-conduct.md). Here is an excerpt: 4 | 5 | _As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities._ 6 | 7 | ## Getting Started 8 | 9 | ### Repo layout 10 | 11 | ``` 12 | ├── publishers # Home for all functions metadata 13 | │ ├── kustomize 14 | │ │ ├── functions 15 | │ │ │ ├── fn-foo.yaml 16 | │ │ │ ├── fn-bar.yaml 17 | │ │ │ └── README.md 18 | │ │ ├── catalogs 19 | │ │ │ ├── v20220225.yaml 20 | │ │ │ ├── v20220101.yaml 21 | │ │ │ └── README.md 22 | │ │ └── OWNERS # OWNERS of the publisher 23 | │ ├── kubeflow 24 | │ ├── sig-cli 25 | │ └── OWNERS # OWNERS to approve new publishers 26 | ├── krm-functions # Home for in-tree functions source code 27 | │ ├── Makefile 28 | │ ├── kustomize 29 | │ │ ├── fn-foo 30 | │ │ ├── README.md 31 | │ │ └── OWNERS # OWNERS to approve code change to the function 32 | │ └── sig-cli 33 | ├── site 34 | ├── Makefile 35 | └── OWNERS 36 | ``` 37 | 38 | ## Contributing in-tree KRM function source code 39 | 40 | To contribute KRM function source code, so that it can be managed and released by this repo, follow the instructions 41 | in the [krm-functions directory]((https://github.com/kubernetes-sigs/krm-functions-registry/tree/main/krm-functions)) 42 | 43 | 44 | ## Publishing KRM function metadata in-tree and out-of-tree functions 45 | 46 | To publish KRM function metadata, independently of where the source code lives, follow the instructions 47 | in the [publishers directory](https://github.com/kubernetes-sigs/krm-functions-registry/tree/main/publishers). 48 | 49 | ## General Kubernetes Contributing docs 50 | 51 | We have full documentation on how to get started contributing here: 52 | 53 | - [Contributor License Agreement](https://git.k8s.io/community/CLA.md) Kubernetes projects require that you sign a Contributor License Agreement (CLA) before we can accept your pull requests 54 | - [Kubernetes Contributor Guide](https://git.k8s.io/community/contributors/guide) - Main contributor documentation, or you can just jump directly to the [contributing section](https://git.k8s.io/community/contributors/guide#contributing) 55 | - [Contributor Cheat Sheet](https://git.k8s.io/community/contributors/guide/contributor-cheatsheet) - Common resources for existing developers 56 | 57 | ## Mentorship 58 | 59 | - [Mentoring Initiatives](https://git.k8s.io/community/mentoring) - We have a diverse set of mentorship programs available that are always looking for volunteers! 60 | 61 | [Catalog KEP]: https://github.com/kubernetes/enhancements/tree/master/keps/sig-cli/2906-kustomize-function-catalog#function-metadata-schema 62 | 63 | ## Contact Information 64 | - [Slack channel](https://kubernetes.slack.com/messages/sig-cli-krm-functions) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE_TEMPLATE: -------------------------------------------------------------------------------- 1 | Copyright {{.Year}} {{.Holder}} 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 The Kubernetes Authors. 2 | # SPDX-License-Identifier: Apache-2.0 3 | # 4 | # Makefile for KRM functions registry. 5 | 6 | MYGOBIN = $(shell go env GOBIN) 7 | ifeq ($(MYGOBIN),) 8 | MYGOBIN = $(shell go env GOPATH)/bin 9 | endif 10 | export PATH := $(MYGOBIN):$(PATH) 11 | 12 | # Run all tests in this repo for in-tree and out-of-tree functions 13 | all: install-tools license validate-metadata test-in-tree 14 | 15 | ## Run all unit tests and e2e tests for in-tree functions 16 | test-in-tree: e2e-test unit-test lint 17 | 18 | # Run all the e2e tests for in-tree functions 19 | e2e-test: build-local $(MYGOBIN)/kustomize 20 | cd tests; \ 21 | go test -v -run TestExamples 22 | 23 | # Validate the metadata for all published functions 24 | validate-metadata: 25 | cd tests; \ 26 | go test -v -run TestValidateMetadata 27 | 28 | # Run all unit tests for in-tree functions 29 | unit-test: 30 | cd krm-functions && $(MAKE) unit-test 31 | 32 | # Build all in-tree functions locally 33 | build-local: 34 | cd krm-functions && $(MAKE) build-local 35 | 36 | # Add project licenses to all code files in here 37 | .PHONY: license 38 | license: $(MYGOBIN)/addlicense 39 | ( find . -type f -exec bash -c "$(MYGOBIN)/addlicense -y 2022 -c 'The Kubernetes Authors.' -f LICENSE_TEMPLATE {}" ";" ) 40 | 41 | # Lint all in-tree functions 42 | lint: 43 | cd tests; golangci-lint run ./... 44 | cd krm-functions && find . -type f -name go.mod -execdir golangci-lint run ./... \; 45 | 46 | # Install tools needed to run tests 47 | install-tools: \ 48 | install-kustomize \ 49 | install-addlicense \ 50 | install-golangci-lint \ 51 | install-helm 52 | 53 | # Install kustomize 54 | install-kustomize: 55 | ifeq (, $(shell which kustomize)) 56 | curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash; \ 57 | mv ./kustomize $(MYGOBIN)/kustomize 58 | endif 59 | 60 | # Install the addlicense tool 61 | install-addlicense: 62 | go install github.com/google/addlicense@v1.0.0 63 | 64 | # Install the lint tool 65 | install-golangci-lint: 66 | go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.44.0 67 | 68 | # Install helm v3 (needed for sig-cli/render-helm-chart) 69 | install-helm: 70 | ifeq (, $(shell which helm)) 71 | curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash 72 | endif 73 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | # See the OWNERS docs at https://go.k8s.io/owners 2 | 3 | approvers: 4 | - krm-functions-registry-owners 5 | - krm-functions-registry-maintainers 6 | -------------------------------------------------------------------------------- /OWNERS_ALIASES: -------------------------------------------------------------------------------- 1 | # See the OWNERS docs at https://go.k8s.io/owners#owners_aliases 2 | 3 | aliases: 4 | krm-functions-registry-owners: 5 | - jeremyrickard 6 | - KnVerey 7 | - mengqiy 8 | 9 | krm-functions-registry-maintainers: 10 | - natasha41575 11 | 12 | sig-cli-functions-approvers: 13 | - jeremyrickard 14 | - KnVerey 15 | - mengqiy 16 | - natasha41575 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # krm-functions-registry 2 | 3 | Public registry of KRM functions. This repo hosts a centralized index for KRM 4 | functions and donated source code for some KRM functions. 5 | 6 | ## Background, contributing, and releasing 7 | 8 | [KEP] 9 | 10 | [Open an Issue] 11 | 12 | [Contributor Guide] 13 | 14 | [Release Process] 15 | 16 | ## Community, discussion, contribution, and support 17 | 18 | Learn how to engage with the Kubernetes community on the [community page](http://kubernetes.io/community/). 19 | 20 | You can reach the maintainers of this project at: 21 | 22 | - [Slack](http://slack.k8s.io/) 23 | - [Mailing List](https://groups.google.com/forum/#!forum/kubernetes-dev) 24 | 25 | ### Code of conduct 26 | 27 | Participation in the Kubernetes community is governed by the [Kubernetes Code of Conduct](code-of-conduct.md). 28 | 29 | [KEP]: https://github.com/kubernetes/enhancements/tree/master/keps/sig-cli/2985-public-krm-functions-registry 30 | [Contributor Guide]: CONTRIBUTING.md 31 | [Release Process]: RELEASING.md 32 | [Open an Issue]: https://github.com/kubernetes-sigs/krm-functions-registry/issues 33 | 34 | [owners]: https://git.k8s.io/community/contributors/guide/owners.md 35 | [Creative Commons 4.0]: https://git.k8s.io/website/LICENSE 36 | -------------------------------------------------------------------------------- /RELEASING.md: -------------------------------------------------------------------------------- 1 | # Release Process \[TODO\] 2 | 3 | This doc will cover the release process for the in-tree KRM 4 | functions whose source code is stored here. 5 | 6 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Security Announcements 4 | 5 | Join the [kubernetes-security-announce] group for security and vulnerability announcements. 6 | 7 | You can also subscribe to an RSS feed of the above using [this link][kubernetes-security-announce-rss]. 8 | 9 | ## Reporting a Vulnerability 10 | 11 | Instructions for reporting a vulnerability can be found on the 12 | [Kubernetes Security and Disclosure Information] page. 13 | 14 | ## Supported Versions 15 | 16 | Information about supported Kubernetes versions can be found on the 17 | [Kubernetes version and version skew support policy] page on the Kubernetes website. 18 | 19 | [kubernetes-security-announce]: https://groups.google.com/forum/#!forum/kubernetes-security-announce 20 | [kubernetes-security-announce-rss]: https://groups.google.com/forum/feed/kubernetes-security-announce/msgs/rss_v2_0.xml?num=50 21 | [Kubernetes version and version skew support policy]: https://kubernetes.io/docs/setup/release/version-skew-policy/#supported-versions 22 | [Kubernetes Security and Disclosure Information]: https://kubernetes.io/docs/reference/issues-security/security/#report-a-vulnerability 23 | -------------------------------------------------------------------------------- /SECURITY_CONTACTS: -------------------------------------------------------------------------------- 1 | # Defined below are the security contacts for this repo. 2 | # 3 | # They are the contact point for the Product Security Committee to reach out 4 | # to for triaging and handling of incoming issues. 5 | # 6 | # The below names agree to abide by the 7 | # [Embargo Policy](https://git.k8s.io/security/private-distributors-list.md#embargo-policy) 8 | # and will be removed and replaced if they violate that agreement. 9 | # 10 | # DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE 11 | # INSTRUCTIONS AT https://kubernetes.io/security/ 12 | 13 | jeremyrickard 14 | KnVerey 15 | mengqiy 16 | -------------------------------------------------------------------------------- /code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Kubernetes Community Code of Conduct 2 | 3 | Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md) 4 | -------------------------------------------------------------------------------- /krm-functions/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 The Kubernetes Authors. 2 | # SPDX-License-Identifier: Apache-2.0 3 | # 4 | # Makefile for in-tree functions. 5 | 6 | # Build all in-tree functions locally if function name not provided 7 | # Otherwise, just build that function locally. 8 | build-local: 9 | ./scripts/build-local.sh $(FUNCTION_NAME) 10 | 11 | # Run all unit tests for in-tree functions 12 | unit-test: 13 | ./scripts/unit-test.sh 14 | -------------------------------------------------------------------------------- /krm-functions/README.md: -------------------------------------------------------------------------------- 1 | # KRM Functions 2 | 3 | This directory is the home for the source code for all in-tree functions that are maintained and 4 | released by this repository. 5 | 6 | ## Requirements 7 | 8 | By donating a function's source code to this repo, you are donating the function to SIG-CLI. We cannot 9 | accept 3rd party functions as in-tree functions. 10 | 11 | ## Files 12 | 13 | Each publisher will need to create their own subdirectory `krm-functions/{PUBLISHER}/` 14 | in this directory to store their functions source code, under . For example, SIG-CLI sponsored functions are located 15 | under `krm-functions/sig-cli/`. 16 | 17 | Each function must be in its own subdirectory `krm-functions/{PUBLISHER}/{FUNCTION NAME}/`. This directory should 18 | contain: 19 | - An OWNERS file to approve code changes to the function. 20 | - A README.md file to provide a user guide for the function. 21 | - Source code and unit tests. 22 | - A Dockerfile that describes how to build the function image. 23 | - An `examples/` directory. An `examples/` directory. Examples that will serve both as examples for functions and as e2e tests. Each example should have its 24 | own subdirectory `krm-functions/{PUBLISHER}/{FUNCTION NAME}/examples/{EXAMPLE_NAME}/`, and this directory should contain: 25 | - A README.md file that serves as a guide for the example. 26 | - A subdirectory `.expected`. This should contain two files: 27 | - `exec.sh`: A script that will run your example. This script will be run on the example directory it is in. This can 28 | be something as simple as `kustomize build --enable-alpha-plugins > resources.yaml`. 29 | - `diff.patch`: This file should contain the expected diff between the original example directory files and the files 30 | after `exec.sh` is run. 31 | - Any additional files needed for your examples to run. For example, if you are running `kustomize build` in your `exec.sh` 32 | script, you will need a kustomization file. 33 | 34 | An example of this is SIG-CLI's [render-helm-chart](https://github.com/kubernetes-sigs/krm-functions-registry/tree/main/krm-functions/sig-cli/render-helm-chart) 35 | function. 36 | -------------------------------------------------------------------------------- /krm-functions/scripts/build-local.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # 3 | # Copyright 2022 The Kubernetes Authors 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | function build_image { 18 | registry="us.gcr.io/k8s-artifacts-prod/krm-functions" 19 | fn_name=`basename "${1}"` 20 | docker build -t "${registry}/${fn_name}:unstable" -f "${1}"/Dockerfile "${1}" 21 | } 22 | 23 | for d in */ ; do 24 | if [ $d != "scripts/" ]; then 25 | for e in "$d"*/ ; do 26 | fn_name=`basename "${e}"` 27 | if [ $fn_name = $1 ] || [ -z "${1}" ]; then 28 | echo building function $fn_name... 29 | build_image "${e::${#e}-1}" 30 | fi 31 | done 32 | fi 33 | done 34 | -------------------------------------------------------------------------------- /krm-functions/scripts/unit-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright 2022 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -e 18 | 19 | for d in */ ; do 20 | if [ $d != "scripts/" ]; then 21 | for e in "$d"*/ ; do ( 22 | echo running unit tests for "$e" ... 23 | cd "$e" 24 | go test -cover -v ./... 25 | ) 26 | done 27 | fi 28 | done 29 | -------------------------------------------------------------------------------- /krm-functions/sig-cli/OWNERS: -------------------------------------------------------------------------------- 1 | # See the OWNERS docs at https://go.k8s.io/owners 2 | 3 | approvers: 4 | - sig-cli-functions-approvers 5 | -------------------------------------------------------------------------------- /krm-functions/sig-cli/README.md: -------------------------------------------------------------------------------- 1 | # KRM functions - SIG CLI 2 | 3 | This directory contains in-tree SIG-CLI sponsored and authored KRM functions. -------------------------------------------------------------------------------- /krm-functions/sig-cli/render-helm-chart/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM golang:1.17-alpine3.13 16 | ENV CGO_ENABLED=0 17 | WORKDIR /go/src/ 18 | 19 | COPY go.mod go.sum ./ 20 | RUN go mod download 21 | RUN go mod tidy 22 | 23 | COPY . . 24 | RUN go build -o /usr/local/bin/function ./ 25 | 26 | RUN apk update && apk add --no-cache curl 27 | ARG HELM_VERSION="v3.8.0" 28 | RUN curl -fsSL -o /helm-${HELM_VERSION}-linux-amd64.tar.gz https://get.helm.sh/helm-${HELM_VERSION}-linux-amd64.tar.gz && \ 29 | tar -zxvf /helm-${HELM_VERSION}-linux-amd64.tar.gz && \ 30 | mv ./linux-amd64/helm /usr/local/bin/helm 31 | 32 | ############################################# 33 | 34 | FROM alpine:3.13 35 | COPY --from=0 /usr/local/bin/function /usr/local/bin/function 36 | COPY --from=0 /usr/local/bin/helm /usr/local/bin/helm 37 | 38 | ENV PATH /usr/local/bin:$PATH 39 | ENV HELM_PATH_CACHE /var/cache 40 | ENV HELM_CONFIG_HOME /tmp/helm/config 41 | ENV HELM_CACHE_HOME /tmp/helm/cache 42 | 43 | ENTRYPOINT ["function"] -------------------------------------------------------------------------------- /krm-functions/sig-cli/render-helm-chart/README.md: -------------------------------------------------------------------------------- 1 | # render-helm-chart 2 | 3 | ## Overview 4 | 5 | 6 | 7 | The `render-helm-chart` function renders a local or remote Helm chart. 8 | 9 | 10 | 11 | Helm is a package manager for kubernetes that uses a packaging format 12 | called charts. A chart is a collection of files within a directory, which 13 | contain templates, CRDs, values, and metadata. 14 | 15 | This function renders charts by using the [helm template command], 16 | so that helm charts can be rendered without needing to install the 17 | helm binary directly. 18 | 19 | You can learn more about helm [here][helm] and more about helm 20 | charts [here][charts]. 21 | 22 | ## Usage 23 | 24 | This function can be used with any KRM function orchestrators such to render a specified helm chart. 25 | To run the function with kustomize, the `network` field is needed for remote charts and the `mounts` 26 | field is needed for local charts. 27 | 28 | ### FunctionConfig 29 | 30 | There are 2 kinds of `functionConfig` supported by this function: 31 | 32 | - `ConfigMap` 33 | - A custom resource of kind `RenderHelmChart` 34 | 35 | Many of the fields in each functionConfig map directly to flag options provided by `helm template`. 36 | 37 | #### `ConfigMap` 38 | To use a `ConfigMap` as the `functionConfig`, the desired parameters must be 39 | specified in the `data` field: 40 | 41 | ```yaml 42 | data: 43 | chartHome: string 44 | configHome: string 45 | name: string 46 | version: string 47 | repo: string 48 | releaseName: string 49 | namespace: string 50 | nameTemplate: string 51 | includeCRDs: string 52 | skipTests: string 53 | valuesFile: string 54 | ``` 55 | 56 | 57 | | Field | Description | Example 58 | | -----------: | ----------- | ----------- 59 | `chartHome` | A filepath to a directory of charts. The function will look for the chart in this local directory before attempting to pull the chart from a specified repo. Defaults to "tmp/charts". When run in a container, this path MUST have the prefix "tmp/". | tmp/charts 60 | `configHome` | Defines a value that the function should pass to helm via the HELM_CONFIG_HOME environment variable. If omitted, {tmpDir}/helm is used, where {tmpDir} is some temporary directory created by the function for the benefit of helm. This option is not supported when running in a container. It is supported only in exec mode (e.g. with kustomize) | /tmp/helm/config 61 | `name` | The name of the chart | minecraft 62 | `version` | The version of the chart | 3.1.3 63 | `repo` | A URL locating the chart on the internet | https://itzg.github.io/minecraft-server-charts 64 | `releaseName` | Replaces RELEASE_NAME in the chart template output | test 65 | `namespace` | Sets the target namespace for a release (`.Release.Namespace` in the template) | my-namespace 66 | `nameTemplate` | Specify the template used to name the release | gatekeeper 67 | `includeCRDs` | Specifies if Helm should also generate CustomResourceDefinitions. Legal values: "true", "false" (default). | "true" 68 | `skipTests` | If set, skip tests from templated output. Legal values: "true", "false" (default). | "true" 69 | `valuesFile` | valuesFile is a remote or local file path to a values file to use instead of the default values that accompanied the chart. The default values are in '{chartHome}/{name}/values.yaml', where `chartHome` and `name` are the parameters defined above. | Using a local values file: path/to/your/values.yaml

Using a remote values file: https://raw.githubusercontent.com/config-sync-examples/helm-components/main/cert-manager-values.yaml 70 | 71 | 72 | #### `RenderHelmChart` 73 | A `functionConfig` of kind `RenderHelmChart` has the following supported parameters: 74 | 75 | ```yaml 76 | helmGlobals: 77 | chartHome: string 78 | configHome: string 79 | helmCharts: 80 | - chartArgs: 81 | name: string 82 | version: string 83 | repo: string 84 | templateOptions: 85 | apiVersions: []string 86 | releaseName: string 87 | namespace: string 88 | nameTemplate: string 89 | includeCRDs: bool 90 | skipTests: bool 91 | values: 92 | valuesFiles: []string 93 | valuesInline: map[string]interface{} 94 | valuesMerge: string 95 | ``` 96 | 97 | | Field | Description | Example 98 | | -----------: | ----------- | ----------- 99 | `helmGlobals` | Parameters applied to all Helm charts 100 | `helmCharts` | An array of helm chart parameters 101 | `chartArgs` | Arguments that describe the chart being rendered. 102 | `templateOptions` | A collection of fields that map to flag options of `helm template`. 103 | `chartHome` | A filepath to a directory of charts. The function will look for the chart in this local directory before attempting to pull the chart from a specified repo. Defaults to "tmp/charts". When run in a container, this path MUST have the prefix "tmp/". | tmp/charts 104 | `configHome` | Defines a value that the function should pass to helm via the HELM_CONFIG_HOME environment variable. If omitted, {tmpDir}/helm is used, where {tmpDir} is some temporary directory created by the function for the benefit of helm. This option is not supported when running in a container. It is supported only in exec mode (e.g. with kustomize) | /tmp/helm/config 105 | `name` | The name of the chart | minecraft 106 | `version` | The version of the chart | 3.1.3 107 | `repo` | A URL locating the chart on the internet | https://itzg.github.io/minecraft-server-charts 108 | `apiVersions` | Kubernetes api versions used for Capabilities.APIVersions | acme.cert-manager.io/v1 109 | `releaseName` | Replaces RELEASE_NAME in the chart template output | test 110 | `namespace` | Sets the target namespace for a release (`.Release.Namespace` in the template) | my-namespace 111 | `nameTemplate` | Specify the template used to name the release | gatekeeper 112 | `includeCRDs` | Specifies if Helm should also generate CustomResourceDefinitions. Legal values: "true", "false" (default). | "true" 113 | `skipTests` | If set, skip tests from templated output. Legal values: "true", "false" (default). | "true" 114 | `values` | Values to use instead of the default values that accompany the chart. This can be defined inline or in a file. 115 | `valuesInline` | Values defined inline to use instead of default values that accompany the chart | global:
  enabled: false
tests:
  enabled: false 116 | `valuesFiles` | Remote or local filepaths to use instead of the default values that accompanied the chart. The default values are in '{chartHome}/{name}/values.yaml', where `chartHome` and `name` are the parameters defined above. | Using a local values file: path/to/your/values.yaml

Using a remote values file: https://raw.githubusercontent.com/config-sync-examples/helm-components/main/cert-manager-values.yaml 117 | `valuesMerge` | ValuesMerge specifies how to treat ValuesInline with respect to ValuesFiles. Legal values: 'merge', 'override' (default), 'replace'. | replace 118 | 119 | [helm]: https://helm.sh/ 120 | [charts]: https://helm.sh/docs/topics/charts/ 121 | [helm template command]: https://helm.sh/docs/helm/helm_template/ 122 | -------------------------------------------------------------------------------- /krm-functions/sig-cli/render-helm-chart/examples/render-helm-chart-kustomize-inline-values/.expected/diff.patch: -------------------------------------------------------------------------------- 1 | diff --git a/resources.yaml b/resources.yaml 2 | new file mode 100644 3 | index 0000000..e2e869b 4 | --- /dev/null 5 | +++ b/resources.yaml 6 | @@ -0,0 +1,127 @@ 7 | +apiVersion: rbac.authorization.k8s.io/v1 8 | +kind: Role 9 | +metadata: 10 | + name: moria-ocp-pipeline 11 | + namespace: mynamespace 12 | +rules: 13 | +- apiGroups: 14 | + - "" 15 | + resources: 16 | + - '*' 17 | + verbs: 18 | + - '*' 19 | +--- 20 | +apiVersion: rbac.authorization.k8s.io/v1 21 | +kind: RoleBinding 22 | +metadata: 23 | + name: moria-ocp-pipeline 24 | + namespace: mynamespace 25 | +roleRef: 26 | + apiGroup: rbac.authorization.k8s.io 27 | + kind: Role 28 | + name: moria-ocp-pipeline 29 | +subjects: 30 | +- kind: ServiceAccount 31 | + name: jenkins 32 | + namespace: mynamespace 33 | +--- 34 | +apiVersion: v1 35 | +data: 36 | + config: eyJleGFtcGxlIjoidmFsdWUifQ== 37 | +kind: Secret 38 | +metadata: 39 | + labels: 40 | + chart: ocp-pipeline-0.1.16 41 | + heritage: Helm 42 | + release: moria 43 | + name: moria-config 44 | +type: Opaque 45 | +--- 46 | +apiVersion: v1 47 | +data: 48 | + WebHookSecretKey: MTIzNDU2Nzg= 49 | +kind: Secret 50 | +metadata: 51 | + labels: 52 | + chart: ocp-pipeline-0.1.16 53 | + heritage: Helm 54 | + release: moria 55 | + name: moria-git-webhook-secret 56 | +type: Opaque 57 | +--- 58 | +apiVersion: build.openshift.io/v1 59 | +kind: BuildConfig 60 | +metadata: 61 | + labels: 62 | + app: ocp-pipeline 63 | + chart: ocp-pipeline-0.1.16 64 | + heritage: Helm 65 | + release: moria 66 | + name: moria-ocp-pipeline-deploy 67 | + namespace: null 68 | +spec: 69 | + nodeSelector: {} 70 | + resources: 71 | + limits: 72 | + cpu: 4000m 73 | + memory: 8G 74 | + requests: 75 | + cpu: 2000m 76 | + memory: 4G 77 | + strategy: 78 | + jenkinsPipelineStrategy: 79 | + jenkinsfile: |- 80 | + def helmName = "helm-v3.1.0-linux-amd64.tar.gz" 81 | + def chartName = "metadata-curator" 82 | + def chartRepo = "http://bcgov.github.io/helm-charts" 83 | + def releaseName = "mc" 84 | + def releaseNamespace = "" 85 | + def forceRecreate = "false" 86 | + def callAnotherPipe = "false" 87 | + def useEnv = "false" 88 | + def fromEnv = "commit" 89 | + def setFlag = "image.tag" 90 | + 91 | + node("nodejs") { 92 | + stage("deploy (it's already built)") { 93 | + sh """ 94 | + curl -L -O https://get.helm.sh/${helmName} 95 | + tar -zxvf ${helmName} 96 | + cd linux-amd64 97 | + 98 | + curl -L -O https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux32 99 | + chmod ugo+x ./jq-linux32 100 | + npm install -g json2yaml 101 | + 102 | + export CONF1=`oc get secret moria-config -o json | ./jq-linux32 .data.config` 103 | + export CONF2=`sed -e 's/^"//' -e 's/"\$//' <<<"\$CONF1"` 104 | + export CONF3=`echo \$CONF2 | base64 -d -` 105 | + export CONF=`echo \$CONF3 | json2yaml` 106 | + 107 | + echo "\$CONF" > ./config.yaml 108 | + oc project ${releaseNamespace} 109 | + ./helm repo add chart ${chartRepo} 110 | + ./helm repo update 111 | + if [ "${forceRecreate}" = "true" ]; then 112 | + ./helm upgrade ${releaseName} chart/${chartName} -f ./config.yaml --install --set hashLabel="${releaseName}\$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 32 | head -n 1)" 113 | + elif [ "${useEnv}" = "true" ]; then 114 | + ./helm upgrade ${releaseName} chart/${chartName} -f ./config.yaml --install --set ${setFlag}=${env[fromEnv]} 115 | + else 116 | + ./helm upgrade ${releaseName} chart/${chartName} -f ./config.yaml --install 117 | + fi 118 | + 119 | + if [ "${callAnotherPipe}" = "true" ]; then 120 | + curl -d '' http://otherwebhookUrl 121 | + fi 122 | + """ 123 | + } 124 | + } 125 | + type: JenkinsPipeline 126 | + triggers: 127 | + - generic: 128 | + allowEnv: true 129 | + secretReference: 130 | + name: moria-git-webhook-secret 131 | + type: generic 132 | +status: 133 | + lastVersion: 0 134 | -------------------------------------------------------------------------------- /krm-functions/sig-cli/render-helm-chart/examples/render-helm-chart-kustomize-inline-values/.expected/exec.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Copyright 2022 The Kubernetes Authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | 17 | # kustomize 4.2.0 is preinstalled in github actions 18 | kustomize build --enable-alpha-plugins --network > resources.yaml 19 | -------------------------------------------------------------------------------- /krm-functions/sig-cli/render-helm-chart/examples/render-helm-chart-kustomize-inline-values/README.md: -------------------------------------------------------------------------------- 1 | # render-helm-chart: Kustomize Inline Values 2 | 3 | ### Overview 4 | 5 | This example demonstrates how to declaratively invoke the `render-helm-chart` 6 | function with kustomize using the `valuesInline` field. 7 | 8 | ### Function invocation 9 | 10 | To use the function with kustomize, you can specify the `functionConfig` 11 | in your kustomization's `generators` field. This example uses inline values 12 | to use instead of the default values accompanying the chart: 13 | 14 | kustomization.yaml: 15 | ```yaml 16 | generators: 17 | - |- 18 | apiVersion: v1alpha1 19 | kind: RenderHelmChart 20 | metadata: 21 | name: demo 22 | annotations: 23 | config.kubernetes.io/function: | 24 | container: 25 | network: true 26 | image: us.gcr.io/k8s-artifacts-prod/krm-functions/render-helm-chart:unstable 27 | helmCharts: 28 | - chartArgs: 29 | name: ocp-pipeline 30 | version: 0.1.16 31 | repo: https://bcgov.github.io/helm-charts 32 | templateOptions: 33 | releaseName: moria 34 | namespace: mynamespace 35 | values: 36 | valuesInline: 37 | releaseNamespace: "" 38 | rbac: 39 | create: true 40 | rules: 41 | - apiGroups: [""] 42 | verbs: ["*"] 43 | resources: ["*"] 44 | ``` 45 | 46 | Then, to build the kustomization with kustomize v4: 47 | 48 | ```shell 49 | kustomize build --enable-alpha-plugins --network . 50 | ``` 51 | 52 | ### Expected result 53 | 54 | You should also be able to find the line `def releaseNamespace = ""` somewhere 55 | in your output, as well as the following: 56 | 57 | ```yaml 58 | apiVersion: rbac.authorization.k8s.io/v1 59 | kind: Role 60 | metadata: 61 | name: moria-ocp-pipeline 62 | namespace: mynamespace 63 | rules: 64 | - apiGroups: 65 | - "" 66 | resources: 67 | - '*' 68 | verbs: 69 | - '*' 70 | --- 71 | apiVersion: rbac.authorization.k8s.io/v1 72 | kind: RoleBinding 73 | metadata: 74 | name: moria-ocp-pipeline 75 | namespace: mynamespace 76 | roleRef: 77 | apiGroup: rbac.authorization.k8s.io 78 | kind: Role 79 | name: moria-ocp-pipeline 80 | subjects: 81 | - kind: ServiceAccount 82 | name: jenkins 83 | namespace: mynamespace 84 | ``` 85 | 86 | which demonstrates that the correct values provided via `valuesInline` were used. -------------------------------------------------------------------------------- /krm-functions/sig-cli/render-helm-chart/examples/render-helm-chart-kustomize-inline-values/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | generators: 16 | - |- 17 | apiVersion: v1alpha1 18 | kind: RenderHelmChart 19 | metadata: 20 | name: demo 21 | annotations: 22 | config.kubernetes.io/function: | 23 | container: 24 | network: true 25 | image: us.gcr.io/k8s-artifacts-prod/krm-functions/render-helm-chart:unstable 26 | helmCharts: 27 | - chartArgs: 28 | name: ocp-pipeline 29 | version: 0.1.16 30 | repo: https://bcgov.github.io/helm-charts 31 | templateOptions: 32 | releaseName: moria 33 | namespace: mynamespace 34 | values: 35 | valuesInline: 36 | releaseNamespace: "" 37 | rbac: 38 | create: true 39 | rules: 40 | - apiGroups: [""] 41 | verbs: ["*"] 42 | resources: ["*"] -------------------------------------------------------------------------------- /krm-functions/sig-cli/render-helm-chart/examples/render-helm-chart-kustomize-values-files/.expected/diff.patch: -------------------------------------------------------------------------------- 1 | diff --git a/resources.yaml b/resources.yaml 2 | new file mode 100644 3 | index 0000000..e2e869b 4 | --- /dev/null 5 | +++ b/resources.yaml 6 | @@ -0,0 +1,127 @@ 7 | +apiVersion: rbac.authorization.k8s.io/v1 8 | +kind: Role 9 | +metadata: 10 | + name: moria-ocp-pipeline 11 | + namespace: mynamespace 12 | +rules: 13 | +- apiGroups: 14 | + - "" 15 | + resources: 16 | + - '*' 17 | + verbs: 18 | + - '*' 19 | +--- 20 | +apiVersion: rbac.authorization.k8s.io/v1 21 | +kind: RoleBinding 22 | +metadata: 23 | + name: moria-ocp-pipeline 24 | + namespace: mynamespace 25 | +roleRef: 26 | + apiGroup: rbac.authorization.k8s.io 27 | + kind: Role 28 | + name: moria-ocp-pipeline 29 | +subjects: 30 | +- kind: ServiceAccount 31 | + name: jenkins 32 | + namespace: mynamespace 33 | +--- 34 | +apiVersion: v1 35 | +data: 36 | + config: eyJleGFtcGxlIjoidmFsdWUifQ== 37 | +kind: Secret 38 | +metadata: 39 | + labels: 40 | + chart: ocp-pipeline-0.1.16 41 | + heritage: Helm 42 | + release: moria 43 | + name: moria-config 44 | +type: Opaque 45 | +--- 46 | +apiVersion: v1 47 | +data: 48 | + WebHookSecretKey: MTIzNDU2Nzg= 49 | +kind: Secret 50 | +metadata: 51 | + labels: 52 | + chart: ocp-pipeline-0.1.16 53 | + heritage: Helm 54 | + release: moria 55 | + name: moria-git-webhook-secret 56 | +type: Opaque 57 | +--- 58 | +apiVersion: build.openshift.io/v1 59 | +kind: BuildConfig 60 | +metadata: 61 | + labels: 62 | + app: ocp-pipeline 63 | + chart: ocp-pipeline-0.1.16 64 | + heritage: Helm 65 | + release: moria 66 | + name: moria-ocp-pipeline-deploy 67 | + namespace: null 68 | +spec: 69 | + nodeSelector: {} 70 | + resources: 71 | + limits: 72 | + cpu: 4000m 73 | + memory: 8G 74 | + requests: 75 | + cpu: 2000m 76 | + memory: 4G 77 | + strategy: 78 | + jenkinsPipelineStrategy: 79 | + jenkinsfile: |- 80 | + def helmName = "helm-v3.1.0-linux-amd64.tar.gz" 81 | + def chartName = "metadata-curator" 82 | + def chartRepo = "http://bcgov.github.io/helm-charts" 83 | + def releaseName = "mc" 84 | + def releaseNamespace = "" 85 | + def forceRecreate = "false" 86 | + def callAnotherPipe = "false" 87 | + def useEnv = "false" 88 | + def fromEnv = "commit" 89 | + def setFlag = "image.tag" 90 | + 91 | + node("nodejs") { 92 | + stage("deploy (it's already built)") { 93 | + sh """ 94 | + curl -L -O https://get.helm.sh/${helmName} 95 | + tar -zxvf ${helmName} 96 | + cd linux-amd64 97 | + 98 | + curl -L -O https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux32 99 | + chmod ugo+x ./jq-linux32 100 | + npm install -g json2yaml 101 | + 102 | + export CONF1=`oc get secret moria-config -o json | ./jq-linux32 .data.config` 103 | + export CONF2=`sed -e 's/^"//' -e 's/"\$//' <<<"\$CONF1"` 104 | + export CONF3=`echo \$CONF2 | base64 -d -` 105 | + export CONF=`echo \$CONF3 | json2yaml` 106 | + 107 | + echo "\$CONF" > ./config.yaml 108 | + oc project ${releaseNamespace} 109 | + ./helm repo add chart ${chartRepo} 110 | + ./helm repo update 111 | + if [ "${forceRecreate}" = "true" ]; then 112 | + ./helm upgrade ${releaseName} chart/${chartName} -f ./config.yaml --install --set hashLabel="${releaseName}\$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 32 | head -n 1)" 113 | + elif [ "${useEnv}" = "true" ]; then 114 | + ./helm upgrade ${releaseName} chart/${chartName} -f ./config.yaml --install --set ${setFlag}=${env[fromEnv]} 115 | + else 116 | + ./helm upgrade ${releaseName} chart/${chartName} -f ./config.yaml --install 117 | + fi 118 | + 119 | + if [ "${callAnotherPipe}" = "true" ]; then 120 | + curl -d '' http://otherwebhookUrl 121 | + fi 122 | + """ 123 | + } 124 | + } 125 | + type: JenkinsPipeline 126 | + triggers: 127 | + - generic: 128 | + allowEnv: true 129 | + secretReference: 130 | + name: moria-git-webhook-secret 131 | + type: generic 132 | +status: 133 | + lastVersion: 0 134 | -------------------------------------------------------------------------------- /krm-functions/sig-cli/render-helm-chart/examples/render-helm-chart-kustomize-values-files/.expected/exec.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Copyright 2022 The Kubernetes Authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | 17 | # kustomize 4.2.0 is preinstalled in github actions 18 | kustomize build --enable-alpha-plugins --network > resources.yaml 19 | -------------------------------------------------------------------------------- /krm-functions/sig-cli/render-helm-chart/examples/render-helm-chart-kustomize-values-files/.krmignore: -------------------------------------------------------------------------------- 1 | .expected 2 | -------------------------------------------------------------------------------- /krm-functions/sig-cli/render-helm-chart/examples/render-helm-chart-kustomize-values-files/README.md: -------------------------------------------------------------------------------- 1 | # render-helm-chart: Kustomize Values Files 2 | 3 | ### Overview 4 | 5 | This example demonstrates how to declaratively invoke the `render-helm-chart` 6 | function with kustomize using multiple values files. 7 | 8 | ### Function invocation 9 | 10 | To use the function with kustomize, you can specify the `functionConfig` 11 | in your kustomization's `generators` field. This example specifies multiple remote 12 | values files to use instead of the default values accompanying the chart: 13 | 14 | kustomization.yaml: 15 | ```yaml 16 | generators: 17 | - |- 18 | apiVersion: v1alpha1 19 | kind: RenderHelmChart 20 | metadata: 21 | name: demo 22 | annotations: 23 | config.kubernetes.io/function: | 24 | container: 25 | network: true 26 | image: us.gcr.io/k8s-artifacts-prod/krm-functions/render-helm-chart:unstable 27 | helmCharts: 28 | - chartArgs: 29 | name: ocp-pipeline 30 | version: 0.1.16 31 | repo: https://bcgov.github.io/helm-charts 32 | templateOptions: 33 | namespace: mynamespace 34 | releaseName: moria 35 | values: 36 | valuesFiles: 37 | - https://raw.githubusercontent.com/natasha41575/kpt-functions-catalog/a9c9cd765a05f7a7fb6923dbde4651b62c9c229c/examples/render-helm-chart-kustomize-values-files/file1.yaml 38 | - https://raw.githubusercontent.com/natasha41575/kpt-functions-catalog/a9c9cd765a05f7a7fb6923dbde4651b62c9c229c/examples/render-helm-chart-kustomize-values-files/file2.yaml 39 | ``` 40 | 41 | Then, to build the kustomization with kustomize v4: 42 | 43 | ```shell 44 | kustomize build --enable-alpha-plugins --network . 45 | ``` 46 | 47 | ### Expected result 48 | 49 | You should also be able to find the line `def releaseNamespace = ""` somewhere 50 | in your output, as well as the following: 51 | 52 | ```yaml 53 | apiVersion: rbac.authorization.k8s.io/v1 54 | kind: Role 55 | metadata: 56 | name: moria-ocp-pipeline 57 | namespace: mynamespace 58 | rules: 59 | - apiGroups: 60 | - "" 61 | resources: 62 | - '*' 63 | verbs: 64 | - '*' 65 | --- 66 | apiVersion: rbac.authorization.k8s.io/v1 67 | kind: RoleBinding 68 | metadata: 69 | name: moria-ocp-pipeline 70 | namespace: mynamespace 71 | roleRef: 72 | apiGroup: rbac.authorization.k8s.io 73 | kind: Role 74 | name: moria-ocp-pipeline 75 | subjects: 76 | - kind: ServiceAccount 77 | name: jenkins 78 | namespace: mynamespace 79 | ``` 80 | 81 | which demonstrates that the correct values provided via `valuesFiles` were used. -------------------------------------------------------------------------------- /krm-functions/sig-cli/render-helm-chart/examples/render-helm-chart-kustomize-values-files/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | generators: 16 | - |- 17 | apiVersion: v1alpha1 18 | kind: RenderHelmChart 19 | metadata: 20 | name: demo 21 | annotations: 22 | config.kubernetes.io/function: | 23 | container: 24 | network: true 25 | image: us.gcr.io/k8s-artifacts-prod/krm-functions/render-helm-chart:unstable 26 | helmCharts: 27 | - chartArgs: 28 | name: ocp-pipeline 29 | version: 0.1.16 30 | repo: https://bcgov.github.io/helm-charts 31 | templateOptions: 32 | namespace: mynamespace 33 | releaseName: moria 34 | values: 35 | valuesFiles: 36 | - https://raw.githubusercontent.com/natasha41575/kpt-functions-catalog/a9c9cd765a05f7a7fb6923dbde4651b62c9c229c/examples/render-helm-chart-kustomize-values-files/file1.yaml 37 | - https://raw.githubusercontent.com/natasha41575/kpt-functions-catalog/a9c9cd765a05f7a7fb6923dbde4651b62c9c229c/examples/render-helm-chart-kustomize-values-files/file2.yaml 38 | -------------------------------------------------------------------------------- /krm-functions/sig-cli/render-helm-chart/go.mod: -------------------------------------------------------------------------------- 1 | module sigs.k8s.io/krm-functions-registry/krm-functions/sig-cli/render-helm-chart 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/imdario/mergo v0.3.12 7 | github.com/pkg/errors v0.9.1 8 | sigs.k8s.io/kustomize/api v0.8.11 9 | sigs.k8s.io/kustomize/kyaml v0.11.0 10 | sigs.k8s.io/yaml v1.2.0 11 | ) 12 | 13 | require ( 14 | github.com/PuerkitoBio/purell v1.1.1 // indirect 15 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect 16 | github.com/davecgh/go-spew v1.1.1 // indirect 17 | github.com/go-errors/errors v1.0.1 // indirect 18 | github.com/go-openapi/jsonpointer v0.19.3 // indirect 19 | github.com/go-openapi/jsonreference v0.19.3 // indirect 20 | github.com/go-openapi/swag v0.19.5 // indirect 21 | github.com/inconshreveable/mousetrap v1.0.0 // indirect 22 | github.com/mailru/easyjson v0.7.0 // indirect 23 | github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect 24 | github.com/pmezard/go-difflib v1.0.0 // indirect 25 | github.com/spf13/cobra v1.0.0 // indirect 26 | github.com/spf13/pflag v1.0.5 // indirect 27 | github.com/stretchr/testify v1.5.1 // indirect 28 | github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect 29 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect 30 | golang.org/x/text v0.3.2 // indirect 31 | gopkg.in/yaml.v2 v2.4.0 // indirect 32 | k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e // indirect 33 | ) 34 | -------------------------------------------------------------------------------- /krm-functions/sig-cli/render-helm-chart/go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 3 | github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= 4 | github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= 5 | github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= 6 | github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= 7 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= 8 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= 9 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 10 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 11 | github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= 12 | github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= 13 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 14 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 15 | github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 16 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 17 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= 18 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 19 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 20 | github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= 21 | github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= 22 | github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 23 | github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 24 | github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= 25 | github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 26 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 27 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 28 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 29 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 30 | github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= 31 | github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= 32 | github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= 33 | github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= 34 | github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= 35 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 36 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 37 | github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= 38 | github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= 39 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 40 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 41 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 42 | github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= 43 | github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w= 44 | github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= 45 | github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o= 46 | github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= 47 | github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY= 48 | github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= 49 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 50 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 51 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 52 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 53 | github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 54 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 55 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 56 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 57 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 58 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 59 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 60 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 61 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 62 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 63 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 64 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 65 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 66 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 67 | github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= 68 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 69 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 70 | github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= 71 | github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= 72 | github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 73 | github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= 74 | github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 75 | github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= 76 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= 77 | github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= 78 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 79 | github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= 80 | github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= 81 | github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= 82 | github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= 83 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 84 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 85 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 86 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 87 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 88 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 89 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 90 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 91 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 92 | github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= 93 | github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 94 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 95 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 96 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 97 | github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 98 | github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 99 | github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 100 | github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM= 101 | github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= 102 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 103 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 104 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 105 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 106 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 107 | github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= 108 | github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= 109 | github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 110 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 111 | github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= 112 | github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 113 | github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= 114 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 115 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 116 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 117 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 118 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 119 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 120 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 121 | github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= 122 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 123 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 124 | github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 125 | github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 126 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 127 | github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 128 | github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= 129 | github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 130 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 131 | github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= 132 | github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= 133 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 134 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 135 | github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= 136 | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 137 | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 138 | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 139 | github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= 140 | github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= 141 | github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= 142 | github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 143 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 144 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 145 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 146 | github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= 147 | github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= 148 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 149 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 150 | github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= 151 | github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= 152 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 153 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 154 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 155 | github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= 156 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 157 | github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= 158 | github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= 159 | github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= 160 | github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI= 161 | github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= 162 | github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= 163 | go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= 164 | go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc= 165 | go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= 166 | go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 167 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 168 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 169 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 170 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 171 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 172 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 173 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 174 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 175 | golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 176 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 177 | golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 178 | golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 179 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= 180 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 181 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 182 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 183 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 184 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 185 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 186 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 187 | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 188 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 189 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 190 | golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 191 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 192 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 193 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= 194 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 195 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 196 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 197 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 198 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 199 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 200 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 201 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 202 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 203 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 204 | google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 205 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 206 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 207 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 208 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 209 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 210 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 211 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 212 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 213 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 214 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= 215 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 216 | gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= 217 | gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 218 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 219 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 220 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 221 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 222 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 223 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 224 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 225 | gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 226 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 227 | k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= 228 | k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= 229 | k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e h1:KLHHjkdQFomZy8+06csTWZ0m1343QqxZhR2LJ1OxCYM= 230 | k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= 231 | sigs.k8s.io/kustomize/api v0.8.11 h1:LzQzlq6Z023b+mBtc6v72N2mSHYmN8x7ssgbf/hv0H8= 232 | sigs.k8s.io/kustomize/api v0.8.11/go.mod h1:a77Ls36JdfCWojpUqR6m60pdGY1AYFix4AH83nJtY1g= 233 | sigs.k8s.io/kustomize/kyaml v0.11.0 h1:9KhiCPKaVyuPcgOLJXkvytOvjMJLoxpjodiycb4gHsA= 234 | sigs.k8s.io/kustomize/kyaml v0.11.0/go.mod h1:GNMwjim4Ypgp/MueD3zXHLRJEjz7RvtPae0AwlvEMFM= 235 | sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= 236 | sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= 237 | sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= 238 | -------------------------------------------------------------------------------- /krm-functions/sig-cli/render-helm-chart/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Kubernetes Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package main 16 | 17 | import ( 18 | "fmt" 19 | "os" 20 | 21 | "sigs.k8s.io/krm-functions-registry/krm-functions/sig-cli/render-helm-chart/third_party/sigs.k8s.io/kustomize/api/builtins" 22 | "sigs.k8s.io/kustomize/api/resmap" 23 | "sigs.k8s.io/kustomize/api/resource" 24 | "sigs.k8s.io/kustomize/kyaml/fn/framework" 25 | "sigs.k8s.io/kustomize/kyaml/fn/framework/command" 26 | kyaml "sigs.k8s.io/kustomize/kyaml/yaml" 27 | ) 28 | 29 | const ( 30 | fnConfigKind = "RenderHelmChart" 31 | configMap = "ConfigMap" 32 | ) 33 | 34 | //nolint 35 | func main() { 36 | asp := HelmChartProcessor{} 37 | cmd := command.Build(&asp, command.StandaloneEnabled, false) 38 | if err := cmd.Execute(); err != nil { 39 | os.Exit(1) 40 | } 41 | } 42 | 43 | type HelmChartProcessor struct{} 44 | 45 | func (slp *HelmChartProcessor) Process(resourceList *framework.ResourceList) error { 46 | err := run(resourceList) 47 | if err != nil { 48 | resourceList.Result = &framework.Result{ 49 | Name: "render-helm-chart", 50 | Items: []framework.ResultItem{ 51 | { 52 | Message: err.Error(), 53 | Severity: framework.Error, 54 | }, 55 | }, 56 | } 57 | return resourceList.Result 58 | } 59 | return nil 60 | } 61 | 62 | type helmChartInflatorFunction struct { 63 | kyaml.ResourceMeta `json:",inline" yaml:",inline"` 64 | plugins []builtins.HelmChartInflationGeneratorPlugin 65 | } 66 | 67 | func (f *helmChartInflatorFunction) Config(rn *kyaml.RNode) error { 68 | y, err := rn.String() 69 | if err != nil { 70 | return fmt.Errorf("cannot get YAML from RNode: %w", err) 71 | } 72 | kind, err := f.getKind(rn) 73 | if err != nil { 74 | return err 75 | } 76 | switch kind { 77 | case fnConfigKind: 78 | err = f.RenderHelmChartArgs([]byte(y)) 79 | if err != nil { 80 | return err 81 | } 82 | case configMap: 83 | dataMap := rn.GetDataMap() 84 | bytes, err := kyaml.Marshal(dataMap) 85 | if err != nil { 86 | return err 87 | } 88 | err = f.ConfigMapArgs(bytes) 89 | if err != nil { 90 | return err 91 | } 92 | default: 93 | return fmt.Errorf("`functionConfig` must be `%s` or `%s`", configMap, fnConfigKind) 94 | } 95 | return nil 96 | } 97 | 98 | func (f *helmChartInflatorFunction) Run(items []*kyaml.RNode) ([]*kyaml.RNode, error) { 99 | resmapFactory := builtins.NewResMapFactory() 100 | resMap, err := resmapFactory.NewResMapFromRNodeSlice(items) 101 | if err != nil { 102 | return nil, err 103 | } 104 | var rm resmap.ResMap 105 | for _, p := range f.plugins { 106 | rm, err = p.Generate() 107 | if err != nil { 108 | return nil, fmt.Errorf("failed to run generator: %w", err) 109 | } 110 | 111 | // check for duplicates for idempotency 112 | for i := range items { 113 | resources := rm.Resources() 114 | for r := range resources { 115 | it := &resource.Resource{RNode: *items[i]} 116 | if resources[r].CurId() == it.CurId() { 117 | // don't attempt to add a resource with the same ID 118 | err := rm.Remove(resources[r].CurId()) 119 | if err != nil { 120 | return items, err 121 | } 122 | } 123 | } 124 | } 125 | 126 | err = resMap.AppendAll(rm) 127 | if err != nil { 128 | return nil, fmt.Errorf("failed to add generated resource: %w", err) 129 | } 130 | } 131 | return resMap.ToRNodeSlice(), nil 132 | } 133 | 134 | func run(resourceList *framework.ResourceList) error { 135 | var fn helmChartInflatorFunction 136 | err := fn.Config(resourceList.FunctionConfig) 137 | if err != nil { 138 | return fmt.Errorf("failed to configure function: %w", err) 139 | } 140 | resourceList.Items, err = fn.Run(resourceList.Items) 141 | if err != nil { 142 | return fmt.Errorf("failed to run function: %w", err) 143 | } 144 | return nil 145 | } 146 | 147 | func (f *helmChartInflatorFunction) getKind(rn *kyaml.RNode) (string, error) { 148 | meta, err := rn.GetMeta() 149 | if err != nil { 150 | return "", err 151 | } 152 | return meta.Kind, nil 153 | } 154 | 155 | func (f *helmChartInflatorFunction) RenderHelmChartArgs(c []byte) (err error) { 156 | args := &builtins.HelmArgs{} 157 | if err = kyaml.Unmarshal(c, args); err != nil { 158 | return 159 | } 160 | for _, helmChart := range args.HelmCharts { 161 | p := builtins.HelmChartInflationGeneratorPlugin{ 162 | HelmGlobals: args.HelmGlobals, 163 | HelmChart: helmChart, 164 | } 165 | if err := p.ValidateArgs(); err != nil { 166 | return err 167 | } 168 | f.plugins = append(f.plugins, p) 169 | } 170 | return nil 171 | } 172 | 173 | func (f *helmChartInflatorFunction) ConfigMapArgs( 174 | bytes []byte) (err error) { 175 | var m map[string]string 176 | 177 | err = kyaml.Unmarshal(bytes, &m) 178 | if err != nil { 179 | return err 180 | } 181 | var p builtins.HelmChartInflationGeneratorPlugin 182 | if val, ok := m["chartHome"]; ok { 183 | p.ChartHome = val 184 | } 185 | if val, ok := m["configHome"]; ok { 186 | p.ConfigHome = val 187 | } 188 | if val, ok := m["name"]; ok { 189 | p.Name = val 190 | } 191 | if val, ok := m["version"]; ok { 192 | p.Version = val 193 | } 194 | if val, ok := m["repo"]; ok { 195 | p.Repo = val 196 | } 197 | if val, ok := m["releaseName"]; ok { 198 | p.ReleaseName = val 199 | } 200 | if val, ok := m["namespace"]; ok { 201 | p.Namespace = val 202 | } 203 | if val, ok := m["includeCRDs"]; ok { 204 | if val == "true" { 205 | p.IncludeCRDs = true 206 | } 207 | } 208 | if val, ok := m["skipTests"]; ok { 209 | if val == "true" { 210 | p.SkipTests = true 211 | } 212 | } 213 | if val, ok := m["valuesFile"]; ok { 214 | p.ValuesFiles = []string{val} 215 | } 216 | if err := p.ValidateArgs(); err != nil { 217 | return err 218 | } 219 | f.plugins = append(f.plugins, p) 220 | return nil 221 | } 222 | -------------------------------------------------------------------------------- /krm-functions/sig-cli/render-helm-chart/main_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Kubernetes Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package main 16 | 17 | import ( 18 | "io/ioutil" 19 | "testing" 20 | 21 | "github.com/stretchr/testify/assert" 22 | "sigs.k8s.io/krm-functions-registry/krm-functions/sig-cli/render-helm-chart/third_party/sigs.k8s.io/kustomize/api/builtins" 23 | "sigs.k8s.io/krm-functions-registry/krm-functions/sig-cli/render-helm-chart/third_party/sigs.k8s.io/kustomize/api/types" 24 | "sigs.k8s.io/kustomize/kyaml/yaml" 25 | ) 26 | 27 | func TestHelmChartInflatorFunction_Config(t *testing.T) { 28 | tests := map[string]struct { 29 | functionConfig string 30 | expectedErr string 31 | expected []builtins.HelmChartInflationGeneratorPlugin 32 | }{ 33 | "invalid function config": { 34 | functionConfig: `invalid`, 35 | expectedErr: "missing Resource metadata", 36 | }, 37 | "function config as ConfigMap": { 38 | functionConfig: ` 39 | apiVersion: v1 40 | kind: ConfigMap 41 | metadata: 42 | name: myMap 43 | data: 44 | name: minecraft 45 | repo: https://itzg.github.io/minecraft-server-charts 46 | version: 3.1.3 47 | releaseName: test 48 | `, 49 | expected: []builtins.HelmChartInflationGeneratorPlugin{ 50 | { 51 | HelmChart: types.HelmChart{ 52 | ChartArgs: types.ChartArgs{ 53 | Name: "minecraft", 54 | Repo: "https://itzg.github.io/minecraft-server-charts", 55 | Version: "3.1.3", 56 | }, 57 | TemplateOptions: types.TemplateOptions{ 58 | ReleaseName: "test", 59 | Values: types.Values{ 60 | ValuesFiles: []string{"tmp/charts/minecraft/values.yaml"}, 61 | ValuesMerge: "override", 62 | }, 63 | }, 64 | }, 65 | }, 66 | }, 67 | }, 68 | "function config as RenderHelmChart": { 69 | functionConfig: ` 70 | apiVersion: v1 71 | kind: RenderHelmChart 72 | metadata: 73 | name: myRenderHelmChart 74 | helmCharts: 75 | - chartArgs: 76 | name: minecraft 77 | repo: https://itzg.github.io/minecraft-server-charts 78 | version: 3.1.3 79 | templateOptions: 80 | releaseName: test-1 81 | - chartArgs: 82 | name: minecraft 83 | repo: https://itzg.github.io/minecraft-server-charts 84 | version: 3.1.3 85 | templateOptions: 86 | releaseName: test-2 87 | `, 88 | expected: []builtins.HelmChartInflationGeneratorPlugin{ 89 | { 90 | HelmChart: types.HelmChart{ 91 | ChartArgs: types.ChartArgs{ 92 | Name: "minecraft", 93 | Repo: "https://itzg.github.io/minecraft-server-charts", 94 | Version: "3.1.3", 95 | }, 96 | TemplateOptions: types.TemplateOptions{ 97 | ReleaseName: "test-1", 98 | Values: types.Values{ 99 | ValuesFiles: []string{"tmp/charts/minecraft/values.yaml"}, 100 | ValuesMerge: "override", 101 | }, 102 | }, 103 | }, 104 | }, 105 | { 106 | HelmChart: types.HelmChart{ 107 | ChartArgs: types.ChartArgs{ 108 | Name: "minecraft", 109 | Repo: "https://itzg.github.io/minecraft-server-charts", 110 | Version: "3.1.3", 111 | }, 112 | TemplateOptions: types.TemplateOptions{ 113 | ReleaseName: "test-2", 114 | Values: types.Values{ 115 | ValuesFiles: []string{"tmp/charts/minecraft/values.yaml"}, 116 | ValuesMerge: "override", 117 | }, 118 | }, 119 | }, 120 | }, 121 | }, 122 | }, 123 | } 124 | 125 | for _, tc := range tests { 126 | var fn helmChartInflatorFunction 127 | node := yaml.MustParse(tc.functionConfig) 128 | err := fn.Config(node) 129 | if tc.expectedErr == "" { 130 | if !assert.NoError(t, err) { 131 | t.FailNow() 132 | } 133 | assert.Equal(t, len(tc.expected), len(fn.plugins)) 134 | for i := range tc.expected { 135 | assert.Equal(t, tc.expected[i].HelmChart, fn.plugins[i].HelmChart) 136 | } 137 | } else { 138 | if !assert.Error(t, err) { 139 | t.FailNow() 140 | } 141 | assert.Contains(t, err.Error(), tc.expectedErr) 142 | } 143 | } 144 | } 145 | 146 | func TestHelmChartInflatorFunction_Run(t *testing.T) { 147 | tmpDir, err := ioutil.TempDir("", "") 148 | assert.NoError(t, err) 149 | 150 | tests := map[string]struct { 151 | functionConfig string 152 | expected string 153 | }{ 154 | "simple": { 155 | functionConfig: ` 156 | apiVersion: v1 157 | kind: RenderHelmChart 158 | metadata: 159 | name: myRenderHelmChart 160 | helmGlobals: 161 | chartHome: ` + tmpDir + ` 162 | helmCharts: 163 | - chartArgs: 164 | name: minecraft 165 | repo: https://itzg.github.io/minecraft-server-charts 166 | version: 3.1.3 167 | templateOptions: 168 | releaseName: test-1 169 | - chartArgs: 170 | name: minecraft 171 | repo: https://itzg.github.io/minecraft-server-charts 172 | version: 3.1.3 173 | templateOptions: 174 | releaseName: test-2 175 | `, 176 | expected: `# Source: minecraft/templates/secrets.yaml 177 | apiVersion: v1 178 | kind: Secret 179 | metadata: 180 | name: test-1-minecraft 181 | labels: 182 | app: test-1-minecraft 183 | chart: "minecraft-3.1.3" 184 | release: "test-1" 185 | heritage: "Helm" 186 | type: Opaque 187 | data: 188 | rcon-password: "Q0hBTkdFTUUh" 189 | # Source: minecraft/templates/minecraft-svc.yaml 190 | apiVersion: v1 191 | kind: Service 192 | metadata: 193 | name: test-1-minecraft 194 | labels: 195 | app: test-1-minecraft 196 | chart: "minecraft-3.1.3" 197 | release: "test-1" 198 | heritage: "Helm" 199 | annotations: {} 200 | spec: 201 | type: ClusterIP 202 | ports: 203 | - name: minecraft 204 | port: 25565 205 | targetPort: minecraft 206 | protocol: TCP 207 | selector: 208 | app: test-1-minecraft 209 | # Source: minecraft/templates/secrets.yaml 210 | apiVersion: v1 211 | kind: Secret 212 | metadata: 213 | name: test-2-minecraft 214 | labels: 215 | app: test-2-minecraft 216 | chart: "minecraft-3.1.3" 217 | release: "test-2" 218 | heritage: "Helm" 219 | type: Opaque 220 | data: 221 | rcon-password: "Q0hBTkdFTUUh" 222 | # Source: minecraft/templates/minecraft-svc.yaml 223 | apiVersion: v1 224 | kind: Service 225 | metadata: 226 | name: test-2-minecraft 227 | labels: 228 | app: test-2-minecraft 229 | chart: "minecraft-3.1.3" 230 | release: "test-2" 231 | heritage: "Helm" 232 | annotations: {} 233 | spec: 234 | type: ClusterIP 235 | ports: 236 | - name: minecraft 237 | port: 25565 238 | targetPort: minecraft 239 | protocol: TCP 240 | selector: 241 | app: test-2-minecraft 242 | `, 243 | }, 244 | "include CRDs": { 245 | functionConfig: ` 246 | apiVersion: v1 247 | kind: RenderHelmChart 248 | metadata: 249 | name: myRenderHelmChart 250 | helmGlobals: 251 | chartHome: ` + tmpDir + ` 252 | helmCharts: 253 | - chartArgs: 254 | name: terraform 255 | repo: https://helm.releases.hashicorp.com 256 | version: 1.0.0 257 | templateOptions: 258 | releaseName: terraforming-mars 259 | includeCRDs: true 260 | `, 261 | expected: `kind: CustomResourceDefinition`, 262 | }, 263 | } 264 | 265 | for _, tc := range tests { 266 | var fn helmChartInflatorFunction 267 | node := yaml.MustParse(tc.functionConfig) 268 | 269 | err = fn.Config(node) 270 | assert.NoError(t, err) 271 | 272 | items, err := fn.Run(nil) 273 | if !assert.NoError(t, err) { 274 | t.FailNow() 275 | } 276 | 277 | actual := "" 278 | for i := range items { 279 | actual = actual + items[i].MustString() 280 | } 281 | assert.Contains(t, actual, tc.expected) 282 | } 283 | } 284 | -------------------------------------------------------------------------------- /krm-functions/sig-cli/render-helm-chart/third_party/README.md: -------------------------------------------------------------------------------- 1 | This package is forked from `sigs.k8s.io/kustomize/api/` with version `api/0.8.11`. -------------------------------------------------------------------------------- /krm-functions/sig-cli/render-helm-chart/third_party/sigs.k8s.io/kustomize/api/builtins/HelmChartInflationGenerator.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Kubernetes Authors. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //go:generate HelmChartInflationGeneratorPluginator 5 | package builtins 6 | 7 | import ( 8 | "bytes" 9 | "crypto/md5" 10 | "encoding/hex" 11 | "fmt" 12 | "io/ioutil" 13 | "net/http" 14 | "net/url" 15 | "os" 16 | "os/exec" 17 | "path/filepath" 18 | "regexp" 19 | "strings" 20 | 21 | "github.com/imdario/mergo" 22 | "github.com/pkg/errors" 23 | "sigs.k8s.io/krm-functions-registry/krm-functions/sig-cli/render-helm-chart/third_party/sigs.k8s.io/kustomize/api/types" 24 | "sigs.k8s.io/kustomize/api/hasher" 25 | "sigs.k8s.io/kustomize/api/resmap" 26 | "sigs.k8s.io/kustomize/api/resource" 27 | "sigs.k8s.io/yaml" 28 | ) 29 | 30 | // Add the given labels to the given field specifications. 31 | type HelmArgs struct { 32 | types.HelmGlobals `json:"helmGlobals,omitempty" yaml:"helmGlobals,omitempty"` 33 | HelmCharts []types.HelmChart `json:"helmCharts,omitempty" yaml:"helmCharts,omitempty"` 34 | } 35 | 36 | type HelmChartInflationGeneratorPlugin struct { 37 | types.HelmGlobals `json:",inline,omitempty" yaml:",inline,omitempty"` 38 | types.HelmChart `json:",inline,omitempty" yaml:",inline,omitempty"` 39 | tmpDir string 40 | } 41 | 42 | const ( 43 | valuesMergeOptionMerge = "merge" 44 | valuesMergeOptionOverride = "override" 45 | valuesMergeOptionReplace = "replace" 46 | ) 47 | 48 | var legalMergeOptions = []string{ 49 | valuesMergeOptionMerge, 50 | valuesMergeOptionOverride, 51 | valuesMergeOptionReplace, 52 | } 53 | 54 | //noinspection GoUnusedGlobalVariable 55 | var KustomizeHelmChartInflationGeneratorPlugin HelmChartInflationGeneratorPlugin 56 | 57 | func (p *HelmChartInflationGeneratorPlugin) establishTmpDir() (err error) { 58 | if p.tmpDir != "" { 59 | // already done. 60 | return nil 61 | } 62 | p.tmpDir, err = ioutil.TempDir("", "kustomize-helm-") 63 | return err 64 | } 65 | 66 | func (p *HelmChartInflationGeneratorPlugin) ValidateArgs() (err error) { 67 | // ChartHome might be written to by the function in a container, 68 | // so it must be under the `/tmp` directory 69 | if p.ChartHome == "" { 70 | p.ChartHome = "tmp/charts" 71 | } 72 | 73 | if len(p.ValuesFiles) == 0 { 74 | p.ValuesFiles = append(p.ValuesFiles, filepath.Join(p.ChartHome, p.Name, "values.yaml")) 75 | } 76 | 77 | if err = p.errIfIllegalValuesMerge(); err != nil { 78 | return err 79 | } 80 | 81 | // ConfigHome is not loaded by the HelmChartInflationGeneratorPlugin, and can be located anywhere. 82 | if p.ConfigHome == "" { 83 | if err = p.establishTmpDir(); err != nil { 84 | return errors.Wrap( 85 | err, "unable to create tmp dir for HELM_CONFIG_HOME") 86 | } 87 | p.ConfigHome = filepath.Join(p.tmpDir, "helm") 88 | } 89 | return nil 90 | } 91 | 92 | func (p *HelmChartInflationGeneratorPlugin) errIfIllegalValuesMerge() error { 93 | if p.ValuesMerge == "" { 94 | // Use the default. 95 | p.ValuesMerge = valuesMergeOptionOverride 96 | return nil 97 | } 98 | for _, opt := range legalMergeOptions { 99 | if p.ValuesMerge == opt { 100 | return nil 101 | } 102 | } 103 | return fmt.Errorf("valuesMerge must be one of %v", legalMergeOptions) 104 | } 105 | 106 | func (p *HelmChartInflationGeneratorPlugin) absChartHome() string { 107 | path, _ := filepath.Abs(p.ChartHome) 108 | return path 109 | } 110 | 111 | func (p *HelmChartInflationGeneratorPlugin) runHelmCommand( 112 | args []string) ([]byte, error) { 113 | stdout := new(bytes.Buffer) 114 | stderr := new(bytes.Buffer) 115 | cmd := exec.Command("helm", args...) 116 | cmd.Stdout = stdout 117 | cmd.Stderr = stderr 118 | env := []string{ 119 | fmt.Sprintf("HELM_CONFIG_HOME=%s", p.ConfigHome), 120 | fmt.Sprintf("HELM_CACHE_HOME=%s/.cache", p.ConfigHome), 121 | fmt.Sprintf("HELM_DATA_HOME=%s/.data", p.ConfigHome)} 122 | cmd.Env = append(os.Environ(), env...) 123 | err := cmd.Run() 124 | if err != nil { 125 | helm := "helm" 126 | err = errors.Wrap( 127 | fmt.Errorf( 128 | "unable to run: '%s %s' with env=%s (is '%s' installed?)", 129 | helm, strings.Join(args, " "), env, helm), 130 | stderr.String(), 131 | ) 132 | } 133 | return stdout.Bytes(), err 134 | } 135 | 136 | // createNewMergedValuesFiles replaces/merges original values file with ValuesInline. 137 | func (p *HelmChartInflationGeneratorPlugin) createNewMergedValuesFiles(path string) ( 138 | string, error) { 139 | pValues, err := ioutil.ReadFile(path) 140 | if err != nil { 141 | if u, urlErr := url.Parse(path); urlErr == nil { 142 | if u.Scheme == "http" || u.Scheme == "https" { 143 | resp, err := http.Get(path) 144 | if err != nil { 145 | return "", err 146 | } 147 | defer resp.Body.Close() 148 | pValues, err = ioutil.ReadAll(resp.Body) 149 | if err != nil { 150 | return "", err 151 | } 152 | } else { // url scheme is not http or https 153 | return "", fmt.Errorf("unsupported URL scheme: %s", path) 154 | } 155 | } else { // invalid path and invalid URL 156 | return "", fmt.Errorf( 157 | "could not read provided values file %q: when reading as file path, received error %v; when reading as URL, received error %v", 158 | path, err, urlErr) 159 | } 160 | } else { 161 | // we want to pass in the absolute path into writeValuesBytes 162 | path, err = filepath.Abs(path) 163 | if err != nil { 164 | return "", err 165 | } 166 | } 167 | if p.ValuesMerge == valuesMergeOptionMerge || 168 | p.ValuesMerge == valuesMergeOptionOverride { 169 | if err = p.replaceValuesInline(pValues); err != nil { 170 | return "", err 171 | } 172 | } 173 | var b []byte 174 | b, err = yaml.Marshal(p.ValuesInline) 175 | if err != nil { 176 | return "", err 177 | } 178 | return p.writeValuesBytes(b, path) 179 | } 180 | 181 | func (p *HelmChartInflationGeneratorPlugin) replaceValuesInline(pValues []byte) error { 182 | var err error 183 | chValues := make(map[string]interface{}) 184 | if err = yaml.Unmarshal(pValues, &chValues); err != nil { 185 | return err 186 | } 187 | switch p.ValuesMerge { 188 | case valuesMergeOptionOverride: 189 | err = mergo.Merge( 190 | &chValues, p.ValuesInline, mergo.WithOverride) 191 | case valuesMergeOptionMerge: 192 | err = mergo.Merge(&chValues, p.ValuesInline) 193 | } 194 | p.ValuesInline = chValues 195 | return err 196 | } 197 | 198 | // Write a absolute path file in the tmp file system. 199 | func (p *HelmChartInflationGeneratorPlugin) writeValuesBytes( 200 | b []byte, path string) (string, error) { 201 | if err := p.establishTmpDir(); err != nil { 202 | return "", fmt.Errorf("cannot create tmp dir to write helm values") 203 | } 204 | // use a hash of the provided path to generate a unique, valid filename 205 | hash := md5.Sum([]byte(path)) 206 | newPath := filepath.Join(p.tmpDir, p.Name+"-kustomize-values-"+hex.EncodeToString(hash[:])+".yaml") 207 | return newPath, ioutil.WriteFile(newPath, b, 0644) 208 | } 209 | 210 | func (p *HelmChartInflationGeneratorPlugin) cleanup() { 211 | if p.tmpDir != "" { 212 | os.RemoveAll(p.tmpDir) 213 | } 214 | } 215 | 216 | func (p *HelmChartInflationGeneratorPlugin) Generate() (rm resmap.ResMap, err error) { 217 | defer p.cleanup() 218 | if err = p.checkHelmVersion(); err != nil { 219 | return nil, err 220 | } 221 | if _, exists := p.chartExistsLocally(); !exists { 222 | if _, err := p.runHelmCommand(p.pullCommand()); err != nil { 223 | return nil, err 224 | } 225 | } 226 | var valuesFiles []string 227 | for _, valuesFile := range p.ValuesFiles { 228 | file, err := p.createNewMergedValuesFiles(valuesFile) 229 | if err != nil { 230 | return nil, err 231 | } 232 | valuesFiles = append(valuesFiles, file) 233 | } 234 | p.ValuesFiles = valuesFiles 235 | 236 | var stdout []byte 237 | stdout, err = p.runHelmCommand(p.templateCommand()) 238 | if err != nil { 239 | return nil, err 240 | } 241 | 242 | factory := NewResMapFactory() 243 | rm, err = factory.NewResMapFromBytes(stdout) 244 | if err == nil { 245 | return rm, nil 246 | } 247 | // try to remove the contents before first "---" because 248 | // helm may produce messages to stdout before it 249 | stdoutStr := string(stdout) 250 | if idx := strings.Index(stdoutStr, "---"); idx != -1 { 251 | return factory.NewResMapFromBytes([]byte(stdoutStr[idx:])) 252 | } 253 | return nil, err 254 | } 255 | 256 | func (p *HelmChartInflationGeneratorPlugin) templateCommand() []string { 257 | args := []string{"template"} 258 | if p.ReleaseName != "" { 259 | args = append(args, p.ReleaseName) 260 | } 261 | if p.Namespace != "" { 262 | args = append(args, "--namespace", p.Namespace) 263 | } 264 | if p.NameTemplate != "" { 265 | args = append(args, "--name-template", p.NameTemplate) 266 | } 267 | if p.Name != "" { 268 | args = append(args, filepath.Join(p.absChartHome(), p.Name)) 269 | } 270 | for _, valuesFile := range p.ValuesFiles { 271 | args = append(args, "-f", valuesFile) 272 | } 273 | for _, apiVer := range p.ApiVersions { 274 | args = append(args, "--api-versions", apiVer) 275 | } 276 | if p.ReleaseName == "" { 277 | // AFAICT, this doesn't work as intended due to a bug in helm. 278 | // See https://github.com/helm/helm/issues/6019 279 | // I've tried placing the flag before and after the name argument. 280 | args = append(args, "--generate-name") 281 | } 282 | if p.Description != "" { 283 | args = append(args, "--description", p.Description) 284 | } 285 | if p.IncludeCRDs { 286 | args = append(args, "--include-crds") 287 | } 288 | if p.SkipTests { 289 | args = append(args, "--skip-tests") 290 | } 291 | return args 292 | } 293 | 294 | func (p *HelmChartInflationGeneratorPlugin) pullCommand() []string { 295 | args := []string{ 296 | "pull", 297 | "--untar", 298 | "--untardir", p.absChartHome()} 299 | if p.Repo != "" { 300 | args = append(args, "--repo", p.Repo) 301 | } 302 | if p.Name != "" { 303 | args = append(args, p.Name) 304 | } 305 | if p.Version != "" { 306 | args = append(args, "--version", p.Version) 307 | } 308 | return args 309 | } 310 | 311 | // chartExistsLocally will return true if the chart does exist in 312 | // local chart home. 313 | func (p *HelmChartInflationGeneratorPlugin) chartExistsLocally() (string, bool) { 314 | path := filepath.Join(p.absChartHome(), p.Name) 315 | s, err := os.Stat(path) 316 | if err != nil { 317 | return path, false 318 | } 319 | return path, s.IsDir() 320 | } 321 | 322 | // checkHelmVersion will return an error if the helm version is not V3 323 | func (p *HelmChartInflationGeneratorPlugin) checkHelmVersion() error { 324 | stdout, err := p.runHelmCommand([]string{"version", "-c", "--short"}) 325 | if err != nil { 326 | return err 327 | } 328 | r, err := regexp.Compile(`v?\d+(\.\d+)+`) 329 | if err != nil { 330 | return err 331 | } 332 | v := r.FindString(string(stdout)) 333 | if v == "" { 334 | return fmt.Errorf("cannot find version string in %s", string(stdout)) 335 | } 336 | if v[0] == 'v' { 337 | v = v[1:] 338 | } 339 | majorVersion := strings.Split(v, ".")[0] 340 | if majorVersion != "3" { 341 | return fmt.Errorf("this HelmChartInflationGeneratorPlugin requires helm V3 but got v%s", v) 342 | } 343 | return nil 344 | } 345 | 346 | func NewResMapFactory() *resmap.Factory { 347 | resourceFactory := resource.NewFactory(&hasher.Hasher{}) 348 | resourceFactory.IncludeLocalConfigs = true 349 | return resmap.NewFactory(resourceFactory) 350 | } 351 | -------------------------------------------------------------------------------- /krm-functions/sig-cli/render-helm-chart/third_party/sigs.k8s.io/kustomize/api/types/helmchartargs.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Kubernetes Authors. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package types 5 | 6 | type HelmGlobals struct { 7 | // ChartHome is a file path to a directory containing a subdirectory for 8 | // each chart to be included in the output. The default value of this field 9 | // is "tmp/charts". 10 | // At runtime, the function will look for the chart under {ChartHome}. If it 11 | // is there, the function will use it as found. If it is not there, the 12 | // function will attempt to pull it and put it in {ChartHome}. 13 | // When run as a container function, local directories must be mounted into 14 | // the container in order for the function to use them. 15 | // If the function needs to pull the helm chart while running in a container, 16 | // ChartHome MUST start with "tmp/". 17 | ChartHome string `json:"chartHome,omitempty" yaml:"chartHome,omitempty"` 18 | 19 | // ConfigHome defines a value that the function should pass to helm via 20 | // the HELM_CONFIG_HOME environment variable. The function doesn't attempt 21 | // to read or write this directory. 22 | // If omitted, {tmpDir}/helm is used, where {tmpDir} is some temporary 23 | // directory created by the function for the benefit of helm. 24 | // Likewise, the function sets 25 | // HELM_CACHE_HOME={ConfigHome}/.cache 26 | // HELM_DATA_HOME={ConfigHome}/.data 27 | // for the helm subprocess. 28 | ConfigHome string `json:"configHome,omitempty" yaml:"configHome,omitempty"` 29 | } 30 | 31 | type HelmChart struct { 32 | // ChartArgs encapsulates information about the chart being inflated, including 33 | // the chart's name, version, and repo. 34 | ChartArgs `json:"chartArgs,omitempty" yaml:"chartArgs,omitempty"` 35 | 36 | // TemplateOptions are fields that become flags to `helm template` when 37 | // the helm chart is being rendered. 38 | TemplateOptions `json:"templateOptions,omitempty" yaml:"templateOptions,omitempty"` 39 | } 40 | 41 | type ChartArgs struct { 42 | // Name is the name of the chart, e.g. 'minecraft'. 43 | Name string `json:"name,omitempty" yaml:"name,omitempty"` 44 | 45 | // Version is the version of the chart, e.g. '3.1.3' 46 | Version string `json:"version,omitempty" yaml:"version,omitempty"` 47 | 48 | // Repo is a URL locating the chart on the internet. 49 | // This is the argument to helm's `--repo` flag, e.g. 50 | // `https://itzg.github.io/minecraft-server-charts`. 51 | Repo string `json:"repo,omitempty" yaml:"repo,omitempty"` 52 | } 53 | 54 | type TemplateOptions struct { 55 | // ApiVersions is the kubernetes apiversions used for Capabilities.APIVersions 56 | ApiVersions []string `json:"apiVerions,omitempty" yaml:"apiVersions,omitempty"` 57 | 58 | // ReleaseName replaces RELEASE-NAME in chart template output, 59 | // making a particular inflation of a chart unique with respect to 60 | // other inflations of the same chart in a cluster. It's the first 61 | // argument to the helm `install` and `template` commands, i.e. 62 | // helm install {RELEASE-NAME} {chartName} 63 | // helm template {RELEASE-NAME} {chartName} 64 | // If omitted, the flag --generate-name is passed to 'helm template'. 65 | ReleaseName string `json:"releaseName,omitempty" yaml:"releaseName,omitempty"` 66 | 67 | // Namespace set the target namespace for a release. It is .Release.Namespace 68 | // in the helm template 69 | Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"` 70 | 71 | // Description is a custom description to add when rendering the helm chart. 72 | Description string `json:"description,omitempty" yaml:"description,omitempty"` 73 | 74 | // NameTemplate is for specifying the name template used to name the release. 75 | NameTemplate string `json:"nameTemplate,omitempty" yaml:"nameTemplate,omitempty"` 76 | 77 | // IncludeCRDs specifies if Helm should also generate CustomResourceDefinitions. 78 | // Defaults to false. 79 | IncludeCRDs bool `json:"includeCRDs,omitempty" yaml:"includeCRDs,omitempty"` 80 | 81 | // SkipTests skips tests from templated output. 82 | SkipTests bool `json:"skipTests,omitempty" yaml:"skipTests,omitempty"` 83 | 84 | // Values are values that are specified inline or in a yaml file to use. 85 | Values `json:"values,omitempty" yaml:"values,omitempty"` 86 | } 87 | 88 | type Values struct { 89 | // ValuesFiles is a list of local file paths to values files to use instead of 90 | // the default values that accompanied the chart. 91 | // The default values are in '{ChartHome}/{Name}/values.yaml'. 92 | ValuesFiles []string `json:"valuesFiles,omitempty" yaml:"valuesFiles,omitempty"` 93 | 94 | // ValuesInline holds value mappings specified directly, 95 | // rather than in a separate file. 96 | ValuesInline map[string]interface{} `json:"valuesInline,omitempty" yaml:"valuesInline,omitempty"` 97 | 98 | // ValuesMerge specifies how to treat ValuesInline with respect to Values. 99 | // Legal values: 'merge', 'override', 'replace'. 100 | // Defaults to 'override'. 101 | ValuesMerge string `json:"valuesMerge,omitempty" yaml:"valuesMerge,omitempty"` 102 | } 103 | -------------------------------------------------------------------------------- /publishers/README.md: -------------------------------------------------------------------------------- 1 | # Publishers 2 | 3 | This directory is the home for all published KRM functions metadata. Each publisher should create their own 4 | subdirectory containing: 5 | 6 | - An OWNERS file containing a list of owners of the publisher 7 | - A README.md file with a description of who the publisher is 8 | - A `functions` directory, containing a file for each published KRM function. The KRM function metadata file should be named after the function, 9 | `{FUNCTION-NAME}.yaml`. This file should be a kubernetes object of type KRMFunctionDefinition, 10 | which is defined in the [Catalog KEP]. 11 | - A `catalogs` directory, containing a file for each published functions Catalog. Each catalog file should be named with the date it was 12 | published, in the form `v{YYYY}{MM}{DD}.yaml`, e.g. `v20220225.yaml`. 13 | 14 | See [SIG-CLI functions] as an example. 15 | 16 | [SIG-CLI functions]: (https://github.com/kubernetes-sigs/krm-functions-registry/tree/main/publishers/sig-cli) 17 | 18 | [Catalog KEP]: https://github.com/kubernetes/enhancements/tree/master/keps/sig-cli/2906-kustomize-function-catalog#function-metadata-schema -------------------------------------------------------------------------------- /publishers/sig-cli/OWNERS: -------------------------------------------------------------------------------- 1 | # See the OWNERS docs at https://go.k8s.io/owners 2 | 3 | approvers: 4 | - sig-cli-functions-approvers 5 | -------------------------------------------------------------------------------- /publishers/sig-cli/README.md: -------------------------------------------------------------------------------- 1 | This directory contains published KRM function metadata and catalogs for 2 | [SIG-CLI](https://github.com/kubernetes/community/tree/master/sig-cli). -------------------------------------------------------------------------------- /publishers/sig-cli/catalogs/v20220225.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # This file is just a placeholder until we have a published catalog. -------------------------------------------------------------------------------- /publishers/sig-cli/functions/render-helm-chart.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # TODO: Add CI to validate the metadata here. 16 | 17 | apiVersion: config.kubernetes.io/v1alpha1 18 | kind: KRMFunctionDefinition 19 | spec: 20 | group: config.kubernetes.io 21 | description: "The `render-helm-chart` function renders a local or remote Helm chart." 22 | publisher: https://github.com/kubernetes/community/tree/master/sig-cli 23 | names: 24 | kind: RenderHelmChart 25 | versions: 26 | - name: v1 27 | idempotent: true 28 | license: Apache 2.0 29 | maintainers: 30 | - natashasarkar@google.com 31 | - mengqiy@google.com 32 | - katrina.verey@shopify.com 33 | usage: https://github.com/kubernetes-sigs/krm-functions-registry/blob/main/krm-functions/sig-cli/render-helm-chart/README.md 34 | examples: 35 | - https://github.com/kubernetes-sigs/krm-functions-registry/blob/main/krm-functions/sig-cli/render-helm-chart/examples/render-helm-chart-kustomize-inline-values/README.md 36 | - https://github.com/kubernetes-sigs/krm-functions-registry/blob/main/krm-functions/sig-cli/render-helm-chart/examples/render-helm-chart-kustomize-values-files/README.md 37 | runtime: 38 | container: 39 | image: us.gcr.io/k8s-artifacts-prod/krm-functions/render-helm-chart:unstable 40 | requireNetwork: true 41 | requireStorageMount: true 42 | schema: 43 | openAPIV3Schema: 44 | properties: 45 | apiVersion: 46 | type: string 47 | kind: 48 | type: string 49 | metadata: 50 | type: object 51 | properties: 52 | name: 53 | type: string 54 | minLength: 1 55 | required: 56 | - name 57 | helmGlobals: 58 | description: parameters applied to all helm charts. 59 | type: object 60 | properties: 61 | chartHome: 62 | description: 63 | type: string 64 | configHome: 65 | description: 66 | type: string 67 | helmCharts: 68 | description: an array of helm chart parameters. 69 | type: array 70 | items: 71 | type: object 72 | description: parameters to configure the helm chart rendering. 73 | properties: 74 | chartArgs: 75 | description: arguments that describe the chart being rendered. 76 | type: object 77 | properties: 78 | name: 79 | description: the name of the chart. 80 | type: string 81 | version: 82 | description: the version of the chart. 83 | type: string 84 | repo: 85 | description: URL locating the chart on the internet 86 | type: string 87 | templateOptions: 88 | description: a collection of fields that map to flag options of `helm template`. 89 | type: object 90 | properties: 91 | apiVersions: 92 | description: kubernetes api versions used for Capabilities.APIVersions 93 | type: array 94 | items: 95 | type: string 96 | releaseName: 97 | description: replaces RELEASE_NAME in the chart template output 98 | type: string 99 | namespace: 100 | description: sets the target namespace for a release (`.Release.Namespace` in the template) 101 | type: string 102 | nameTemplate: 103 | description: specifies the template used to name the release 104 | type: string 105 | includeCRDs: 106 | description: specifies if Helm should also generate CustomResourceDefinitions. Legal values are "true", "false" (default). 107 | type: bool 108 | skipTests: 109 | description: if set, skip tests from templated output. Legal values are "true", "false" (default). 110 | type: bool 111 | values: 112 | description: values to use instead of the default values that accompany the chart. 113 | type: object 114 | properties: 115 | valuesFiles: 116 | description: remote or local filepaths to use instead of the default values that accompanied the chart. The default values are in '{chartHome}/{name}/values.yaml', where `chartHome` and `name` are the parameters defined above. 117 | type: array 118 | items: 119 | type: string 120 | valuesInline: 121 | description: values defined inline to use instead of default values that accompany the chart. 122 | type: object 123 | additionalProperties: 124 | type: string 125 | valuesMerge: 126 | description: valuesMerge specifies how to treat ValuesInline with respect to ValuesFiles. Legal values are 'merge', 'override' (default), 'replace'. 127 | type: string 128 | -------------------------------------------------------------------------------- /site/README.md: -------------------------------------------------------------------------------- 1 | # Site \[TODO\] 2 | 3 | This directory will contain the source code for the site contents that will be used to display 4 | the published functions metadata. -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2022 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | make all 18 | -------------------------------------------------------------------------------- /tests/e2e_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Kubernetes Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package tests 16 | 17 | import ( 18 | "testing" 19 | 20 | "github.com/GoogleContainerTools/kpt/pkg/test/runner" 21 | ) 22 | 23 | // TestExamples runs all in-tree examples in the ../krm-functions/sig-cli directory as tests. 24 | // 25 | // It expects each subdirectory to have a '.expected' folder with the following files: 26 | // - 'config.yaml' has the configuration, containing the following fields: 27 | // - 'exitCode': The expected exit code (default 0) 28 | // - 'skip': If set to true, this test will be skipped (default false) 29 | // - 'exec.sh' is a script to run in the current directory. For example, to test a kustomization 30 | // file output, this can be something like `kustomize build` > resources.yaml. 31 | // - 'diff.patch' is the expected diff output between original directory files and 32 | // files after exec script running. 33 | // 34 | func TestExamples(t *testing.T) { 35 | cases, err := runner.ScanTestCases("../krm-functions") 36 | if err != nil { 37 | t.Fatalf(err.Error()) 38 | } 39 | for _, c := range *cases { 40 | c := c 41 | c.Config.ImagePullPolicy = "never" 42 | t.Run(c.Path, func(t *testing.T) { 43 | r, err := runner.NewRunner(t, c, c.Config.TestType) 44 | if err != nil { 45 | t.Fatalf("error creating test runner: %s", err) 46 | } 47 | if r.Skip() { 48 | t.Skip() 49 | } 50 | err = r.Run() 51 | if err != nil { 52 | t.Fatalf("error running test: %s", err) 53 | } 54 | }) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tests/go.mod: -------------------------------------------------------------------------------- 1 | module sigs.k8s.io/krm-functions-registry/tests 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/GoogleContainerTools/kpt v1.0.0-beta.13.0.20220208222711-5169954be82f 7 | github.com/stretchr/testify v1.7.0 8 | k8s.io/kube-openapi v0.0.0-20211109043139-026bd182f079 9 | sigs.k8s.io/kustomize/kyaml v0.13.3 10 | sigs.k8s.io/yaml v1.2.0 11 | ) 12 | 13 | require ( 14 | github.com/PuerkitoBio/purell v1.1.1 // indirect 15 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect 16 | github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect 17 | github.com/davecgh/go-spew v1.1.1 // indirect 18 | github.com/go-errors/errors v1.4.0 // indirect 19 | github.com/go-openapi/jsonpointer v0.19.5 // indirect 20 | github.com/go-openapi/jsonreference v0.19.5 // indirect 21 | github.com/go-openapi/swag v0.19.14 // indirect 22 | github.com/google/go-cmp v0.5.6 // indirect 23 | github.com/josharian/intern v1.0.0 // indirect 24 | github.com/mailru/easyjson v0.7.6 // indirect 25 | github.com/mitchellh/mapstructure v1.4.1 // indirect 26 | github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect 27 | github.com/pkg/errors v0.9.1 // indirect 28 | github.com/pmezard/go-difflib v1.0.0 // indirect 29 | github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect 30 | golang.org/x/net v0.0.0-20210520170846-37e1c6afe023 // indirect 31 | golang.org/x/text v0.3.6 // indirect 32 | gopkg.in/yaml.v2 v2.4.0 // indirect 33 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect 34 | k8s.io/utils v0.0.0-20210820185131-d34e5cb4466e // indirect 35 | ) 36 | 37 | replace sigs.k8s.io/kustomize/kyaml => sigs.k8s.io/kustomize/kyaml v0.13.4-0.20220224183231-6950a0d24640 38 | -------------------------------------------------------------------------------- /tests/testutils.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Kubernetes Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package tests 16 | 17 | const KrmFunctionSchema = `swagger: "2.0" 18 | info: 19 | title: KRM Function Metadata 20 | version: v1alpha1 21 | definitions: 22 | KRMFunctionDefinition: 23 | type: object 24 | description: | 25 | KRMFunctionDefinition is metadata that defines a KRM function 26 | the same way a CustomResourceDefinition defines a custom resource. 27 | x-kubernetes-group-version-kind: 28 | - group: config.kubernetes.io 29 | kind: KRMFunctionDefinition 30 | version: v1alpha1 31 | required: 32 | - apiVersion 33 | - kind 34 | - spec 35 | properties: 36 | apiVersion: 37 | description: apiVersion of KRMFunctionDefinition. i.e. config.kubernetes.io/v1alpha1 38 | type: string 39 | enum: 40 | - config.kubernetes.io/v1alpha1 41 | kind: 42 | description: kind of the KRMFunctionDefinition. It must be KRMFunctionDefinition. 43 | type: string 44 | enum: 45 | - KRMFunctionDefinition 46 | spec: 47 | type: object 48 | description: spec contains the metadata for a KRM function. 49 | required: 50 | - group 51 | - names 52 | - description 53 | - publisher 54 | - versions 55 | properties: 56 | group: 57 | description: group of the functionConfig 58 | type: string 59 | description: 60 | description: brief description of the KRM function. 61 | type: string 62 | publisher: 63 | description: the entity (e.g. organization) that produced and owns this KRM function. 64 | type: string 65 | names: 66 | description: the resource and kind names for the KRM function 67 | type: object 68 | required: 69 | - kind 70 | properties: 71 | kind: 72 | description: the Kind of the functionConfig 73 | type: string 74 | versions: 75 | description: the versions of the functionConfig 76 | type: array 77 | items: 78 | type: object 79 | required: 80 | - name 81 | - schema 82 | - idempotent 83 | - runtime 84 | - usage 85 | - examples 86 | - license 87 | properties: 88 | name: 89 | description: Version of the functionConfig 90 | type: string 91 | schema: 92 | description: a URI pointing to the schema of the functionConfig 93 | type: object 94 | required: 95 | - openAPIV3Schema 96 | properties: 97 | openAPIV3Schema: 98 | description: openAPIV3Schema is the OpenAPI v3 schema to use for validation 99 | # kube-openapi validation doesn't support references, and inlining this ref is extremely tedious 100 | # $ref: "#/definitions/io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1.JSONSchemaProps" 101 | idempotent: 102 | description: If the function is idempotent. 103 | type: boolean 104 | usage: 105 | description: | 106 | A URI pointing to a README.md that describe the details of how to 107 | use the KRM function. It should at least cover what the function 108 | does and what functionConfig does it support and it should give 109 | detailed explanation about each field in the functionConfig. 110 | type: string 111 | examples: 112 | description: | 113 | A list of URIs that point to README.md files. At least one example 114 | must be provided. Each README.md should cover an example. It 115 | should at least cover how to get input resources, how to run it 116 | and what is the expected output. 117 | type: array 118 | items: 119 | type: string 120 | license: 121 | description: The license of the KRM function. 122 | type: string 123 | enum: 124 | - Apache 2.0 125 | maintainers: 126 | description: | 127 | The maintainers for the function. It should only be used 128 | when the maintainers are different from the ones in 129 | spec.maintainers. When this field is specified, it 130 | override spec.maintainers. 131 | type: array 132 | items: 133 | type: string 134 | runtime: 135 | description: | 136 | The runtime information about the KRM function. At least one of 137 | container and exec must be set. 138 | type: object 139 | properties: 140 | container: 141 | description: The runtime information for container-based KRM function. 142 | type: object 143 | required: 144 | - image 145 | properties: 146 | image: 147 | description: The image name of the KRM function. 148 | type: string 149 | sha256: 150 | description: | 151 | The digest of the image that can be verified against. It 152 | is required only when the image is using semver. 153 | type: string 154 | requireNetwork: 155 | description: If network is required to run this function. 156 | type: boolean 157 | requireStorageMount: 158 | description: If storage mount is required to run this function. 159 | type: boolean 160 | exec: 161 | description: The runtime information for exec-based KRM function. 162 | type: object 163 | required: 164 | - platform 165 | properties: 166 | platforms: 167 | description: Per platform runtime information. 168 | type: array 169 | items: 170 | type: object 171 | required: 172 | - bin 173 | - os 174 | - arch 175 | - uri 176 | - sha256 177 | properties: 178 | bin: 179 | description: The binary name. 180 | type: string 181 | os: 182 | description: The target operating system to run the KRM function. 183 | type: string 184 | enum: 185 | - linux 186 | - darwin 187 | - windows 188 | arch: 189 | description: The target architecture to run the KRM function. 190 | type: string 191 | enum: 192 | - amd64 193 | - arm64 194 | uri: 195 | description: The location to download the binary. 196 | type: string 197 | sha256: 198 | description: The degist of the binary that can be used to verify the binary. 199 | type: string 200 | home: 201 | description: A URI pointing the home page of the KRM function. 202 | type: string 203 | maintainers: 204 | description: The maintainers for the function. 205 | type: array 206 | items: 207 | type: string 208 | tags: 209 | description: | 210 | The tags (or keywords) of the function. e.g. mutator, validator, 211 | generator, prefix, GCP. 212 | type: array 213 | items: 214 | type: string 215 | paths: {} 216 | ` 217 | -------------------------------------------------------------------------------- /tests/validate-metadata_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Kubernetes Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package tests 16 | 17 | import ( 18 | "encoding/json" 19 | "os" 20 | "path/filepath" 21 | "testing" 22 | 23 | "github.com/stretchr/testify/assert" 24 | "github.com/stretchr/testify/require" 25 | "k8s.io/kube-openapi/pkg/validation/spec" 26 | "k8s.io/kube-openapi/pkg/validation/strfmt" 27 | "k8s.io/kube-openapi/pkg/validation/validate" 28 | "sigs.k8s.io/kustomize/kyaml/fn/framework" 29 | k8syaml "sigs.k8s.io/yaml" 30 | ) 31 | 32 | // TestValidateMetadata validates that the function metadata in each function metadata 33 | // file of the publishers directory is a valid KRMFunctionDefinition. 34 | func TestValidateMetadata(t *testing.T) { 35 | assert.NoError(t, os.Chdir("../publishers")) 36 | publishers, err := os.ReadDir(".") 37 | assert.NoError(t, err) 38 | 39 | for _, publisher := range publishers { 40 | if publisher.IsDir() { 41 | functionDir := filepath.Join(publisher.Name(), "functions") 42 | functions, err := os.ReadDir(functionDir) 43 | assert.NoError(t, err) 44 | 45 | for _, function := range functions { 46 | validateFunctionMetadata(t, filepath.Join(functionDir, function.Name())) 47 | } 48 | } 49 | } 50 | } 51 | 52 | func validateFunctionMetadata(t *testing.T, path string) { 53 | functionMetadata, err := os.ReadFile(path) 54 | require.NoError(t, err) 55 | 56 | schemaJSON, err := k8syaml.YAMLToJSON([]byte(KrmFunctionSchema)) 57 | require.NoError(t, err) 58 | 59 | swagger := &spec.Swagger{} 60 | require.NoError(t, swagger.UnmarshalJSON(schemaJSON)) 61 | 62 | var input map[string]interface{} 63 | inputJSON, err := k8syaml.YAMLToJSON(functionMetadata) 64 | require.NoError(t, err) 65 | require.NoError(t, json.Unmarshal(inputJSON, &input)) 66 | 67 | schema := swagger.Definitions["KRMFunctionDefinition"] 68 | schemaValidationError := validate.AgainstSchema(&schema, 69 | input, strfmt.Default) 70 | 71 | require.NoError(t, schemaValidationError) 72 | 73 | var def framework.KRMFunctionDefinition 74 | err = k8syaml.Unmarshal(functionMetadata, &def) 75 | require.NoError(t, err) 76 | } 77 | --------------------------------------------------------------------------------