Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,10 @@ test-junit: $(SETUP_ENVTEST) $(GOTESTSUM) ## Run tests with verbose setting and
operator: ## Build operator binary
go build -trimpath -ldflags "$(LDFLAGS)" -o $(BIN_DIR)/operator cmd/main.go

.PHONY: plugin
plugin: ## Build plugin binary
go build -trimpath -ldflags "$(LDFLAGS)" -o $(BIN_DIR)/clusterctl-operator cmd/plugin/main.go

## --------------------------------------
## Lint / Verify
## --------------------------------------
Expand Down
146 changes: 146 additions & 0 deletions cmd/plugin/cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
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 cmd

import (
"flag"
"fmt"
"os"
"strconv"
"strings"

"github.com/MakeNowJust/heredoc"
"github.com/pkg/errors"
"github.com/spf13/cobra"

configclient "sigs.k8s.io/cluster-api/cmd/clusterctl/client/config"
logf "sigs.k8s.io/cluster-api/cmd/clusterctl/log"
)

type stackTracer interface {
StackTrace() errors.StackTrace
}

var (
cfgFile string
verbosity *int
)

// RootCmd is operator root CLI command.
var RootCmd = &cobra.Command{
Use: "operator",
Short: "clusterctl plugin for leveraging Cluster API Operator.",
Long: LongDesc(`
Use this clusterctl plugin to bootstrap a management cluster for Cluster API with the Cluster API Operator.`),
}

// Execute executes the root command.
func Execute() {
if err := RootCmd.Execute(); err != nil {
if verbosity != nil && *verbosity >= 5 {
if err, ok := err.(stackTracer); ok { //nolint:errorlint
for _, f := range err.StackTrace() {
fmt.Fprintf(os.Stderr, "%+s:%d\n", f, f)
}
}
}

os.Exit(1)
}
}

func init() {
flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError)

verbosity = flag.CommandLine.Int("v", 0, "Set the log level verbosity. This overrides the CLUSTERCTL_LOG_LEVEL environment variable.")

RootCmd.PersistentFlags().AddGoFlagSet(flag.CommandLine)
RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "",
"Path to clusterctl configuration (default is `$XDG_CONFIG_HOME/cluster-api/clusterctl.yaml`) or to a remote location (i.e. https://example.com/clusterctl.yaml)")

cobra.OnInitialize(initConfig)
}

func initConfig() {
// check if the CLUSTERCTL_LOG_LEVEL was set via env var or in the config file
if *verbosity == 0 { //nolint:nestif
configClient, err := configclient.New(cfgFile)
if err == nil {
v, err := configClient.Variables().Get("CLUSTERCTL_LOG_LEVEL")
if err == nil && v != "" {
verbosityFromEnv, err := strconv.Atoi(v)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to convert CLUSTERCTL_LOG_LEVEL string to an int. err=%s\n", err.Error())
os.Exit(1)
}

verbosity = &verbosityFromEnv
}
}
}

logf.SetLogger(logf.NewLogger(logf.WithThreshold(verbosity)))
}

const indentation = ` `

// LongDesc normalizes a command's long description to follow the conventions.
func LongDesc(s string) string {
if s == "" {
return s
}

return normalizer{s}.heredoc().trim().string
}

// Examples normalizes a command's examples to follow the conventions.
func Examples(s string) string {
if s == "" {
return s
}

return normalizer{s}.trim().indent().string
}

type normalizer struct {
string
}

func (s normalizer) heredoc() normalizer {
s.string = heredoc.Doc(s.string)
return s
}

func (s normalizer) trim() normalizer {
s.string = strings.TrimSpace(s.string)
return s
}

func (s normalizer) indent() normalizer {
splitLines := strings.Split(s.string, "\n")
indentedLines := make([]string, 0, len(splitLines))

for _, line := range splitLines {
trimmed := strings.TrimSpace(line)
indented := indentation + trimmed
indentedLines = append(indentedLines, indented)
}

s.string = strings.Join(indentedLines, "\n")

return s
}
34 changes: 34 additions & 0 deletions cmd/plugin/cmd/upgrade.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
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 cmd

import (
"github.com/spf13/cobra"
)

var upgradeCmd = &cobra.Command{
Use: "upgrade",
Short: "Upgrade core and provider components in a management cluster using the Cluster API Operator.",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
return cmd.Help()
},
}

func init() {
RootCmd.AddCommand(upgradeCmd)
}
27 changes: 27 additions & 0 deletions cmd/plugin/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
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 (
_ "k8s.io/client-go/plugin/pkg/client/auth"

"sigs.k8s.io/cluster-api-operator/cmd/plugin/cmd"
)

func main() {
cmd.Execute()
}
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ go 1.20
replace sigs.k8s.io/cluster-api => sigs.k8s.io/cluster-api v1.5.0-rc.0

require (
github.com/MakeNowJust/heredoc v1.0.0
github.com/google/go-cmp v0.5.9
github.com/google/go-github/v52 v52.0.0
github.com/onsi/ginkgo/v2 v2.11.0
github.com/onsi/gomega v1.27.10
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.7.0
github.com/spf13/pflag v1.0.5
golang.org/x/oauth2 v0.10.0
k8s.io/api v0.27.2
Expand All @@ -26,7 +29,6 @@ require (

require (
github.com/BurntSushi/toml v1.0.0 // indirect
github.com/MakeNowJust/heredoc v1.0.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.0 // indirect
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
Expand Down Expand Up @@ -90,7 +92,6 @@ require (
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.16.0 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/common v0.42.0 // indirect
Expand All @@ -99,7 +100,6 @@ require (
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/spf13/afero v1.9.5 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/spf13/cobra v1.7.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/viper v1.16.0 // indirect
github.com/stoewer/go-strcase v1.2.0 // indirect
Expand Down