github.com/gravitational/teleport/api@v0.0.0-20240507183017-3110591cbafc/types/kubernetes_server.go (about) 1 /* 2 Copyright 2022 Gravitational, Inc. 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 package types 18 19 import ( 20 "fmt" 21 "sort" 22 "time" 23 24 "github.com/gravitational/trace" 25 26 "github.com/gravitational/teleport/api" 27 "github.com/gravitational/teleport/api/types/compare" 28 "github.com/gravitational/teleport/api/utils" 29 ) 30 31 var _ compare.IsEqual[KubeServer] = (*KubernetesServerV3)(nil) 32 33 // KubeServer represents a single Kubernetes server. 34 type KubeServer interface { 35 // ResourceWithLabels provides common resource methods. 36 ResourceWithLabels 37 // GetNamespace returns server namespace. 38 GetNamespace() string 39 // GetTeleportVersion returns the teleport version the server is running on. 40 GetTeleportVersion() string 41 // GetHostname returns the server hostname. 42 GetHostname() string 43 // GetHostID returns ID of the host the server is running on. 44 GetHostID() string 45 // GetRotation gets the state of certificate authority rotation. 46 GetRotation() Rotation 47 // SetRotation sets the state of certificate authority rotation. 48 SetRotation(Rotation) 49 // String returns string representation of the server. 50 String() string 51 // Copy returns a copy of this kube server object. 52 Copy() KubeServer 53 // CloneResource returns a copy of the KubeServer as a ResourceWithLabels 54 CloneResource() ResourceWithLabels 55 // GetCluster returns the Kubernetes Cluster this kube server proxies. 56 GetCluster() KubeCluster 57 // SetCluster sets the kube cluster this kube server server proxies. 58 SetCluster(KubeCluster) error 59 // ProxiedService provides common methods for a proxied service. 60 ProxiedService 61 } 62 63 // NewKubernetesServerV3 creates a new kube server instance. 64 func NewKubernetesServerV3(meta Metadata, spec KubernetesServerSpecV3) (*KubernetesServerV3, error) { 65 s := &KubernetesServerV3{ 66 Metadata: meta, 67 Spec: spec, 68 } 69 if err := s.CheckAndSetDefaults(); err != nil { 70 return nil, trace.Wrap(err) 71 } 72 return s, nil 73 } 74 75 // NewKubernetesServerV3FromCluster creates a new kubernetes server from the provided clusters. 76 func NewKubernetesServerV3FromCluster(cluster *KubernetesClusterV3, hostname, hostID string) (*KubernetesServerV3, error) { 77 return NewKubernetesServerV3(Metadata{ 78 Name: cluster.GetName(), 79 }, KubernetesServerSpecV3{ 80 Hostname: hostname, 81 HostID: hostID, 82 Cluster: cluster, 83 }) 84 } 85 86 // GetVersion returns the kubernetes server resource version. 87 func (s *KubernetesServerV3) GetVersion() string { 88 return s.Version 89 } 90 91 // GetTeleportVersion returns the Teleport version the server is running. 92 func (s *KubernetesServerV3) GetTeleportVersion() string { 93 return s.Spec.Version 94 } 95 96 // GetHostname returns the kubernetes server hostname. 97 func (s *KubernetesServerV3) GetHostname() string { 98 return s.Spec.Hostname 99 } 100 101 // GetHostID returns ID of the host the server is running on. 102 func (s *KubernetesServerV3) GetHostID() string { 103 return s.Spec.HostID 104 } 105 106 // GetKind returns the resource kind. 107 func (s *KubernetesServerV3) GetKind() string { 108 return s.Kind 109 } 110 111 // GetSubKind returns the resource subkind. 112 func (s *KubernetesServerV3) GetSubKind() string { 113 return s.SubKind 114 } 115 116 // SetSubKind sets the resource subkind. 117 func (s *KubernetesServerV3) SetSubKind(sk string) { 118 s.SubKind = sk 119 } 120 121 // GetResourceID returns the resource ID. 122 func (s *KubernetesServerV3) GetResourceID() int64 { 123 return s.Metadata.ID 124 } 125 126 // SetResourceID sets the resource ID. 127 func (s *KubernetesServerV3) SetResourceID(id int64) { 128 s.Metadata.ID = id 129 } 130 131 // GetRevision returns the revision 132 func (s *KubernetesServerV3) GetRevision() string { 133 return s.Metadata.GetRevision() 134 } 135 136 // SetRevision sets the revision 137 func (s *KubernetesServerV3) SetRevision(rev string) { 138 s.Metadata.SetRevision(rev) 139 } 140 141 // GetMetadata returns the resource metadata. 142 func (s *KubernetesServerV3) GetMetadata() Metadata { 143 return s.Metadata 144 } 145 146 // GetNamespace returns the resource namespace. 147 func (s *KubernetesServerV3) GetNamespace() string { 148 return s.Metadata.Namespace 149 } 150 151 // SetExpiry sets the resource expiry time. 152 func (s *KubernetesServerV3) SetExpiry(expiry time.Time) { 153 s.Metadata.SetExpiry(expiry) 154 } 155 156 // Expiry returns the resource expiry time. 157 func (s *KubernetesServerV3) Expiry() time.Time { 158 return s.Metadata.Expiry() 159 } 160 161 // GetName returns the resource name. 162 func (s *KubernetesServerV3) GetName() string { 163 return s.Metadata.Name 164 } 165 166 // SetName sets the resource name. 167 func (s *KubernetesServerV3) SetName(name string) { 168 s.Metadata.Name = name 169 } 170 171 // GetRotation returns the server CA rotation state. 172 func (s *KubernetesServerV3) GetRotation() Rotation { 173 return s.Spec.Rotation 174 } 175 176 // SetRotation sets the server CA rotation state. 177 func (s *KubernetesServerV3) SetRotation(r Rotation) { 178 s.Spec.Rotation = r 179 } 180 181 // GetCluster returns the cluster this kube server proxies. 182 func (s *KubernetesServerV3) GetCluster() KubeCluster { 183 if s.Spec.Cluster == nil { 184 return nil 185 } 186 return s.Spec.Cluster 187 } 188 189 // SetCluster sets the cluster this kube server proxies. 190 func (s *KubernetesServerV3) SetCluster(cluster KubeCluster) error { 191 clusterV3, ok := cluster.(*KubernetesClusterV3) 192 if !ok { 193 return trace.BadParameter("expected *KubernetesClusterV3, got %T", cluster) 194 } 195 s.Spec.Cluster = clusterV3 196 return nil 197 } 198 199 // String returns the server string representation. 200 func (s *KubernetesServerV3) String() string { 201 return fmt.Sprintf("KubeServer(Name=%v, Version=%v, Hostname=%v, HostID=%v, Cluster=%v)", 202 s.GetName(), s.GetTeleportVersion(), s.GetHostname(), s.GetHostID(), s.GetCluster()) 203 } 204 205 // setStaticFields sets static resource header and metadata fields. 206 func (s *KubernetesServerV3) setStaticFields() { 207 s.Kind = KindKubeServer 208 s.Version = V3 209 } 210 211 // CheckAndSetDefaults checks and sets default values for any missing fields. 212 func (s *KubernetesServerV3) CheckAndSetDefaults() error { 213 s.setStaticFields() 214 if err := s.Metadata.CheckAndSetDefaults(); err != nil { 215 return trace.Wrap(err) 216 } 217 if s.Spec.HostID == "" { 218 return trace.BadParameter("missing kube server HostID") 219 } 220 if s.Spec.Version == "" { 221 s.Spec.Version = api.Version 222 } 223 if s.Spec.Cluster == nil { 224 return trace.BadParameter("missing kube server Cluster") 225 } 226 227 if err := s.Spec.Cluster.CheckAndSetDefaults(); err != nil { 228 return trace.Wrap(err) 229 } 230 231 return nil 232 } 233 234 // Origin returns the origin value of the resource. 235 func (s *KubernetesServerV3) Origin() string { 236 return s.Metadata.Origin() 237 } 238 239 // SetOrigin sets the origin value of the resource. 240 func (s *KubernetesServerV3) SetOrigin(origin string) { 241 s.Metadata.SetOrigin(origin) 242 } 243 244 // GetProxyIDs returns a list of proxy ids this server is connected to. 245 func (s *KubernetesServerV3) GetProxyIDs() []string { 246 return s.Spec.ProxyIDs 247 } 248 249 // SetProxyID sets the proxy ids this server is connected to. 250 func (s *KubernetesServerV3) SetProxyIDs(proxyIDs []string) { 251 s.Spec.ProxyIDs = proxyIDs 252 } 253 254 // GetLabel retrieves the label with the provided key. If not found 255 // value will be empty and ok will be false. 256 func (s *KubernetesServerV3) GetLabel(key string) (value string, ok bool) { 257 if s.Spec.Cluster != nil { 258 if v, ok := s.Spec.Cluster.GetLabel(key); ok { 259 return v, ok 260 } 261 } 262 263 v, ok := s.Metadata.Labels[key] 264 return v, ok 265 } 266 267 // GetAllLabels returns all resource's labels. Considering: 268 // * Static labels from `Metadata.Labels` and `Spec.Cluster`. 269 // * Dynamic labels from `Spec.Cluster.Spec`. 270 func (s *KubernetesServerV3) GetAllLabels() map[string]string { 271 staticLabels := make(map[string]string) 272 for name, value := range s.Metadata.Labels { 273 staticLabels[name] = value 274 } 275 276 var dynamicLabels map[string]CommandLabelV2 277 if s.Spec.Cluster != nil { 278 for name, value := range s.Spec.Cluster.Metadata.Labels { 279 staticLabels[name] = value 280 } 281 282 dynamicLabels = s.Spec.Cluster.Spec.DynamicLabels 283 } 284 285 return CombineLabels(staticLabels, dynamicLabels) 286 } 287 288 // GetStaticLabels returns the kube server static labels. 289 func (s *KubernetesServerV3) GetStaticLabels() map[string]string { 290 return s.Metadata.Labels 291 } 292 293 // SetStaticLabels sets the kube server static labels. 294 func (s *KubernetesServerV3) SetStaticLabels(sl map[string]string) { 295 s.Metadata.Labels = sl 296 } 297 298 // Copy returns a copy of this kube server object. 299 func (s *KubernetesServerV3) Copy() KubeServer { 300 return utils.CloneProtoMsg(s) 301 } 302 303 // CloneResource returns a copy of this kube server object. 304 func (s *KubernetesServerV3) CloneResource() ResourceWithLabels { 305 return s.Copy() 306 } 307 308 // MatchSearch goes through select field values and tries to 309 // match against the list of search values. 310 func (s *KubernetesServerV3) MatchSearch(values []string) bool { 311 return MatchSearch(nil, values, nil) 312 } 313 314 // IsEqual determines if two kube server resources are equivalent to one another. 315 func (k *KubernetesServerV3) IsEqual(i KubeServer) bool { 316 if other, ok := i.(*KubernetesServerV3); ok { 317 return deriveTeleportEqualKubernetesServerV3(k, other) 318 } 319 return false 320 } 321 322 // KubeServers represents a list of kube servers. 323 type KubeServers []KubeServer 324 325 // Len returns the slice length. 326 func (s KubeServers) Len() int { return len(s) } 327 328 // Less compares kube servers by name and host ID. 329 func (s KubeServers) Less(i, j int) bool { 330 switch { 331 case s[i].GetName() < s[j].GetName(): 332 return true 333 case s[i].GetName() > s[j].GetName(): 334 return false 335 default: 336 return s[i].GetHostID() < s[j].GetHostID() 337 } 338 } 339 340 // Swap swaps two kube servers. 341 func (s KubeServers) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 342 343 // ToMap returns these kubernetes clusters as a map keyed by cluster name. 344 func (s KubeServers) ToMap() map[string]KubeServer { 345 m := make(map[string]KubeServer, len(s)) 346 for _, kubeServer := range s { 347 m[kubeServer.GetName()] = kubeServer 348 } 349 return m 350 } 351 352 // SortByCustom custom sorts by given sort criteria. 353 func (s KubeServers) SortByCustom(sortBy SortBy) error { 354 if sortBy.Field == "" { 355 return nil 356 } 357 358 // We assume sorting by type KubeServer, we are really 359 // wanting to sort its contained resource Cluster. 360 isDesc := sortBy.IsDesc 361 switch sortBy.Field { 362 case ResourceMetadataName: 363 sort.SliceStable(s, func(i, j int) bool { 364 return stringCompare(s[i].GetCluster().GetName(), s[j].GetCluster().GetName(), isDesc) 365 }) 366 case ResourceSpecDescription: 367 sort.SliceStable(s, func(i, j int) bool { 368 return stringCompare(s[i].GetCluster().GetDescription(), s[j].GetCluster().GetDescription(), isDesc) 369 }) 370 default: 371 return trace.NotImplemented("sorting by field %q for resource %q is not supported", sortBy.Field, KindKubeServer) 372 } 373 374 return nil 375 } 376 377 // AsResources returns kube servers as type resources with labels. 378 func (s KubeServers) AsResources() []ResourceWithLabels { 379 resources := make([]ResourceWithLabels, len(s)) 380 for i, server := range s { 381 resources[i] = ResourceWithLabels(server) 382 } 383 return resources 384 } 385 386 // GetFieldVals returns list of select field values. 387 func (s KubeServers) GetFieldVals(field string) ([]string, error) { 388 vals := make([]string, 0, len(s)) 389 switch field { 390 case ResourceMetadataName: 391 for _, server := range s { 392 vals = append(vals, server.GetCluster().GetName()) 393 } 394 case ResourceSpecDescription: 395 for _, server := range s { 396 vals = append(vals, server.GetCluster().GetDescription()) 397 } 398 default: 399 return nil, trace.NotImplemented("getting field %q for resource %q is not supported", field, KindKubeServer) 400 } 401 402 return vals, nil 403 }