github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/cmd/roachprod/vm/local/local.go (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package local 12 13 import ( 14 "fmt" 15 "os" 16 "path/filepath" 17 "text/tabwriter" 18 "time" 19 20 "github.com/cockroachdb/cockroach/pkg/cmd/roachprod/config" 21 "github.com/cockroachdb/cockroach/pkg/cmd/roachprod/install" 22 "github.com/cockroachdb/cockroach/pkg/cmd/roachprod/vm" 23 "github.com/cockroachdb/cockroach/pkg/util/timeutil" 24 "github.com/cockroachdb/errors" 25 "github.com/spf13/pflag" 26 ) 27 28 // ProviderName is config.Local. 29 const ProviderName = config.Local 30 31 func init() { 32 vm.Providers[ProviderName] = &Provider{} 33 } 34 35 // A Provider is used to create stub VM objects. 36 type Provider struct{} 37 38 // No-op implementation of ProviderFlags 39 type emptyFlags struct{} 40 41 // ConfigureCreateFlags is part of ProviderFlags. This implementation is a no-op. 42 func (o *emptyFlags) ConfigureCreateFlags(flags *pflag.FlagSet) { 43 } 44 45 // ConfigureClusterFlags is part of ProviderFlags. This implementation is a no-op. 46 func (o *emptyFlags) ConfigureClusterFlags(*pflag.FlagSet, vm.MultipleProjectsOption) { 47 } 48 49 // CleanSSH is part of the vm.Provider interface. This implementation is a no-op. 50 func (p *Provider) CleanSSH() error { 51 return nil 52 } 53 54 // ConfigSSH is part of the vm.Provider interface. This implementation is a no-op. 55 func (p *Provider) ConfigSSH() error { 56 return nil 57 } 58 59 // Create just creates fake host-info entries in the local filesystem 60 func (p *Provider) Create(names []string, opts vm.CreateOpts) error { 61 path := filepath.Join(os.ExpandEnv(config.DefaultHostDir), config.Local) 62 file, err := os.Create(path) 63 if err != nil { 64 return errors.Wrapf(err, "problem creating file %s", path) 65 } 66 defer file.Close() 67 68 // Align columns left and separate with at least two spaces. 69 tw := tabwriter.NewWriter(file, 0, 8, 2, ' ', 0) 70 if _, err := tw.Write([]byte("# user@host\tlocality\n")); err != nil { 71 return err 72 } 73 for i := 0; i < len(names); i++ { 74 if _, err := tw.Write([]byte(fmt.Sprintf( 75 "%s@%s\t%s\n", config.OSUser.Username, "127.0.0.1", "region=local,zone=local"))); err != nil { 76 return err 77 } 78 } 79 if err := tw.Flush(); err != nil { 80 return errors.Wrapf(err, "problem writing file %s", path) 81 } 82 return nil 83 } 84 85 // Delete is part of the vm.Provider interface. This implementation is a no-op. 86 func (p *Provider) Delete(vms vm.List) error { 87 return nil 88 } 89 90 // Extend is part of the vm.Provider interface. This implementation returns an error. 91 func (p *Provider) Extend(vms vm.List, lifetime time.Duration) error { 92 return errors.New("local clusters have unlimited lifetime") 93 } 94 95 // FindActiveAccount is part of the vm.Provider interface. This implementation is a no-op. 96 func (p *Provider) FindActiveAccount() (string, error) { 97 return "", nil 98 } 99 100 // Flags is part of the vm.Provider interface. This implementation is a no-op. 101 func (p *Provider) Flags() vm.ProviderFlags { 102 return &emptyFlags{} 103 } 104 105 // List constructs N-many localhost VM instances, using SyncedCluster as a way to remember 106 // how many nodes we should have 107 func (p *Provider) List() (ret vm.List, _ error) { 108 if sc, ok := install.Clusters[ProviderName]; ok { 109 now := timeutil.Now() 110 for range sc.VMs { 111 ret = append(ret, vm.VM{ 112 Name: "localhost", 113 CreatedAt: now, 114 Lifetime: time.Hour, 115 PrivateIP: "127.0.0.1", 116 Provider: ProviderName, 117 ProviderID: ProviderName, 118 PublicIP: "127.0.0.1", 119 RemoteUser: config.OSUser.Username, 120 VPC: ProviderName, 121 MachineType: ProviderName, 122 Zone: ProviderName, 123 }) 124 } 125 } 126 return 127 } 128 129 // Name returns the name of the Provider, which will also surface in VM.Provider 130 func (p *Provider) Name() string { 131 return ProviderName 132 } 133 134 // Active is part of the vm.Provider interface. 135 func (p *Provider) Active() bool { 136 return true 137 }