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  }