diff --git a/Makefile b/Makefile index 62c570f61aa..5eaccce44ed 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# Copyright 2019 The Kubernetes Authors. +# Copyright 2023 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -64,6 +64,7 @@ install: build ## Build and install the binary with the current source code. Use .PHONY: generate generate: generate-testdata ## Update/generate all mock data. You should run this commands to update the mock data after your changes. + ./docs/docs.sh go mod tidy .PHONY: generate-testdata @@ -71,6 +72,11 @@ generate-testdata: ## Update/generate the testdata in $GOPATH/src/sigs.k8s.io/ku rm -rf testdata/ ./test/testdata/generate.sh +.PHONY: generate-docs +generate-docs: ## Update/generate the docs in $GOPATH/src/sigs.k8s.io/kubebuilder + source "test/common.sh" && build_kb + ./docs/docs.sh + .PHONY: lint lint: golangci-lint yamllint ## Run golangci-lint linter & yamllint $(GOLANGCI_LINT) run diff --git a/docs/book/src/component-config-tutorial/generate_docs.go b/docs/book/src/component-config-tutorial/generate_docs.go new file mode 100644 index 00000000000..751ac82eeca --- /dev/null +++ b/docs/book/src/component-config-tutorial/generate_docs.go @@ -0,0 +1,196 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package componentconfig + +import ( + "os" + "path/filepath" + + log "github.com/sirupsen/logrus" + + "github.com/spf13/afero" + pluginutil "sigs.k8s.io/kubebuilder/v3/pkg/plugin/util" + "sigs.k8s.io/kubebuilder/v3/test/e2e/utils" +) + +type Sample struct { + ctx *utils.TestContext +} + +func NewSample(binaryPath, samplePath string) Sample { + log.Infof("Generating the sample context of component-config...") + + ctx := newSampleContext(binaryPath, samplePath, "GO111MODULE=on") + + return Sample{&ctx} +} + +func newSampleContext(binaryPath string, samplePath string, env ...string) utils.TestContext { + cmdContext := &utils.CmdContext{ + Env: env, + Dir: samplePath, + } + + testContext := utils.TestContext{ + CmdContext: cmdContext, + BinaryName: binaryPath, + } + + return testContext +} + +// Prepare the Context for the sample project +func (sp *Sample) Prepare() { + log.Infof("destroying directory for sample project") + sp.ctx.Destroy() + + log.Infof("refreshing tools and creating directory...") + err := sp.ctx.Prepare() + + CheckError("creating directory for sample project", err) +} + +func (sp *Sample) GenerateSampleProject() { + log.Infof("Initializing the project") + err := sp.ctx.Init( + "--domain", "tutorial.kubebuilder.io", + "--repo", "tutorial.kubebuilder.io/project", + "--license", "apache2", + "--owner", "The Kubernetes authors", + "component-config", + ) + CheckError("Initializing the project", err) + + log.Infof("Adding a new config type") + err = sp.ctx.CreateAPI( + "--group", "config", + "--version", "v2", + "--kind", "ProjectConfig", + "--resource", "--controller=false", + "--make=false", + ) + CheckError("Creating the API", err) +} + +func (sp *Sample) UpdateTutorial() { + // 1. generate controller_manager_config.yaml + var fs = afero.NewOsFs() + err := afero.WriteFile(fs, filepath.Join(sp.ctx.Dir, "config/manager/controller_manager_config.yaml"), + []byte(`apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 +kind: ControllerManagerConfig +metadata: + labels: + app.kubernetes.io/name: controllermanagerconfig + app.kubernetes.io/instance: controller-manager-configuration + app.kubernetes.io/component: manager + app.kubernetes.io/created-by: project + app.kubernetes.io/part-of: project + app.kubernetes.io/managed-by: kustomize +health: + healthProbeBindAddress: :8081 +metrics: + bindAddress: 127.0.0.1:8080 +webhook: + port: 9443 +leaderElection: + leaderElect: true + resourceName: 80807133.tutorial.kubebuilder.io +clusterName: example-test`), 0600, + ) + CheckError("fixing controller_manager_config", err) + + // 2. add componentconfig + err = pluginutil.InsertCode( + filepath.Join(sp.ctx.Dir, "PROJECT"), + "More info: https://book.kubebuilder.io/reference/project-config.html", + "\ncomponentConfig: true", + ) + CheckError("fixing PROJECT", err) + + // 3. fix projectconfig_types.go + err = pluginutil.InsertCode( + filepath.Join(sp.ctx.Dir, "api/v2/projectconfig_types.go"), + "metav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"", + "\n cfg \"sigs.k8s.io/controller-runtime/pkg/config/v1alpha1\"", + ) + CheckError("fixing projectconfig_types", err) + + err = pluginutil.InsertCode( + filepath.Join(sp.ctx.Dir, "api/v2/projectconfig_types.go"), + "Status ProjectConfigStatus `json:\"status,omitempty\"`", + //nolint:lll + "\n // ControllerManagerConfigurationSpec returns the configurations for controllers\n cfg.ControllerManagerConfigurationSpec `json:\",inline\"`\n\n ClusterName string `json:\"clusterName,omitempty\"`", + ) + CheckError("fixing projectconfig_types", err) + + // 4. fix kustomization.yaml + err = pluginutil.InsertCode( + filepath.Join(sp.ctx.Dir, "config/default/kustomization.yaml"), + "manager_auth_proxy_patch.yaml", + //nolint:lll + "\n\n# Mount the controller config file for loading manager configurations\n# through a ComponentConfig type\n- manager_config_patch.yaml", + ) + CheckError("fixing default/kustomization", err) + + err = pluginutil.InsertCode( + filepath.Join(sp.ctx.Dir, "config/manager/kustomization.yaml"), + "- manager.yaml", + //nolint:lll + "\n\ngeneratorOptions:\n disableNameSuffixHash: true\nconfigMapGenerator:\n- name: manager-config\n files:\n - controller_manager_config.yaml", + ) + CheckError("fixing manager/kustomization", err) + + // 5. fix manager_config_patch + err = pluginutil.InsertCode( + filepath.Join(sp.ctx.Dir, "config/default/manager_config_patch.yaml"), + "name: manager", + //nolint:lll + "\n args:\n - \"--config=controller_manager_config.yaml\"\n volumeMounts:\n - name: manager-config\n mountPath: /controller_manager_config.yaml\n subPath: controller_manager_config.yaml\n volumes:\n - name: manager-config\n configMap:\n name: manager-config", + ) + CheckError("fixing manager_config_patch", err) + + // 6. fix main + err = pluginutil.InsertCode( + filepath.Join(sp.ctx.Dir, "main.go"), + "ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))", + //nolint:lll + "\n\n var err error\n ctrlConfig := configv2.ProjectConfig{}\n options := ctrl.Options{Scheme: scheme}\n if configFile != \"\" {\n options, err = options.AndFrom(ctrl.ConfigFile().AtPath(configFile).OfKind(&ctrlConfig))\n if err != nil {\n setupLog.Error(err, \"unable to load the config file\")\n os.Exit(1)\n }\n }", + ) + CheckError("fixing main.go", err) + + err = pluginutil.ReplaceInFile( + filepath.Join(sp.ctx.Dir, "main.go"), + //nolint:lll + `flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") + flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") + flag.BoolVar(&enableLeaderElection, "leader-elect", false, + "Enable leader election for controller manager. "+ + "Enabling this will ensure there is only one active controller manager.") +`, + //nolint:lll + "var configFile string\n flag.StringVar(&configFile, \"config\", \"\",\n \"The controller will load its initial configuration from this file. \"+\n \"Omit this flag to use the default configuration values. \"+\n \"Command-line flags override configuration from this file.\")\n", + ) + CheckError("fixing main.go", err) +} + +// CheckError will exit with exit code 1 when err is not nil. +func CheckError(msg string, err error) { + if err != nil { + log.Errorf("error %s: %s", msg, err) + os.Exit(1) + } +} diff --git a/docs/book/src/component-config-tutorial/testdata/project/README.md b/docs/book/src/component-config-tutorial/testdata/project/README.md index 4e55b988a3b..3a778e70fb1 100644 --- a/docs/book/src/component-config-tutorial/testdata/project/README.md +++ b/docs/book/src/component-config-tutorial/testdata/project/README.md @@ -78,7 +78,7 @@ More information can be found via the [Kubebuilder Documentation](https://book.k ## License -Copyright 2023. +Copyright 2023 The Kubernetes authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/docs/book/src/component-config-tutorial/testdata/project/api/v2/groupversion_info.go b/docs/book/src/component-config-tutorial/testdata/project/api/v2/groupversion_info.go index 8d87debb460..12badc8da4e 100644 --- a/docs/book/src/component-config-tutorial/testdata/project/api/v2/groupversion_info.go +++ b/docs/book/src/component-config-tutorial/testdata/project/api/v2/groupversion_info.go @@ -1,5 +1,5 @@ /* -Copyright 2023. +Copyright 2023 The Kubernetes authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/docs/book/src/component-config-tutorial/testdata/project/api/v2/projectconfig_types.go b/docs/book/src/component-config-tutorial/testdata/project/api/v2/projectconfig_types.go index 224fa7ec4eb..85e058ae086 100644 --- a/docs/book/src/component-config-tutorial/testdata/project/api/v2/projectconfig_types.go +++ b/docs/book/src/component-config-tutorial/testdata/project/api/v2/projectconfig_types.go @@ -1,5 +1,5 @@ /* -Copyright 2023. +Copyright 2023 The Kubernetes authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -49,7 +49,6 @@ type ProjectConfig struct { Spec ProjectConfigSpec `json:"spec,omitempty"` Status ProjectConfigStatus `json:"status,omitempty"` - // ControllerManagerConfigurationSpec returns the configurations for controllers cfg.ControllerManagerConfigurationSpec `json:",inline"` diff --git a/docs/book/src/component-config-tutorial/testdata/project/api/v2/zz_generated.deepcopy.go b/docs/book/src/component-config-tutorial/testdata/project/api/v2/zz_generated.deepcopy.go index 715af21c786..ed6397b49b3 100644 --- a/docs/book/src/component-config-tutorial/testdata/project/api/v2/zz_generated.deepcopy.go +++ b/docs/book/src/component-config-tutorial/testdata/project/api/v2/zz_generated.deepcopy.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2023. +Copyright 2023 The Kubernetes authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/default/kustomization.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/default/kustomization.yaml index c5d1f660399..a16d5a3fce5 100644 --- a/docs/book/src/component-config-tutorial/testdata/project/config/default/kustomization.yaml +++ b/docs/book/src/component-config-tutorial/testdata/project/config/default/kustomization.yaml @@ -30,11 +30,12 @@ patchesStrategicMerge: # endpoint w/o any authn/z, please comment the following line. - manager_auth_proxy_patch.yaml - # Mount the controller config file for loading manager configurations # through a ComponentConfig type - manager_config_patch.yaml + + # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in # crd/kustomization.yaml #- manager_webhook_patch.yaml diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/default/manager_auth_proxy_patch.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/default/manager_auth_proxy_patch.yaml index 7945f64a1de..b7512661674 100644 --- a/docs/book/src/component-config-tutorial/testdata/project/config/default/manager_auth_proxy_patch.yaml +++ b/docs/book/src/component-config-tutorial/testdata/project/config/default/manager_auth_proxy_patch.yaml @@ -48,3 +48,8 @@ spec: requests: cpu: 5m memory: 64Mi + - name: manager + args: + - "--health-probe-bind-address=:8081" + - "--metrics-bind-address=127.0.0.1:8080" + - "--leader-elect" diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/manager/controller_manager_config.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/manager/controller_manager_config.yaml index 1391a7ad490..61a3a4ddee9 100644 --- a/docs/book/src/component-config-tutorial/testdata/project/config/manager/controller_manager_config.yaml +++ b/docs/book/src/component-config-tutorial/testdata/project/config/manager/controller_manager_config.yaml @@ -17,4 +17,4 @@ webhook: leaderElection: leaderElect: true resourceName: 80807133.tutorial.kubebuilder.io -clusterName: example-test +clusterName: example-test \ No newline at end of file diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/manager/kustomization.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/manager/kustomization.yaml index 2bcd3eeaa94..968035943b5 100644 --- a/docs/book/src/component-config-tutorial/testdata/project/config/manager/kustomization.yaml +++ b/docs/book/src/component-config-tutorial/testdata/project/config/manager/kustomization.yaml @@ -3,7 +3,6 @@ resources: generatorOptions: disableNameSuffixHash: true - configMapGenerator: - name: manager-config files: diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/manager/manager.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/manager/manager.yaml index 6e09e6bf26e..a5989e41094 100644 --- a/docs/book/src/component-config-tutorial/testdata/project/config/manager/manager.yaml +++ b/docs/book/src/component-config-tutorial/testdata/project/config/manager/manager.yaml @@ -68,6 +68,8 @@ spec: containers: - command: - /manager + args: + - --leader-elect image: controller:latest name: manager securityContext: diff --git a/docs/book/src/component-config-tutorial/testdata/project/hack/boilerplate.go.txt b/docs/book/src/component-config-tutorial/testdata/project/hack/boilerplate.go.txt index 65b86227183..8c36d12450d 100644 --- a/docs/book/src/component-config-tutorial/testdata/project/hack/boilerplate.go.txt +++ b/docs/book/src/component-config-tutorial/testdata/project/hack/boilerplate.go.txt @@ -1,5 +1,5 @@ /* -Copyright 2023. +Copyright 2023 The Kubernetes authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/docs/book/src/component-config-tutorial/testdata/project/main.go b/docs/book/src/component-config-tutorial/testdata/project/main.go index 07d4ad17849..0a65c481bd3 100644 --- a/docs/book/src/component-config-tutorial/testdata/project/main.go +++ b/docs/book/src/component-config-tutorial/testdata/project/main.go @@ -1,5 +1,5 @@ /* -Copyright 2023. +Copyright 2023 The Kubernetes authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -48,6 +48,9 @@ func init() { } func main() { + var metricsAddr string + var enableLeaderElection bool + var probeAddr string var configFile string flag.StringVar(&configFile, "config", "", "The controller will load its initial configuration from this file. "+ @@ -72,7 +75,25 @@ func main() { } } - mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), options) + mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ + Scheme: scheme, + MetricsBindAddress: metricsAddr, + Port: 9443, + HealthProbeBindAddress: probeAddr, + LeaderElection: enableLeaderElection, + LeaderElectionID: "80807133.tutorial.kubebuilder.io", + // LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily + // when the Manager ends. This requires the binary to immediately end when the + // Manager is stopped, otherwise, this setting is unsafe. Setting this significantly + // speeds up voluntary leader transitions as the new leader don't have to wait + // LeaseDuration time first. + // + // In the default scaffold provided, the program ends immediately after + // the manager stops, so would be fine to enable this option. However, + // if you are doing or is intended to do any operation such as perform cleanups + // after the manager stops then its usage might be unsafe. + // LeaderElectionReleaseOnCancel: true, + }) if err != nil { setupLog.Error(err, "unable to start manager") os.Exit(1) diff --git a/docs/book/src/update-docs/generate_docs.go b/docs/book/src/update-docs/generate_docs.go new file mode 100644 index 00000000000..5a237c28ec7 --- /dev/null +++ b/docs/book/src/update-docs/generate_docs.go @@ -0,0 +1,47 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "fmt" + + componentconfig "sigs.k8s.io/kubebuilder/v3/docs/book/src/component-config-tutorial" +) + +func main() { + fmt.Println("Generating documents...") + + fmt.Println("Generating component-config tutorial...") + UpdateComponentConfigTutorial() + + // TODO: Generate cronjob-tutorial + + // TODO: Generate multiversion-tutorial +} + +func UpdateComponentConfigTutorial() { + binaryPath := "/tmp/kubebuilder/bin/kubebuilder" + samplePath := "docs/book/src/component-config-tutorial/testdata/project/" + + sp := componentconfig.NewSample(binaryPath, samplePath) + + sp.Prepare() + + sp.GenerateSampleProject() + + sp.UpdateTutorial() +} diff --git a/docs/docs.sh b/docs/docs.sh new file mode 100755 index 00000000000..0b7d15d35ac --- /dev/null +++ b/docs/docs.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +# Copyright 2023 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +go run docs/book/src/update-docs/generate_docs.go + +cd docs/book/src/component-config-tutorial/testdata/project + +make build +