gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/tools/gvisor_k8s_tool/provider/clusterflag/clusterflag.go (about) 1 // Copyright 2023 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package clusterflag implements a flag.Value which can be used in commands 16 // to represent a Kubernetes cluster. 17 package clusterflag 18 19 import ( 20 "context" 21 "fmt" 22 "strings" 23 24 "gvisor.dev/gvisor/tools/gvisor_k8s_tool/cluster" 25 "gvisor.dev/gvisor/tools/gvisor_k8s_tool/provider/gke" 26 "gvisor.dev/gvisor/tools/gvisor_k8s_tool/provider/kubectl" 27 ) 28 29 // Provider is a cluster provider. 30 type Provider string 31 32 const ( 33 // Kubectl is a provider using a local kubectl config. 34 Kubectl Provider = "kube" 35 36 // GKE is a provider using GKE. 37 GKE Provider = "gke" 38 ) 39 40 // String returns the provider name. 41 func (p Provider) String() string { 42 return string(p) 43 } 44 45 // Valid returns whether the Provider is valid. 46 func (p Provider) Valid() bool { 47 switch p { 48 case Kubectl, GKE: 49 return true 50 default: 51 return false 52 } 53 } 54 55 // ValidInfo validates whether the given info is valid for this provider. 56 func (p Provider) ValidInfo(info string) error { 57 switch p { 58 case Kubectl: 59 return nil 60 case GKE: 61 _, err := gke.NewClusterURL(info) 62 return err 63 default: 64 return fmt.Errorf("invalid provider: %q", p) 65 } 66 } 67 68 // Flag contains the necessary information to connect to a Kubernetes cluster. 69 // Flag implements flag.Value. 70 type Flag struct { 71 StringVal string 72 Provider Provider 73 Info string 74 } 75 76 // Valid checks if the flag values are valid. 77 func (f *Flag) Valid() error { 78 if !f.Provider.Valid() { 79 return fmt.Errorf("invalid provider: %q", f.Provider) 80 } 81 if err := f.Provider.ValidInfo(f.Info); err != nil { 82 return fmt.Errorf("invalid info for provider %q: %w", f.Provider, err) 83 } 84 return nil 85 } 86 87 // String implements flag.Value.String. 88 func (f *Flag) String() string { 89 return f.StringVal 90 } 91 92 // Get implements flag.Value.Get. 93 func (f *Flag) Get() any { 94 return f 95 } 96 97 // Set implements flag.Value.Set. 98 // Set(String()) should be idempotent. 99 func (f *Flag) Set(s string) error { 100 f.StringVal = s 101 parts := strings.SplitN(s, ":", 2) 102 if len(parts) != 2 { 103 return fmt.Errorf("invalid format: %q (expected <provider>:<info>)", s) 104 } 105 f2 := Flag{ 106 StringVal: s, 107 Provider: Provider(parts[0]), 108 Info: parts[1], 109 } 110 if err := f2.Valid(); err != nil { 111 return err 112 } 113 f.Provider = f2.Provider 114 f.Info = f2.Info 115 return nil 116 } 117 118 // Cluster creates a cluster client. 119 func (f *Flag) Cluster(ctx context.Context) (*cluster.Cluster, error) { 120 switch f.Provider { 121 case Kubectl: 122 return kubectl.NewCluster(f.Info) 123 case GKE: 124 clusterURL, err := gke.NewClusterURL(f.Info) 125 if err != nil { 126 return nil, err 127 } 128 return gke.GetCluster(ctx, clusterURL) 129 default: 130 return nil, fmt.Errorf("invalid provider: %q", f.Provider) 131 } 132 }