diff --git a/docs/book/src/getting-started/testdata/project/PROJECT b/docs/book/src/getting-started/testdata/project/PROJECT index 9507e610e6..1867160fcb 100644 --- a/docs/book/src/getting-started/testdata/project/PROJECT +++ b/docs/book/src/getting-started/testdata/project/PROJECT @@ -2,7 +2,6 @@ # This file is used to track the info used to scaffold your project # and allow the plugins properly work. # More info: https://book.kubebuilder.io/reference/project-config.html -componentConfig: true domain: example.com layout: - go.kubebuilder.io/v4 diff --git a/docs/book/src/getting-started/testdata/project/api/v1alpha1/memcached_types.go b/docs/book/src/getting-started/testdata/project/api/v1alpha1/memcached_types.go index 83b2e49eba..c605aef4b4 100644 --- a/docs/book/src/getting-started/testdata/project/api/v1alpha1/memcached_types.go +++ b/docs/book/src/getting-started/testdata/project/api/v1alpha1/memcached_types.go @@ -18,7 +18,6 @@ package v1alpha1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - cfg "sigs.k8s.io/controller-runtime/pkg/config/v1alpha1" ) // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! @@ -65,10 +64,6 @@ type Memcached struct { Spec MemcachedSpec `json:"spec,omitempty"` Status MemcachedStatus `json:"status,omitempty"` - // ControllerManagerConfigurationSpec returns the configurations for controllers - cfg.ControllerManagerConfigurationSpec `json:",inline"` - - ClusterName string `json:"clusterName,omitempty"` } //+kubebuilder:object:root=true diff --git a/docs/book/src/getting-started/testdata/project/api/v1alpha1/zz_generated.deepcopy.go b/docs/book/src/getting-started/testdata/project/api/v1alpha1/zz_generated.deepcopy.go index 23d4d278d6..f002d24b13 100644 --- a/docs/book/src/getting-started/testdata/project/api/v1alpha1/zz_generated.deepcopy.go +++ b/docs/book/src/getting-started/testdata/project/api/v1alpha1/zz_generated.deepcopy.go @@ -32,7 +32,6 @@ func (in *Memcached) DeepCopyInto(out *Memcached) { in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) out.Spec = in.Spec in.Status.DeepCopyInto(&out.Status) - in.ControllerManagerConfigurationSpec.DeepCopyInto(&out.ControllerManagerConfigurationSpec) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Memcached. diff --git a/docs/book/src/getting-started/testdata/project/cmd/main.go b/docs/book/src/getting-started/testdata/project/cmd/main.go index d829c4cba1..107c513776 100644 --- a/docs/book/src/getting-started/testdata/project/cmd/main.go +++ b/docs/book/src/getting-started/testdata/project/cmd/main.go @@ -17,6 +17,7 @@ limitations under the License. package main import ( + "crypto/tls" "flag" "os" @@ -30,6 +31,8 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" + metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" + "sigs.k8s.io/controller-runtime/pkg/webhook" cachev1alpha1 "example.com/memcached/api/v1alpha1" "example.com/memcached/internal/controller" @@ -49,11 +52,20 @@ func init() { } func main() { - var configFile string - flag.StringVar(&configFile, "config", "", - "The controller will load its initial configuration from this file. "+ - "Omit this flag to use the default configuration values. "+ - "Command-line flags override configuration from this file.") + var metricsAddr string + var enableLeaderElection bool + var probeAddr string + var secureMetrics bool + var enableHTTP2 bool + 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.") + flag.BoolVar(&secureMetrics, "metrics-secure", false, + "If set the metrics endpoint is served securely") + flag.BoolVar(&enableHTTP2, "enable-http2", false, + "If set, HTTP/2 will be enabled for the metrics and webhook servers") opts := zap.Options{ Development: true, } @@ -62,18 +74,49 @@ func main() { ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) - var err error - ctrlConfig := cachev1alpha1.Memcached{} - options := ctrl.Options{Scheme: scheme} - if configFile != "" { - options, err = options.AndFrom(ctrl.ConfigFile().AtPath(configFile).OfKind(&ctrlConfig)) - if err != nil { - setupLog.Error(err, "unable to load the config file") - os.Exit(1) - } + // if the enable-http2 flag is false (the default), http/2 should be disabled + // due to its vulnerabilities. More specifically, disabling http/2 will + // prevent from being vulnerable to the HTTP/2 Stream Cancellation and + // Rapid Reset CVEs. For more information see: + // - https://github.com/advisories/GHSA-qppj-fm5r-hxr3 + // - https://github.com/advisories/GHSA-4374-p667-p6c8 + disableHTTP2 := func(c *tls.Config) { + setupLog.Info("disabling http/2") + c.NextProtos = []string{"http/1.1"} } - mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), options) + tlsOpts := []func(*tls.Config){} + if !enableHTTP2 { + tlsOpts = append(tlsOpts, disableHTTP2) + } + + webhookServer := webhook.NewServer(webhook.Options{ + TLSOpts: tlsOpts, + }) + + mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ + Scheme: scheme, + Metrics: metricsserver.Options{ + BindAddress: metricsAddr, + SecureServing: secureMetrics, + TLSOpts: tlsOpts, + }, + WebhookServer: webhookServer, + HealthProbeBindAddress: probeAddr, + LeaderElection: enableLeaderElection, + LeaderElectionID: "4b13cc52.example.com", + // 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/getting-started/testdata/project/config/crd/bases/cache.example.com_memcacheds.yaml b/docs/book/src/getting-started/testdata/project/config/crd/bases/cache.example.com_memcacheds.yaml index 63092c9818..b2fdeae633 100644 --- a/docs/book/src/getting-started/testdata/project/config/crd/bases/cache.example.com_memcacheds.yaml +++ b/docs/book/src/getting-started/testdata/project/config/crd/bases/cache.example.com_memcacheds.yaml @@ -26,73 +26,6 @@ spec: may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string - cacheNamespace: - description: |- - CacheNamespace if specified restricts the manager's cache to watch objects in - the desired namespace Defaults to all namespaces - - - Note: If a namespace is specified, controllers can still Watch for a - cluster-scoped resource (e.g Node). For namespaced resources the cache - will only hold objects from the desired namespace. - type: string - clusterName: - type: string - controller: - description: |- - Controller contains global configuration options for controllers - registered within this manager. - properties: - cacheSyncTimeout: - description: |- - CacheSyncTimeout refers to the time limit set to wait for syncing caches. - Defaults to 2 minutes if not set. - format: int64 - type: integer - groupKindConcurrency: - additionalProperties: - type: integer - description: |- - GroupKindConcurrency is a map from a Kind to the number of concurrent reconciliation - allowed for that controller. - - - When a controller is registered within this manager using the builder utilities, - users have to specify the type the controller reconciles in the For(...) call. - If the object's kind passed matches one of the keys in this map, the concurrency - for that controller is set to the number specified. - - - The key is expected to be consistent in form with GroupKind.String(), - e.g. ReplicaSet in apps group (regardless of version) would be `ReplicaSet.apps`. - type: object - recoverPanic: - description: RecoverPanic indicates if panics should be recovered. - type: boolean - type: object - gracefulShutDown: - description: |- - GracefulShutdownTimeout is the duration given to runnable to stop before the manager actually returns on stop. - To disable graceful shutdown, set to time.Duration(0) - To use graceful shutdown without timeout, set to a negative duration, e.G. time.Duration(-1) - The graceful shutdown is skipped for safety reasons in case the leader election lease is lost. - type: string - health: - description: Health contains the controller health configuration - properties: - healthProbeBindAddress: - description: |- - HealthProbeBindAddress is the TCP address that the controller should bind to - for serving health probes - It can be set to "0" or "" to disable serving the health probe. - type: string - livenessEndpointName: - description: LivenessEndpointName, defaults to "healthz" - type: string - readinessEndpointName: - description: ReadinessEndpointName, defaults to "readyz" - type: string - type: object kind: description: |- Kind is a string value representing the REST resource this object represents. @@ -101,75 +34,8 @@ spec: In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string - leaderElection: - description: |- - LeaderElection is the LeaderElection config to be used when configuring - the manager.Manager leader election - properties: - leaderElect: - description: |- - leaderElect enables a leader election client to gain leadership - before executing the main loop. Enable this when running replicated - components for high availability. - type: boolean - leaseDuration: - description: |- - leaseDuration is the duration that non-leader candidates will wait - after observing a leadership renewal until attempting to acquire - leadership of a led but unrenewed leader slot. This is effectively the - maximum duration that a leader can be stopped before it is replaced - by another candidate. This is only applicable if leader election is - enabled. - type: string - renewDeadline: - description: |- - renewDeadline is the interval between attempts by the acting master to - renew a leadership slot before it stops leading. This must be less - than or equal to the lease duration. This is only applicable if leader - election is enabled. - type: string - resourceLock: - description: |- - resourceLock indicates the resource object type that will be used to lock - during leader election cycles. - type: string - resourceName: - description: |- - resourceName indicates the name of resource object that will be used to lock - during leader election cycles. - type: string - resourceNamespace: - description: |- - resourceName indicates the namespace of resource object that will be used to lock - during leader election cycles. - type: string - retryPeriod: - description: |- - retryPeriod is the duration the clients should wait between attempting - acquisition and renewal of a leadership. This is only applicable if - leader election is enabled. - type: string - required: - - leaderElect - - leaseDuration - - renewDeadline - - resourceLock - - resourceName - - resourceNamespace - - retryPeriod - type: object metadata: type: object - metrics: - description: Metrics contains the controller metrics configuration - properties: - bindAddress: - description: |- - BindAddress is the TCP address that the controller should bind to - for serving prometheus metrics. - It can be set to "0" to disable the metrics serving. - type: string - type: object spec: description: MemcachedSpec defines the desired state of Memcached properties: @@ -261,36 +127,6 @@ spec: type: object type: array type: object - syncPeriod: - description: |- - SyncPeriod determines the minimum frequency at which watched resources are - reconciled. A lower period will correct entropy more quickly, but reduce - responsiveness to change if there are many watched resources. Change this - value only if you know what you are doing. Defaults to 10 hours if unset. - there will a 10 percent jitter between the SyncPeriod of all controllers - so that all controllers will not send list requests simultaneously. - type: string - webhook: - description: Webhook contains the controllers webhook configuration - properties: - certDir: - description: |- - CertDir is the directory that contains the server key and certificate. - if not set, webhook server would look up the server key and certificate in - {TempDir}/k8s-webhook-server/serving-certs. The server key and certificate - must be named tls.key and tls.crt, respectively. - type: string - host: - description: |- - Host is the hostname that the webhook server binds to. - It is used to set webhook.Server.Host. - type: string - port: - description: |- - Port is the port that the webhook server serves at. - It is used to set webhook.Server.Port. - type: integer - type: object type: object served: true storage: true diff --git a/docs/book/src/getting-started/testdata/project/config/default/kustomization.yaml b/docs/book/src/getting-started/testdata/project/config/default/kustomization.yaml index e0e588792c..d851be9cae 100644 --- a/docs/book/src/getting-started/testdata/project/config/default/kustomization.yaml +++ b/docs/book/src/getting-started/testdata/project/config/default/kustomization.yaml @@ -32,10 +32,6 @@ patches: # endpoint w/o any authn/z, please comment the following line. - path: manager_auth_proxy_patch.yaml -# Mount the controller config file for loading manager configurations -# through a ComponentConfig type -- path: manager_config_patch.yaml - # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in # crd/kustomization.yaml #- path: manager_webhook_patch.yaml diff --git a/docs/book/src/getting-started/testdata/project/config/default/manager_auth_proxy_patch.yaml b/docs/book/src/getting-started/testdata/project/config/default/manager_auth_proxy_patch.yaml index 74c49152af..4c3c27602f 100644 --- a/docs/book/src/getting-started/testdata/project/config/default/manager_auth_proxy_patch.yaml +++ b/docs/book/src/getting-started/testdata/project/config/default/manager_auth_proxy_patch.yaml @@ -32,3 +32,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/getting-started/testdata/project/config/default/manager_config_patch.yaml b/docs/book/src/getting-started/testdata/project/config/default/manager_config_patch.yaml index 6c400155cf..f6f5891692 100644 --- a/docs/book/src/getting-started/testdata/project/config/default/manager_config_patch.yaml +++ b/docs/book/src/getting-started/testdata/project/config/default/manager_config_patch.yaml @@ -8,13 +8,3 @@ spec: spec: containers: - name: manager - args: - - "--config=controller_manager_config.yaml" - volumeMounts: - - name: manager-config - mountPath: /controller_manager_config.yaml - subPath: controller_manager_config.yaml - volumes: - - name: manager-config - configMap: - name: manager-config diff --git a/docs/book/src/getting-started/testdata/project/config/manager/controller_manager_config.yaml b/docs/book/src/getting-started/testdata/project/config/manager/controller_manager_config.yaml deleted file mode 100644 index 1391a7ad49..0000000000 --- a/docs/book/src/getting-started/testdata/project/config/manager/controller_manager_config.yaml +++ /dev/null @@ -1,20 +0,0 @@ -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 diff --git a/docs/book/src/getting-started/testdata/project/config/manager/kustomization.yaml b/docs/book/src/getting-started/testdata/project/config/manager/kustomization.yaml index 2bcd3eeaa9..5c5f0b84cb 100644 --- a/docs/book/src/getting-started/testdata/project/config/manager/kustomization.yaml +++ b/docs/book/src/getting-started/testdata/project/config/manager/kustomization.yaml @@ -1,10 +1,2 @@ resources: - manager.yaml - -generatorOptions: - disableNameSuffixHash: true - -configMapGenerator: -- name: manager-config - files: - - controller_manager_config.yaml diff --git a/docs/book/src/getting-started/testdata/project/config/manager/manager.yaml b/docs/book/src/getting-started/testdata/project/config/manager/manager.yaml index 5117573d61..b4ba9334e8 100644 --- a/docs/book/src/getting-started/testdata/project/config/manager/manager.yaml +++ b/docs/book/src/getting-started/testdata/project/config/manager/manager.yaml @@ -68,6 +68,8 @@ spec: containers: - command: - /manager + args: + - --leader-elect image: controller:latest name: manager env: diff --git a/hack/docs/generate_samples.go b/hack/docs/generate_samples.go index 48b23c904f..39d1c6c04d 100644 --- a/hack/docs/generate_samples.go +++ b/hack/docs/generate_samples.go @@ -55,11 +55,8 @@ func main() { func updateTutorial(generator tutorial_generator) { generator.Prepare() - generator.GenerateSampleProject() - generator.UpdateTutorial() - generator.CodeGen() } @@ -76,7 +73,7 @@ func UpdateCronjobTutorial() { } func UpdateGettingStarted() { - samplePath := "docs/book/src/getting-started/testdata/project/" + samplePath := "docs/book/src/getting-started/testdata/project" sp := gettingstarted.NewSample(KubebuilderBinName, samplePath) updateTutorial(&sp) } diff --git a/hack/docs/internal/cronjob-tutorial/generate_cronjob.go b/hack/docs/internal/cronjob-tutorial/generate_cronjob.go index 0039c0454c..190555ec84 100644 --- a/hack/docs/internal/cronjob-tutorial/generate_cronjob.go +++ b/hack/docs/internal/cronjob-tutorial/generate_cronjob.go @@ -34,9 +34,7 @@ type Sample struct { func NewSample(binaryPath, samplePath string) Sample { log.Infof("Generating the sample context of Cronjob...") - ctx := newSampleContext(binaryPath, samplePath, "GO111MODULE=on") - return Sample{&ctx} } diff --git a/hack/docs/internal/getting-started/generate_getting_started.go b/hack/docs/internal/getting-started/generate_getting_started.go index cccbb246fe..b78d9d36ca 100644 --- a/hack/docs/internal/getting-started/generate_getting_started.go +++ b/hack/docs/internal/getting-started/generate_getting_started.go @@ -19,11 +19,8 @@ package gettingstarted import ( "os" "os/exec" - "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" ) @@ -33,12 +30,14 @@ type Sample struct { func NewSample(binaryPath, samplePath string) Sample { log.Infof("Generating the sample context of getting-started...") - ctx := newSampleContext(binaryPath, samplePath, "GO111MODULE=on") - return Sample{&ctx} } +func (sp *Sample) UpdateTutorial() { + log.Println("TODO: update tutorial") +} + func newSampleContext(binaryPath string, samplePath string, env ...string) utils.TestContext { cmdContext := &utils.CmdContext{ Env: env, @@ -55,13 +54,13 @@ func newSampleContext(binaryPath string, samplePath string, env ...string) utils // Prepare the Context for the sample project func (sp *Sample) Prepare() { - log.Infof("destroying directory for getting-started sample project") + log.Infof("Destroying directory for getting-started sample project") sp.ctx.Destroy() - log.Infof("refreshing tools and creating directory...") + log.Infof("Refreshing tools and creating directory...") err := sp.ctx.Prepare() - CheckError("creating directory for sample project", err) + CheckError("Creating directory for sample project", err) } func (sp *Sample) GenerateSampleProject() { @@ -71,8 +70,6 @@ func (sp *Sample) GenerateSampleProject() { "--repo", "example.com/memcached", "--license", "apache2", "--owner", "The Kubernetes authors", - "--plugins=go/v4", - "--component-config", ) CheckError("Initializing the getting started project", err) @@ -91,70 +88,7 @@ func (sp *Sample) GenerateSampleProject() { 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. fix memcached_types.go - err = pluginutil.InsertCode( - filepath.Join(sp.ctx.Dir, "api/v1alpha1/memcached_types.go"), - `metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"`, - ` - cfg "sigs.k8s.io/controller-runtime/pkg/config/v1alpha1"`) - CheckError("fixing memcached_types", err) - - err = pluginutil.InsertCode( - filepath.Join(sp.ctx.Dir, "api/v1alpha1/memcached_types.go"), - `Status MemcachedStatus `+"`"+`json:"status,omitempty"`+"`", - ` - // ControllerManagerConfigurationSpec returns the configurations for controllers - cfg.ControllerManagerConfigurationSpec `+"`"+`json:",inline"`+"`"+` - - ClusterName string `+"`"+`json:"clusterName,omitempty"`+"`", - ) - - CheckError("fixing memcached_types", err) - - // 3. fix main - err = pluginutil.InsertCode( - filepath.Join(sp.ctx.Dir, "cmd/main.go"), - `var err error`, - ` - ctrlConfig := cachev1alpha1.Memcached{}`) - CheckError("fixing main.go", err) - - err = pluginutil.InsertCode( - filepath.Join(sp.ctx.Dir, "cmd/main.go"), - `AtPath(configFile)`, - `.OfKind(&ctrlConfig)`) - CheckError("fixing main.go", err) -} - func (sp *Sample) CodeGen() { - cmd := exec.Command("make", "manifests") _, err := sp.ctx.Run(cmd) CheckError("Failed to run make manifests for getting started tutorial", err)