github.com/cloudfoundry-incubator/stembuild@v0.0.0-20211223202937-5b61d62226c6/commandparser/package_stemcell.go (about)

     1  package commandparser
     2  
     3  import (
     4  	"context"
     5  	"flag"
     6  	"fmt"
     7  	"os"
     8  	"path/filepath"
     9  
    10  	"github.com/cloudfoundry-incubator/stembuild/colorlogger"
    11  
    12  	"github.com/cloudfoundry-incubator/stembuild/filesystem"
    13  
    14  	"github.com/cloudfoundry-incubator/stembuild/package_stemcell/config"
    15  	"github.com/google/subcommands"
    16  )
    17  
    18  //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . OSAndVersionGetter
    19  type OSAndVersionGetter interface {
    20  	GetVersion() string
    21  	GetVersionWithPatchNumber(string) string
    22  	GetOs() string
    23  }
    24  
    25  //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . PackagerFactory
    26  type PackagerFactory interface {
    27  	Packager(sourceConfig config.SourceConfig, outputConfig config.OutputConfig, logLevel int, color bool) (Packager, error)
    28  }
    29  
    30  //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Packager
    31  type Packager interface {
    32  	Package() error
    33  	ValidateFreeSpaceForPackage(fs filesystem.FileSystem) error
    34  	ValidateSourceParameters() error
    35  }
    36  
    37  //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . PackagerMessenger
    38  type PackagerMessenger interface {
    39  	InvalidOutputConfig(error)
    40  	CannotCreatePackager(error)
    41  	DoesNotHaveEnoughSpace(error)
    42  	SourceParametersAreInvalid(error)
    43  	PackageFailed(error)
    44  }
    45  
    46  type PackageCmd struct {
    47  	GlobalFlags        *GlobalFlags
    48  	sourceConfig       config.SourceConfig
    49  	outputConfig       config.OutputConfig
    50  	osAndVersionGetter OSAndVersionGetter
    51  	packagerFactory    PackagerFactory
    52  	packagerMessenger  PackagerMessenger
    53  }
    54  
    55  func NewPackageCommand(o OSAndVersionGetter, p PackagerFactory, m PackagerMessenger) *PackageCmd {
    56  	return &PackageCmd{
    57  		osAndVersionGetter: o,
    58  		packagerFactory:    p,
    59  		packagerMessenger:  m,
    60  	}
    61  }
    62  
    63  var patchVersion string
    64  
    65  func (*PackageCmd) Name() string { return "package" }
    66  func (*PackageCmd) Synopsis() string {
    67  	return "Create a BOSH Stemcell from a VMDK file or a provisioned vCenter VM"
    68  }
    69  func (*PackageCmd) Usage() string {
    70  	return fmt.Sprintf(`
    71  Create a BOSH Stemcell from a VMDK file or a provisioned vCenter VM
    72  
    73  VM on vCenter:
    74  
    75    %[1]s package -vcenter-url <vCenter URL> -vcenter-username <vCenter username> -vcenter-password <vCenter password> -vm-inventory-path <vCenter VM inventory path>
    76  
    77    Requirements:
    78      - VM provisioned using the stembuild construct command
    79      - Access to vCenter environment
    80      - The [vcenter-url], [vcenter-username], [vcenter-password], and [vm-inventory-path] flags must be specified.
    81      - NOTE: The 'vm' keyword must be included between the datacenter name and folder name for the vm-inventory-path (e.g: <datacenter>/vm/<vm-folder>/<vm-name>) 
    82    Example:
    83      %[1]s package -vcenter-url vcenter.example.com -vcenter-username root -vcenter-password 'password' -vm-inventory-path '/my-datacenter/vm/my-folder/my-vm' 
    84  
    85  VMDK: 
    86  
    87    %[1]s package -vmdk <path-to-vmdk> 
    88  
    89    Requirements:
    90      - The VMware 'ovftool' binary must be on your path or Fusion/Workstation
    91      must be installed (both include the 'ovftool').
    92      - The [vmdk] flag must be specified.  If the [output] flag is
    93      not specified the stemcell will be created in the current working directory.
    94  
    95    Example:
    96      %[1]s package -vmdk my-1803-vmdk.vmdk 
    97  
    98      Will create an Windows 1803 stemcell using [vmdk] 'my-1803-vmdk.vmdk'
    99      The final stemcell will be found in the current working directory.
   100  
   101  Flags:
   102  `, filepath.Base(os.Args[0]))
   103  }
   104  
   105  func (p *PackageCmd) SetFlags(f *flag.FlagSet) {
   106  	f.StringVar(&p.sourceConfig.Vmdk, "vmdk", "", "VMDK file to create stemcell from")
   107  	f.StringVar(&p.sourceConfig.VmInventoryPath, "vm-inventory-path", "", "vCenter VM inventory path. (e.g: <datacenter>/vm/<vm-folder>/<vm-name>)")
   108  	f.StringVar(&p.sourceConfig.Username, "vcenter-username", "", "vCenter username")
   109  	f.StringVar(&p.sourceConfig.Password, "vcenter-password", "", "vCenter password")
   110  	f.StringVar(&p.sourceConfig.URL, "vcenter-url", "", "vCenter url")
   111  	f.StringVar(&p.sourceConfig.CaCertFile, "vcenter-ca-certs", "", "filepath for custom ca certs")
   112  
   113  	f.StringVar(&p.outputConfig.OutputDir, "outputDir", "", "Output directory, default is the current working directory.")
   114  	f.StringVar(&p.outputConfig.OutputDir, "o", "", "Output directory (shorthand)")
   115  	f.StringVar(&patchVersion, "patch-version", "", "Number or name of the patch version for the stemcell being built (e.g: for 2019.12.3 the string would be \"3\")")
   116  }
   117  
   118  func (p *PackageCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
   119  
   120  	logLevel := colorlogger.NONE
   121  	if p.GlobalFlags.Debug {
   122  		logLevel = colorlogger.DEBUG
   123  	}
   124  
   125  	p.setOSandStemcellVersions()
   126  
   127  	err := p.outputConfig.ValidateConfig()
   128  	if err != nil {
   129  		p.packagerMessenger.InvalidOutputConfig(err)
   130  		return subcommands.ExitFailure
   131  	}
   132  
   133  	packager, err := p.packagerFactory.Packager(p.sourceConfig, p.outputConfig, logLevel, p.GlobalFlags.Color)
   134  	if err != nil {
   135  		p.packagerMessenger.CannotCreatePackager(err)
   136  		return subcommands.ExitFailure
   137  	}
   138  
   139  	err = packager.ValidateFreeSpaceForPackage(&filesystem.OSFileSystem{})
   140  	if err != nil {
   141  		p.packagerMessenger.DoesNotHaveEnoughSpace(err)
   142  		return subcommands.ExitFailure
   143  	}
   144  
   145  	err = packager.ValidateSourceParameters()
   146  	if err != nil {
   147  		p.packagerMessenger.SourceParametersAreInvalid(err)
   148  		return subcommands.ExitFailure
   149  	}
   150  
   151  	if err := packager.Package(); err != nil {
   152  		p.packagerMessenger.PackageFailed(err)
   153  		return subcommands.ExitFailure
   154  	}
   155  
   156  	return subcommands.ExitSuccess
   157  }
   158  
   159  func (p *PackageCmd) setOSandStemcellVersions() {
   160  	p.outputConfig.Os = p.osAndVersionGetter.GetOs()
   161  
   162  	if patchVersion == "" {
   163  		p.outputConfig.StemcellVersion = p.osAndVersionGetter.GetVersion()
   164  	} else {
   165  		p.outputConfig.StemcellVersion = p.osAndVersionGetter.GetVersionWithPatchNumber(patchVersion)
   166  	}
   167  }