-
Notifications
You must be signed in to change notification settings - Fork 376
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
410 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
/* | ||
Copyright 2023 The KCP 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" | ||
"io" | ||
|
||
"github.com/spf13/cobra" | ||
"github.com/spf13/pflag" | ||
|
||
"k8s.io/apimachinery/pkg/util/sets" | ||
cliflag "k8s.io/component-base/cli/flag" | ||
) | ||
|
||
const ( | ||
usageFmt = "Usage:\n %s\n" | ||
) | ||
|
||
// setPartialUsageAndHelpFunc set both usage and help function. | ||
// Print the flag sets we need instead of all of them. | ||
func setPartialUsageAndHelpFunc(cmd *cobra.Command, fss cliflag.NamedFlagSets, cols int, flags []string) { | ||
cmd.SetUsageFunc(func(cmd *cobra.Command) error { | ||
fmt.Fprintf(cmd.OutOrStderr(), usageFmt, cmd.UseLine()) | ||
printMostImportantFlags(cmd.OutOrStderr(), fss, cols, flags) | ||
fmt.Fprintf(cmd.OutOrStderr(), "\nUse \"%s\" for a list of all flags available.\n", cmd.CommandPath()) | ||
return nil | ||
}) | ||
cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) { | ||
fmt.Fprintf(cmd.OutOrStdout(), "%s\n\n"+usageFmt, cmd.Long, cmd.UseLine()) | ||
printMostImportantFlags(cmd.OutOrStdout(), fss, cols, flags) | ||
fmt.Fprintf(cmd.OutOrStderr(), "\nUse \"%s options\" for a list of all flags available.\n", cmd.CommandPath()) | ||
}) | ||
} | ||
|
||
func printMostImportantFlags(w io.Writer, fss cliflag.NamedFlagSets, cols int, visibleFlags []string) { | ||
visibleFlagsSet := sets.NewString(visibleFlags...) | ||
filteredFFS := cliflag.NamedFlagSets{} | ||
filteredFS := filteredFFS.FlagSet("Most important") | ||
|
||
for _, name := range fss.Order { | ||
fs := fss.FlagSets[name] | ||
if !fs.HasFlags() { | ||
continue | ||
} | ||
|
||
fs.VisitAll(func(f *pflag.Flag) { | ||
if visibleFlagsSet.Has(f.Name) { | ||
filteredFS.AddFlag(f) | ||
} | ||
}) | ||
} | ||
|
||
cliflag.PrintSections(w, filteredFFS, cols) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
/* | ||
Copyright 2023 The KCP 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" | ||
"math/rand" | ||
"os" | ||
"strings" | ||
"time" | ||
|
||
"github.com/spf13/cobra" | ||
|
||
"k8s.io/apimachinery/pkg/util/errors" | ||
genericapiserver "k8s.io/apiserver/pkg/server" | ||
"k8s.io/client-go/rest" | ||
"k8s.io/component-base/cli" | ||
cliflag "k8s.io/component-base/cli/flag" | ||
"k8s.io/component-base/cli/globalflag" | ||
"k8s.io/component-base/config" | ||
"k8s.io/component-base/logs" | ||
_ "k8s.io/component-base/logs/json/register" | ||
"k8s.io/component-base/term" | ||
"k8s.io/component-base/version" | ||
"k8s.io/klog/v2" | ||
|
||
"github.com/kcp-dev/kcp/cmd/kcp-core/options" | ||
"github.com/kcp-dev/kcp/pkg/cmd/help" | ||
"github.com/kcp-dev/kcp/pkg/embeddedetcd" | ||
kcpfeatures "github.com/kcp-dev/kcp/pkg/features" | ||
"github.com/kcp-dev/kcp/pkg/server" | ||
) | ||
|
||
func main() { | ||
rand.Seed(time.Now().UTC().UnixNano()) | ||
|
||
cmd := &cobra.Command{ | ||
Use: "kcp", | ||
Short: "Kube for Control Plane (KCP)", | ||
Long: help.Doc(` | ||
KCP is the easiest way to manage Kubernetes applications against one or | ||
more clusters, by giving you a personal control plane that schedules your | ||
workloads onto one or many clusters, and making it simple to pick up and | ||
move. It supports advanced use cases such as spreading your apps across | ||
clusters for resiliency, scheduling batch workloads onto clusters with | ||
free capacity, and enabling collaboration for individual teams without | ||
having access to the underlying clusters. | ||
To get started, launch a new cluster with 'kcp start', which will | ||
initialize your personal control plane and write an admin kubeconfig file | ||
to disk. | ||
`), | ||
SilenceUsage: true, | ||
SilenceErrors: true, | ||
} | ||
|
||
cols, _, _ := term.TerminalSize(cmd.OutOrStdout()) | ||
|
||
// manually extract root directory from flags first as it influence all other flags | ||
rootDir := ".kcp" | ||
for i, f := range os.Args { | ||
if f == "--root-directory" { | ||
if i < len(os.Args)-1 { | ||
rootDir = os.Args[i+1] | ||
} // else let normal flag processing fail | ||
} else if strings.HasPrefix(f, "--root-directory=") { | ||
rootDir = strings.TrimPrefix(f, "--root-directory=") | ||
} | ||
} | ||
|
||
serverOptions := options.NewOptions(rootDir) | ||
serverOptions.Server.GenericControlPlane.Logs.Config.Verbosity = config.VerbosityLevel(2) | ||
|
||
startCmd := &cobra.Command{ | ||
Use: "start", | ||
Short: "Start the control plane process", | ||
Long: help.Doc(` | ||
Start the control plane process | ||
The server process listens on port 6443 and will act like a Kubernetes | ||
API server. It will initialize any necessary data to the provided start | ||
location or as a '.kcp' directory in the current directory. An admin | ||
kubeconfig file will be generated at initialization time that may be | ||
used to access the control plane. | ||
`), | ||
PersistentPreRunE: func(*cobra.Command, []string) error { | ||
// silence client-go warnings. | ||
// apiserver loopback clients should not log self-issued warnings. | ||
rest.SetDefaultWarningHandler(rest.NoWarnings{}) | ||
return nil | ||
}, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
// run as early as possible to avoid races later when some components (e.g. grpc) start early using klog | ||
if err := serverOptions.Server.GenericControlPlane.Logs.ValidateAndApply(kcpfeatures.DefaultFeatureGate); err != nil { | ||
return err | ||
} | ||
|
||
completed, err := serverOptions.Complete() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if errs := completed.Validate(); len(errs) > 0 { | ||
return errors.NewAggregate(errs) | ||
} | ||
|
||
logger := klog.FromContext(cmd.Context()) | ||
logger.Info("running with selected batteries", "batteries", strings.Join(completed.Server.Extra.BatteriesIncluded, ",")) | ||
|
||
config, err := server.NewConfig(completed.Server) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
completedConfig, err := config.Complete() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
ctx := genericapiserver.SetupSignalContext() | ||
|
||
// the etcd server must be up before NewServer because storage decorators access it right away | ||
if completedConfig.EmbeddedEtcd.Config != nil { | ||
if err := embeddedetcd.NewServer(completedConfig.EmbeddedEtcd).Run(ctx); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
s, err := server.NewServer(completedConfig) | ||
if err != nil { | ||
return err | ||
} | ||
return s.Run(ctx) | ||
}, | ||
} | ||
|
||
// add start named flag sets to start flags | ||
fss := cliflag.NamedFlagSets{} | ||
serverOptions.AddFlags(&fss) | ||
globalflag.AddGlobalFlags(fss.FlagSet("global"), cmd.Name(), logs.SkipLoggingConfigurationFlags()) | ||
startFlags := startCmd.Flags() | ||
for _, f := range fss.FlagSets { | ||
startFlags.AddFlagSet(f) | ||
} | ||
|
||
startOptionsCmd := &cobra.Command{ | ||
Use: "options", | ||
Short: "Show all start command options", | ||
Long: help.Doc(` | ||
Show all start command options | ||
"kcp start"" has a large number of options. This command shows all of them. | ||
`), | ||
PersistentPreRunE: func(*cobra.Command, []string) error { | ||
// silence client-go warnings. | ||
// apiserver loopback clients should not log self-issued warnings. | ||
rest.SetDefaultWarningHandler(rest.NoWarnings{}) | ||
return nil | ||
}, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
fmt.Fprintf(cmd.OutOrStderr(), usageFmt, startCmd.UseLine()) | ||
cliflag.PrintSections(cmd.OutOrStderr(), fss, cols) | ||
return nil | ||
}, | ||
} | ||
startCmd.AddCommand(startOptionsCmd) | ||
cmd.AddCommand(startCmd) | ||
|
||
setPartialUsageAndHelpFunc(startCmd, fss, cols, []string{ | ||
"etcd-servers", | ||
"batteries-included", | ||
"run-virtual-workspaces", | ||
}) | ||
|
||
help.FitTerminal(cmd.OutOrStdout()) | ||
|
||
if v := version.Get().String(); len(v) == 0 { | ||
cmd.Version = "<unknown>" | ||
} else { | ||
cmd.Version = v | ||
} | ||
|
||
os.Exit(cli.Run(cmd)) | ||
} |
Oops, something went wrong.