github.com/gravitational/teleport/api@v0.0.0-20240507183017-3110591cbafc/types/header/header.go (about)

     1  /*
     2  Copyright 2023 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 header
    18  
    19  import (
    20  	"slices"
    21  	"time"
    22  
    23  	"github.com/gravitational/trace"
    24  
    25  	"github.com/gravitational/teleport/api/types/common"
    26  	"github.com/gravitational/teleport/api/types/compare"
    27  	"github.com/gravitational/teleport/api/utils"
    28  )
    29  
    30  var (
    31  	_ compare.IsEqual[*ResourceHeader] = (*ResourceHeader)(nil)
    32  	_ compare.IsEqual[*Metadata]       = (*Metadata)(nil)
    33  )
    34  
    35  func ResourceHeaderFromMetadata(metadata Metadata) ResourceHeader {
    36  	return ResourceHeader{
    37  		Metadata: metadata,
    38  	}
    39  }
    40  
    41  // ResourceHeader is a common header for Teleport resources.
    42  type ResourceHeader struct {
    43  	// Kind is a resource kind.
    44  	Kind string `json:"kind,omitempty"`
    45  	// SubKind is an optional resource sub kind, used in some resources.
    46  	SubKind string `json:"sub_kind,omitempty"`
    47  	// Version is the resource version.
    48  	Version string `json:"version,omitempty"`
    49  	// Metadata is metadata for the resource.
    50  	Metadata Metadata `json:"metadata,omitempty"`
    51  }
    52  
    53  // GetVersion returns the resource version.
    54  func (h *ResourceHeader) GetVersion() string {
    55  	return h.Version
    56  }
    57  
    58  // SetVersion sets the resource version.
    59  func (h *ResourceHeader) SetVersion(version string) {
    60  	h.Version = version
    61  }
    62  
    63  // GetResourceID returns the resource ID.
    64  func (h *ResourceHeader) GetResourceID() int64 {
    65  	return h.Metadata.GetID()
    66  }
    67  
    68  // SetResourceID sets the resource ID.
    69  func (h *ResourceHeader) SetResourceID(id int64) {
    70  	h.Metadata.SetID(id)
    71  }
    72  
    73  // GetRevision returns the revision.
    74  func (h *ResourceHeader) GetRevision() string {
    75  	return h.Metadata.GetRevision()
    76  }
    77  
    78  // SetRevision sets the revision.
    79  func (h *ResourceHeader) SetRevision(rev string) {
    80  	h.Metadata.SetRevision(rev)
    81  }
    82  
    83  // GetName returns the name of the resource.
    84  func (h *ResourceHeader) GetName() string {
    85  	return h.Metadata.GetName()
    86  }
    87  
    88  // SetName sets the name of the resource.
    89  func (h *ResourceHeader) SetName(v string) {
    90  	h.Metadata.SetName(v)
    91  }
    92  
    93  // Expiry returns the resource expiry setting.
    94  func (h *ResourceHeader) Expiry() time.Time {
    95  	return h.Metadata.Expiry()
    96  }
    97  
    98  // SetExpiry sets the resource expiry.
    99  func (h *ResourceHeader) SetExpiry(t time.Time) {
   100  	h.Metadata.SetExpiry(t)
   101  }
   102  
   103  // GetMetadata returns object metadata.
   104  func (h *ResourceHeader) GetMetadata() Metadata {
   105  	return h.Metadata
   106  }
   107  
   108  // GetKind returns the resource kind.
   109  func (h *ResourceHeader) GetKind() string {
   110  	return h.Kind
   111  }
   112  
   113  // SetKind sets the resource kind.
   114  func (h *ResourceHeader) SetKind(kind string) {
   115  	h.Kind = kind
   116  }
   117  
   118  // GetSubKind returns the resource subkind.
   119  func (h *ResourceHeader) GetSubKind() string {
   120  	return h.SubKind
   121  }
   122  
   123  // SetSubKind sets the resource subkind.
   124  func (h *ResourceHeader) SetSubKind(s string) {
   125  	h.SubKind = s
   126  }
   127  
   128  // Origin returns the origin value of the resource.
   129  func (h *ResourceHeader) Origin() string {
   130  	return h.Metadata.Origin()
   131  }
   132  
   133  // SetOrigin sets the origin value of the resource.
   134  func (h *ResourceHeader) SetOrigin(origin string) {
   135  	h.Metadata.SetOrigin(origin)
   136  }
   137  
   138  // GetStaticLabels returns the static labels for the resource.
   139  func (h *ResourceHeader) GetStaticLabels() map[string]string {
   140  	return h.Metadata.GetStaticLabels()
   141  }
   142  
   143  // SetStaticLabels sets the static labels for the resource.
   144  func (h *ResourceHeader) SetStaticLabels(sl map[string]string) {
   145  	h.Metadata.SetStaticLabels(sl)
   146  }
   147  
   148  // GetLabel retrieves the label with the provided key. If not found
   149  // value will be empty and ok will be false.
   150  func (h *ResourceHeader) GetLabel(key string) (string, bool) {
   151  	return h.Metadata.GetLabel(key)
   152  }
   153  
   154  // GetAllLabels returns all labels from the resource.
   155  func (h *ResourceHeader) GetAllLabels() map[string]string {
   156  	return h.Metadata.GetAllLabels()
   157  }
   158  
   159  // CheckAndSetDefaults will verify that the resource header is valid. This will additionally
   160  // verify that the metadata is valid.
   161  func (h *ResourceHeader) CheckAndSetDefaults() error {
   162  	if h.Kind == "" {
   163  		return trace.BadParameter("resource has an empty Kind field")
   164  	}
   165  	if h.Version == "" {
   166  		return trace.BadParameter("resource has an empty Version field")
   167  	}
   168  	return trace.Wrap(h.Metadata.CheckAndSetDefaults())
   169  }
   170  
   171  // IsEqual determines if two resource headers are equivalent to one another.
   172  func (h *ResourceHeader) IsEqual(i *ResourceHeader) bool {
   173  	return deriveTeleportEqualResourceHeader(h, i)
   174  }
   175  
   176  // Metadata is resource metadata
   177  type Metadata struct {
   178  	// Name is an object name
   179  	Name string `json:"name" yaml:"name"`
   180  	// Description is object description
   181  	Description string `json:"description,omitempty" yaml:"description,omitempty"`
   182  	// Labels is a set of labels
   183  	Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
   184  	// Expires is a global expiry time header can be set on any resource in the system.
   185  	Expires time.Time `json:"expires" yaml:"expires"`
   186  	// ID is a record ID
   187  	// Deprecated: Use revision instead.
   188  	ID int64 `json:"id,omitempty" yaml:"id,omitempty"`
   189  	// Revision is an opaque identifier which tracks the versions of a resource
   190  	// over time. Clients should ignore and not alter its value but must return
   191  	// the revision in any updates of a resource.
   192  	Revision string `json:"revision,omitempty" yaml:"revision,omitempty"`
   193  }
   194  
   195  // GetID returns the resource ID.
   196  // Deprecated: Use GetRevision instead
   197  func (m *Metadata) GetID() int64 {
   198  	return m.ID
   199  }
   200  
   201  // SetID sets the resource ID.
   202  // Deprecated: Use SetRevision instead
   203  func (m *Metadata) SetID(id int64) {
   204  	m.ID = id
   205  }
   206  
   207  // GetRevision returns the revision
   208  func (m *Metadata) GetRevision() string {
   209  	return m.Revision
   210  }
   211  
   212  // SetRevision sets the revision
   213  func (m *Metadata) SetRevision(rev string) {
   214  	m.Revision = rev
   215  }
   216  
   217  // GetName returns the name of the resource.
   218  func (m *Metadata) GetName() string {
   219  	return m.Name
   220  }
   221  
   222  // SetName sets the name of the resource.
   223  func (m *Metadata) SetName(name string) {
   224  	m.Name = name
   225  }
   226  
   227  // SetExpiry sets the expiry time for the object.
   228  func (m *Metadata) SetExpiry(expires time.Time) {
   229  	m.Expires = expires
   230  }
   231  
   232  // Expiry returns the object expiry setting.
   233  func (m *Metadata) Expiry() time.Time {
   234  	return m.Expires
   235  }
   236  
   237  // Origin returns the origin value of the resource.
   238  func (m *Metadata) Origin() string {
   239  	if m.Labels == nil {
   240  		return ""
   241  	}
   242  	return m.Labels[common.OriginLabel]
   243  }
   244  
   245  // SetOrigin sets the origin value of the resource.
   246  func (m *Metadata) SetOrigin(origin string) {
   247  	if m.Labels == nil {
   248  		m.Labels = map[string]string{}
   249  	}
   250  	m.Labels[common.OriginLabel] = origin
   251  }
   252  
   253  // CheckAndSetDefaults verifies that the metadata object is valid.
   254  func (m *Metadata) CheckAndSetDefaults() error {
   255  	if m.Name == "" {
   256  		return trace.BadParameter("missing parameter Name")
   257  	}
   258  
   259  	// adjust expires time to UTC if it's set
   260  	if !m.Expires.IsZero() {
   261  		utils.UTC(&m.Expires)
   262  	}
   263  
   264  	for key := range m.Labels {
   265  		if !common.IsValidLabelKey(key) {
   266  			return trace.BadParameter("invalid label key: %q", key)
   267  		}
   268  	}
   269  
   270  	// Check the origin value.
   271  	if m.Origin() != "" {
   272  		if !slices.Contains(common.OriginValues, m.Origin()) {
   273  			return trace.BadParameter("invalid origin value %q, must be one of %v", m.Origin(), common.OriginValues)
   274  		}
   275  	}
   276  
   277  	return nil
   278  }
   279  
   280  // GetStaticLabels returns the static labels for the metadata.
   281  func (m *Metadata) GetStaticLabels() map[string]string {
   282  	return m.Labels
   283  }
   284  
   285  // SetStaticLabels sets the static labels for the metadata.
   286  func (m *Metadata) SetStaticLabels(sl map[string]string) {
   287  	m.Labels = sl
   288  }
   289  
   290  // GetLabel retrieves the label with the provided key. If not found
   291  // value will be empty and ok will be false.
   292  func (m *Metadata) GetLabel(key string) (string, bool) {
   293  	v, ok := m.Labels[key]
   294  	return v, ok
   295  }
   296  
   297  // GetAllLabels returns all labels from the resource.
   298  func (m *Metadata) GetAllLabels() map[string]string {
   299  	return m.Labels
   300  }
   301  
   302  // IsEqual determines if two metadata resources are equivalent to one another.
   303  func (m *Metadata) IsEqual(i *Metadata) bool {
   304  	return deriveTeleportEqualMetadata(m, i)
   305  }