sigs.k8s.io/kubebuilder/v3@v3.14.0/pkg/plugins/golang/v2/init.go (about)

     1  /*
     2  Copyright 2020 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  //go:deprecated This package has been deprecated
    18  package v2
    19  
    20  import (
    21  	"fmt"
    22  	"os"
    23  	"path/filepath"
    24  	"strings"
    25  
    26  	log "github.com/sirupsen/logrus"
    27  	"github.com/spf13/pflag"
    28  
    29  	"sigs.k8s.io/kubebuilder/v3/pkg/config"
    30  	cfgv2 "sigs.k8s.io/kubebuilder/v3/pkg/config/v2"
    31  	"sigs.k8s.io/kubebuilder/v3/pkg/internal/validation"
    32  	"sigs.k8s.io/kubebuilder/v3/pkg/machinery"
    33  	"sigs.k8s.io/kubebuilder/v3/pkg/plugin"
    34  	"sigs.k8s.io/kubebuilder/v3/pkg/plugin/util"
    35  	"sigs.k8s.io/kubebuilder/v3/pkg/plugins/golang"
    36  	"sigs.k8s.io/kubebuilder/v3/pkg/plugins/golang/v2/scaffolds"
    37  )
    38  
    39  // Variables and function to check Go version requirements.
    40  var (
    41  	goVerMin = golang.MustParse("go1.13")
    42  	goVerMax = golang.MustParse("go2.0alpha1")
    43  )
    44  
    45  var _ plugin.InitSubcommand = &initSubcommand{}
    46  
    47  type initSubcommand struct {
    48  	config config.Config
    49  
    50  	// For help text.
    51  	commandName string
    52  
    53  	// boilerplate options
    54  	license string
    55  	owner   string
    56  
    57  	// config options
    58  	domain string
    59  	repo   string
    60  	name   string
    61  
    62  	// flags
    63  	fetchDeps          bool
    64  	skipGoVersionCheck bool
    65  }
    66  
    67  func (p *initSubcommand) UpdateMetadata(cliMeta plugin.CLIMetadata, subcmdMeta *plugin.SubcommandMetadata) {
    68  	p.commandName = cliMeta.CommandName
    69  
    70  	subcmdMeta.Description = `Initialize a new project including the following files:
    71    - a "go.mod" with project dependencies
    72    - a "PROJECT" file that stores project configuration
    73    - a "Makefile" with several useful make targets for the project
    74    - several YAML files for project deployment under the "config" directory
    75    - a "main.go" file that creates the manager that will run the project controllers
    76  `
    77  	subcmdMeta.Examples = fmt.Sprintf(`  # Initialize a new project with your domain and name in copyright
    78    %[1]s init --plugins go/v2 --domain example.org --owner "Your name"
    79  
    80    # Initialize a new project defining a specific project version
    81    %[1]s init --plugins go/v2 --project-version 2
    82  `, cliMeta.CommandName)
    83  }
    84  
    85  func (p *initSubcommand) BindFlags(fs *pflag.FlagSet) {
    86  	fs.BoolVar(&p.skipGoVersionCheck, "skip-go-version-check",
    87  		false, "if specified, skip checking the Go version")
    88  
    89  	// dependency args
    90  	fs.BoolVar(&p.fetchDeps, "fetch-deps", true, "ensure dependencies are downloaded")
    91  
    92  	// boilerplate args
    93  	fs.StringVar(&p.license, "license", "apache2",
    94  		"license to use to boilerplate, may be one of 'apache2', 'none'")
    95  	fs.StringVar(&p.owner, "owner", "", "owner to add to the copyright")
    96  
    97  	// project args
    98  	fs.StringVar(&p.domain, "domain", "my.domain", "domain for groups")
    99  	fs.StringVar(&p.repo, "repo", "", "name to use for go module (e.g., github.com/user/repo), "+
   100  		"defaults to the go package of the current working directory.")
   101  	fs.StringVar(&p.name, "project-name", "", "name of this project")
   102  }
   103  
   104  func (p *initSubcommand) InjectConfig(c config.Config) error {
   105  	p.config = c
   106  
   107  	if err := p.config.SetDomain(p.domain); err != nil {
   108  		return err
   109  	}
   110  
   111  	// Try to guess repository if flag is not set.
   112  	if p.repo == "" {
   113  		repoPath, err := golang.FindCurrentRepo()
   114  		if err != nil {
   115  			return fmt.Errorf("error finding current repository: %v", err)
   116  		}
   117  		p.repo = repoPath
   118  	}
   119  	if err := p.config.SetRepository(p.repo); err != nil {
   120  		return err
   121  	}
   122  
   123  	if p.config.GetVersion().Compare(cfgv2.Version) > 0 {
   124  		// Assign a default project name
   125  		if p.name == "" {
   126  			dir, err := os.Getwd()
   127  			if err != nil {
   128  				return fmt.Errorf("error getting current directory: %v", err)
   129  			}
   130  			p.name = strings.ToLower(filepath.Base(dir))
   131  		}
   132  		// Check if the project name is a valid k8s namespace (DNS 1123 label).
   133  		if err := validation.IsDNS1123Label(p.name); err != nil {
   134  			return fmt.Errorf("project name (%s) is invalid: %v", p.name, err)
   135  		}
   136  		if err := p.config.SetProjectName(p.name); err != nil {
   137  			return err
   138  		}
   139  	}
   140  
   141  	return nil
   142  }
   143  
   144  func (p *initSubcommand) PreScaffold(machinery.Filesystem) error {
   145  	// Ensure Go version is in the allowed range if check not turned off.
   146  	if !p.skipGoVersionCheck {
   147  		if err := golang.ValidateGoVersion(goVerMin, goVerMax); err != nil {
   148  			return err
   149  		}
   150  	}
   151  
   152  	return nil
   153  }
   154  
   155  func (p *initSubcommand) Scaffold(fs machinery.Filesystem) error {
   156  	scaffolder := scaffolds.NewInitScaffolder(p.config, p.license, p.owner)
   157  	scaffolder.InjectFS(fs)
   158  	err := scaffolder.Scaffold()
   159  	if err != nil {
   160  		return err
   161  	}
   162  
   163  	if !p.fetchDeps {
   164  		log.Println("Skipping fetching dependencies.")
   165  		return nil
   166  	}
   167  
   168  	// Ensure that we are pinning controller-runtime version
   169  	// xref: https://github.com/kubernetes-sigs/kubebuilder/issues/997
   170  	err = util.RunCmd("Get controller runtime", "go", "get",
   171  		"sigs.k8s.io/controller-runtime@"+scaffolds.ControllerRuntimeVersion)
   172  	if err != nil {
   173  		return err
   174  	}
   175  
   176  	return nil
   177  }
   178  
   179  func (p *initSubcommand) PostScaffold() error {
   180  	err := util.RunCmd("Update dependencies", "go", "mod", "tidy")
   181  	if err != nil {
   182  		return err
   183  	}
   184  
   185  	fmt.Printf("Next: define a resource with:\n$ %s create api\n", p.commandName)
   186  	return nil
   187  }