github.com/gravitational/teleport/api@v0.0.0-20240507183017-3110591cbafc/types/resource_153.go (about) 1 // Copyright 2023 Gravitational, Inc 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 types 16 17 import ( 18 "encoding/json" 19 "time" 20 21 "google.golang.org/protobuf/types/known/timestamppb" 22 23 headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" 24 ) 25 26 // ResourceMetadata is the smallest interface that defines a Teleport resource. 27 type ResourceMetadata interface { 28 // GetMetadata returns the generic resource metadata. 29 GetMetadata() *headerv1.Metadata 30 } 31 32 // Resource153 is a resource that follows RFD 153. 33 // 34 // It exists as a weak guideline for fields that resource protos must provide 35 // and as a way to adapt "new" resources to the legacy [Resource] interface. 36 // 37 // Strongly prefer using actual types, like *myprotov1.Foo, instead of this 38 // interface. If you do need to represent resources in a generic manner, 39 // consider declaring a smaller interface with only what you need. 40 // 41 // Embedding or further extending this interface is highly discouraged. 42 type Resource153 interface { 43 // GetKind returns the resource kind. 44 // 45 // Kind is usually hard-coded for each underlying type. 46 GetKind() string 47 48 // GetSubKind returns the resource sub-kind, if any. 49 GetSubKind() string 50 51 // GetVersion returns the resource API version. 52 // 53 // See [headerv1.Metadata.Revision] for an identifier of the resource over 54 // time. 55 GetVersion() string 56 57 // GetMetadata returns the generic resource metadata. 58 GetMetadata() *headerv1.Metadata 59 } 60 61 // LegacyToResource153 converts a legacy [Resource] into a [Resource153]. 62 // 63 // Useful to handle old and new resources uniformly. If you can, consider 64 // further "downgrading" the Resource153 interface into the smallest subset that 65 // works for you (for example, [ResourceMetadata]). 66 func LegacyToResource153(r Resource) Resource153 { 67 return &legacyToResource153Adapter{inner: r} 68 } 69 70 type legacyToResource153Adapter struct { 71 inner Resource 72 } 73 74 // Unwrap is an escape hatch for Resource instances that are piped down into the 75 // codebase as a legacy Resource. 76 // 77 // Ideally you shouldn't depend on this. 78 func (r *legacyToResource153Adapter) Unwrap() Resource { 79 return r.inner 80 } 81 82 // MarshalJSON adds support for marshaling the wrapped resource (instead of 83 // marshaling the adapter itself). 84 func (r *legacyToResource153Adapter) MarshalJSON() ([]byte, error) { 85 return json.Marshal(r.inner) 86 } 87 88 func (r *legacyToResource153Adapter) GetKind() string { 89 return r.inner.GetKind() 90 } 91 92 func (r *legacyToResource153Adapter) GetMetadata() *headerv1.Metadata { 93 md := r.inner.GetMetadata() 94 95 var expires *timestamppb.Timestamp 96 if md.Expires != nil { 97 expires = timestamppb.New(*md.Expires) 98 } 99 100 return &headerv1.Metadata{ 101 Name: md.Name, 102 Namespace: md.Namespace, 103 Description: md.Description, 104 Labels: md.Labels, 105 Expires: expires, 106 Id: md.ID, 107 Revision: md.Revision, 108 } 109 } 110 111 func (r *legacyToResource153Adapter) GetSubKind() string { 112 return r.inner.GetSubKind() 113 } 114 115 func (r *legacyToResource153Adapter) GetVersion() string { 116 return r.inner.GetVersion() 117 } 118 119 // Resource153ToLegacy transforms an RFD 153 style resource into a legacy 120 // [Resource] type. 121 // 122 // Note that CheckAndSetDefaults is a noop for the returned resource and 123 // SetSubKind is not implemented and panics on use. 124 func Resource153ToLegacy(r Resource153) Resource { 125 return &resource153ToLegacyAdapter{inner: r} 126 } 127 128 // Resource153Unwrapper returns a legacy [Resource] type from a wrapped RFD 129 // 153 style resource 130 type Resource153Unwrapper interface { 131 Unwrap() Resource153 132 } 133 134 type resource153ToLegacyAdapter struct { 135 inner Resource153 136 } 137 138 // Unwrap is an escape hatch for Resource153 instances that are piped down into 139 // the codebase as a legacy Resource. 140 // 141 // Ideally you shouldn't depend on this. 142 func (r *resource153ToLegacyAdapter) Unwrap() Resource153 { 143 return r.inner 144 } 145 146 // MarshalJSON adds support for marshaling the wrapped resource (instead of 147 // marshaling the adapter itself). 148 func (r *resource153ToLegacyAdapter) MarshalJSON() ([]byte, error) { 149 return json.Marshal(r.inner) 150 } 151 152 func (r *resource153ToLegacyAdapter) Expiry() time.Time { 153 expires := r.inner.GetMetadata().Expires 154 // return zero time.time{} for zero *timestamppb.Timestamp, instead of 01/01/1970. 155 if expires == nil { 156 return time.Time{} 157 } 158 159 return expires.AsTime() 160 } 161 162 func (r *resource153ToLegacyAdapter) GetKind() string { 163 return r.inner.GetKind() 164 } 165 166 func (r *resource153ToLegacyAdapter) GetMetadata() Metadata { 167 md := r.inner.GetMetadata() 168 169 // use zero time.time{} for zero *timestamppb.Timestamp, instead of 01/01/1970. 170 expires := md.Expires.AsTime() 171 if md.Expires == nil { 172 expires = time.Time{} 173 } 174 175 return Metadata{ 176 Name: md.Name, 177 Namespace: md.Namespace, 178 Description: md.Description, 179 Labels: md.Labels, 180 Expires: &expires, 181 //nolint:staticcheck // SA1019. We need to refer to Id to create the Metadata. 182 ID: md.Id, 183 Revision: md.Revision, 184 } 185 } 186 187 func (r *resource153ToLegacyAdapter) GetName() string { 188 return r.inner.GetMetadata().Name 189 } 190 191 func (r *resource153ToLegacyAdapter) GetResourceID() int64 { 192 //nolint:staticcheck // SA1019. We need to refer to Id to provide GetResourceID. 193 return r.inner.GetMetadata().Id 194 } 195 196 func (r *resource153ToLegacyAdapter) GetRevision() string { 197 return r.inner.GetMetadata().Revision 198 } 199 200 func (r *resource153ToLegacyAdapter) GetSubKind() string { 201 return r.inner.GetSubKind() 202 } 203 204 func (r *resource153ToLegacyAdapter) GetVersion() string { 205 return r.inner.GetVersion() 206 } 207 208 func (r *resource153ToLegacyAdapter) SetExpiry(t time.Time) { 209 r.inner.GetMetadata().Expires = timestamppb.New(t) 210 } 211 212 func (r *resource153ToLegacyAdapter) SetName(name string) { 213 r.inner.GetMetadata().Name = name 214 } 215 216 func (r *resource153ToLegacyAdapter) SetResourceID(id int64) { 217 //nolint:staticcheck // SA1019. We need to refer to Id to provide SetResourceID. 218 r.inner.GetMetadata().Id = id 219 } 220 221 func (r *resource153ToLegacyAdapter) SetRevision(rev string) { 222 r.inner.GetMetadata().Revision = rev 223 } 224 225 func (r *resource153ToLegacyAdapter) SetSubKind(subKind string) { 226 panic("interface Resource153 does not implement SetSubKind") 227 }