2022-09-05 03:06:08 -04:00
/ *
Copyright ( c ) Edgeless Systems GmbH
SPDX - License - Identifier : AGPL - 3.0 - only
* /
2022-05-12 09:14:52 -04:00
package cmd
import (
2022-06-09 10:10:42 -04:00
"fmt"
2023-02-21 08:05:41 -05:00
"strings"
2022-06-09 10:10:42 -04:00
2022-09-21 07:47:57 -04:00
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
2023-02-21 08:05:41 -05:00
"github.com/edgelesssys/constellation/v2/internal/compatibility"
2022-09-21 07:47:57 -04:00
"github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/file"
2023-02-21 08:05:41 -05:00
"github.com/edgelesssys/constellation/v2/internal/versions"
2023-01-02 07:33:56 -05:00
"github.com/siderolabs/talos/pkg/machinery/config/encoder"
2022-05-12 09:14:52 -04:00
"github.com/spf13/afero"
"github.com/spf13/cobra"
2023-02-21 08:05:41 -05:00
"golang.org/x/mod/semver"
2022-05-12 09:14:52 -04:00
)
func newConfigGenerateCmd ( ) * cobra . Command {
cmd := & cobra . Command {
2023-02-27 12:19:52 -05:00
Use : "generate {aws|azure|gcp|openstack|qemu}" ,
2022-05-12 09:14:52 -04:00
Short : "Generate a default configuration file" ,
Long : "Generate a default configuration file for your selected cloud provider." ,
2022-05-18 05:39:14 -04:00
Args : cobra . MatchAll (
cobra . ExactArgs ( 1 ) ,
isCloudProvider ( 0 ) ,
) ,
ValidArgsFunction : generateCompletion ,
RunE : runConfigGenerate ,
2022-05-12 09:14:52 -04:00
}
2022-05-24 05:56:40 -04:00
cmd . Flags ( ) . StringP ( "file" , "f" , constants . ConfigFilename , "path to output file, or '-' for stdout" )
2023-02-21 08:05:41 -05:00
cmd . Flags ( ) . StringP ( "kubernetes" , "k" , semver . MajorMinor ( config . Default ( ) . KubernetesVersion ) , "Kubernetes version to use in format MAJOR.MINOR" )
2022-05-12 09:14:52 -04:00
return cmd
}
type generateFlags struct {
2023-02-21 08:05:41 -05:00
file string
k8sVersion string
2022-05-12 09:14:52 -04:00
}
2023-01-04 04:46:29 -05:00
type configGenerateCmd struct {
log debugLog
}
2022-05-12 09:14:52 -04:00
func runConfigGenerate ( cmd * cobra . Command , args [ ] string ) error {
2023-01-04 04:46:29 -05:00
log , err := newCLILogger ( cmd )
if err != nil {
return fmt . Errorf ( "creating logger: %w" , err )
}
defer log . Sync ( )
2022-05-12 09:14:52 -04:00
fileHandler := file . NewHandler ( afero . NewOsFs ( ) )
2022-05-18 05:39:14 -04:00
provider := cloudprovider . FromString ( args [ 0 ] )
2023-01-04 04:46:29 -05:00
cg := & configGenerateCmd { log : log }
return cg . configGenerate ( cmd , fileHandler , provider )
2022-05-12 09:14:52 -04:00
}
2023-01-04 04:46:29 -05:00
func ( cg * configGenerateCmd ) configGenerate ( cmd * cobra . Command , fileHandler file . Handler , provider cloudprovider . Provider ) error {
2022-05-12 09:14:52 -04:00
flags , err := parseGenerateFlags ( cmd )
if err != nil {
return err
}
2023-01-12 05:35:26 -05:00
2023-01-04 04:46:29 -05:00
cg . log . Debugf ( "Parsed flags as %v" , flags )
cg . log . Debugf ( "Using cloud provider %s" , provider . String ( ) )
2023-01-12 05:35:26 -05:00
conf := createConfig ( provider )
2023-03-03 03:04:54 -05:00
conf . KubernetesVersion = flags . k8sVersion
2022-05-12 09:14:52 -04:00
if flags . file == "-" {
2022-05-18 05:39:14 -04:00
content , err := encoder . NewEncoder ( conf ) . Encode ( )
2022-05-16 12:54:25 -04:00
if err != nil {
2022-06-09 10:10:42 -04:00
return fmt . Errorf ( "encoding config content: %w" , err )
2022-05-16 12:54:25 -04:00
}
2023-01-04 04:46:29 -05:00
cg . log . Debugf ( "Writing YAML data to stdout" )
2022-05-16 12:54:25 -04:00
_ , err = cmd . OutOrStdout ( ) . Write ( content )
return err
2022-05-12 09:14:52 -04:00
}
2023-01-04 04:46:29 -05:00
cg . log . Debugf ( "Writing YAML data to configuration file" )
2022-08-08 05:04:17 -04:00
if err := fileHandler . WriteYAML ( flags . file , conf , file . OptMkdirAll ) ; err != nil {
return err
}
2023-01-12 05:35:26 -05:00
2022-08-08 05:04:17 -04:00
cmd . Println ( "Config file written to" , flags . file )
2022-09-11 10:24:15 -04:00
cmd . Println ( "Please fill in your CSP-specific configuration before proceeding." )
2022-10-31 11:39:56 -04:00
cmd . Println ( "For more information refer to the documentation:" )
2022-09-10 07:44:17 -04:00
cmd . Println ( "\thttps://docs.edgeless.systems/constellation/getting-started/first-steps" )
2022-09-02 11:11:06 -04:00
2022-08-08 05:04:17 -04:00
return nil
2022-05-12 09:14:52 -04:00
}
2023-01-12 05:35:26 -05:00
// createConfig creates a config file for the given provider.
func createConfig ( provider cloudprovider . Provider ) * config . Config {
conf := config . Default ( )
conf . RemoveProviderExcept ( provider )
// set a lower default for QEMU's state disk
if provider == cloudprovider . QEMU {
conf . StateDiskSizeGB = 10
}
return conf
}
2023-02-21 08:05:41 -05:00
// supportedVersions prints the supported version without v prefix and without patch version.
// Should only be used when accepting Kubernetes versions from --kubernetes.
func supportedVersions ( ) string {
builder := strings . Builder { }
for i , version := range versions . SupportedK8sVersions ( ) {
if i > 0 {
builder . WriteString ( " " )
}
builder . WriteString ( strings . TrimPrefix ( semver . MajorMinor ( version ) , "v" ) )
}
return builder . String ( )
}
2022-05-12 09:14:52 -04:00
func parseGenerateFlags ( cmd * cobra . Command ) ( generateFlags , error ) {
file , err := cmd . Flags ( ) . GetString ( "file" )
if err != nil {
2023-02-21 08:05:41 -05:00
return generateFlags { } , fmt . Errorf ( "parsing file flag: %w" , err )
2022-05-12 09:14:52 -04:00
}
2023-02-21 08:05:41 -05:00
k8sVersion , err := cmd . Flags ( ) . GetString ( "kubernetes" )
if err != nil {
return generateFlags { } , fmt . Errorf ( "parsing kuberentes flag: %w" , err )
}
2023-03-03 03:04:54 -05:00
resolvedVersion , err := resolveK8sVersion ( k8sVersion )
if err != nil {
return generateFlags { } , fmt . Errorf ( "resolving kuberentes version from flag: %w" , err )
2023-02-21 08:05:41 -05:00
}
2022-05-12 09:14:52 -04:00
return generateFlags {
2023-02-21 08:05:41 -05:00
file : file ,
2023-03-03 03:04:54 -05:00
k8sVersion : resolvedVersion ,
2022-05-12 09:14:52 -04:00
} , nil
}
2022-05-18 05:39:14 -04:00
// createCompletion handles the completion of the create command. It is frequently called
// while the user types arguments of the command to suggest completion.
2023-03-20 06:03:36 -04:00
func generateCompletion ( _ * cobra . Command , args [ ] string , _ string ) ( [ ] string , cobra . ShellCompDirective ) {
2022-05-18 05:39:14 -04:00
switch len ( args ) {
case 0 :
2022-09-26 09:52:31 -04:00
return [ ] string { "aws" , "gcp" , "azure" , "qemu" } , cobra . ShellCompDirectiveNoFileComp
2022-05-18 05:39:14 -04:00
default :
return [ ] string { } , cobra . ShellCompDirectiveError
}
}
2023-03-03 03:04:54 -05:00
// resolveK8sVersion takes the user input from --kubernetes and transforms a MAJOR.MINOR definition into a supported
// MAJOR.MINOR.PATCH release.
func resolveK8sVersion ( k8sVersion string ) ( string , error ) {
prefixedVersion := compatibility . EnsurePrefixV ( k8sVersion )
if ! semver . IsValid ( prefixedVersion ) {
return "" , fmt . Errorf ( "kubernetes flag does not specify a valid semantic version: %s" , k8sVersion )
}
extendedVersion := config . K8sVersionFromMajorMinor ( prefixedVersion )
if extendedVersion == "" {
return "" , fmt . Errorf ( "--kubernetes (%s) does not specify a valid Kubernetes version. Supported versions: %s" , strings . TrimPrefix ( k8sVersion , "v" ) , supportedVersions ( ) )
}
return extendedVersion , nil
}