github.com/hernad/nomad@v1.6.112/nomad/structs/service_registration.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package structs
     5  
     6  import (
     7  	"crypto/md5"
     8  	"encoding/binary"
     9  	"fmt"
    10  
    11  	"github.com/hernad/nomad/helper"
    12  	"github.com/hernad/nomad/helper/ipaddr"
    13  	"golang.org/x/exp/slices"
    14  )
    15  
    16  const (
    17  	// ServiceRegistrationUpsertRPCMethod is the RPC method for upserting
    18  	// service registrations into Nomad state.
    19  	//
    20  	// Args: ServiceRegistrationUpsertRequest
    21  	// Reply: ServiceRegistrationUpsertResponse
    22  	ServiceRegistrationUpsertRPCMethod = "ServiceRegistration.Upsert"
    23  
    24  	// ServiceRegistrationDeleteByIDRPCMethod is the RPC method for deleting
    25  	// a service registration by its ID.
    26  	//
    27  	// Args: ServiceRegistrationDeleteByIDRequest
    28  	// Reply: ServiceRegistrationDeleteByIDResponse
    29  	ServiceRegistrationDeleteByIDRPCMethod = "ServiceRegistration.DeleteByID"
    30  
    31  	// ServiceRegistrationListRPCMethod is the RPC method for listing service
    32  	// registrations within Nomad.
    33  	//
    34  	// Args: ServiceRegistrationListRequest
    35  	// Reply: ServiceRegistrationListResponse
    36  	ServiceRegistrationListRPCMethod = "ServiceRegistration.List"
    37  
    38  	// ServiceRegistrationGetServiceRPCMethod is the RPC method for detailing a
    39  	// service and its registrations according to its name.
    40  	//
    41  	// Args: ServiceRegistrationByNameRequest
    42  	// Reply: ServiceRegistrationByNameResponse
    43  	ServiceRegistrationGetServiceRPCMethod = "ServiceRegistration.GetService"
    44  )
    45  
    46  // ServiceRegistration is the internal representation of a Nomad service
    47  // registration.
    48  type ServiceRegistration struct {
    49  
    50  	// ID is the unique identifier for this registration. It currently follows
    51  	// the Consul service registration format to provide consistency between
    52  	// the two solutions.
    53  	ID string
    54  
    55  	// ServiceName is the human friendly identifier for this service
    56  	// registration. This is not unique.
    57  	ServiceName string
    58  
    59  	// Namespace is Job.Namespace and therefore the namespace in which this
    60  	// service registration resides.
    61  	Namespace string
    62  
    63  	// NodeID is Node.ID on which this service registration is currently
    64  	// running.
    65  	NodeID string
    66  
    67  	// Datacenter is the DC identifier of the node as identified by
    68  	// Node.Datacenter. It is denormalized here to allow filtering services by
    69  	// datacenter without looking up every node.
    70  	Datacenter string
    71  
    72  	// JobID is Job.ID and represents the job which contained the service block
    73  	// which resulted in this service registration.
    74  	JobID string
    75  
    76  	// AllocID is Allocation.ID and represents the allocation within which this
    77  	// service is running.
    78  	AllocID string
    79  
    80  	// Tags are determined from either Service.Tags or Service.CanaryTags and
    81  	// help identify this service. Tags can also be used to perform lookups of
    82  	// services depending on their state and role.
    83  	Tags []string
    84  
    85  	// Address is the IP address of this service registration. This information
    86  	// comes from the client and is not guaranteed to be routable; this depends
    87  	// on cluster network topology.
    88  	Address string
    89  
    90  	// Port is the port number on which this service registration is bound. It
    91  	// is determined by a combination of factors on the client.
    92  	Port int
    93  
    94  	CreateIndex uint64
    95  	ModifyIndex uint64
    96  }
    97  
    98  // Copy creates a deep copy of the service registration. This copy can then be
    99  // safely modified. It handles nil objects.
   100  func (s *ServiceRegistration) Copy() *ServiceRegistration {
   101  	if s == nil {
   102  		return nil
   103  	}
   104  
   105  	ns := new(ServiceRegistration)
   106  	*ns = *s
   107  	ns.Tags = slices.Clone(ns.Tags)
   108  
   109  	return ns
   110  }
   111  
   112  // Equal performs an equality check on the two service registrations. It
   113  // handles nil objects.
   114  func (s *ServiceRegistration) Equal(o *ServiceRegistration) bool {
   115  	if s == nil || o == nil {
   116  		return s == o
   117  	}
   118  	if s.ID != o.ID {
   119  		return false
   120  	}
   121  	if s.ServiceName != o.ServiceName {
   122  		return false
   123  	}
   124  	if s.NodeID != o.NodeID {
   125  		return false
   126  	}
   127  	if s.Datacenter != o.Datacenter {
   128  		return false
   129  	}
   130  	if s.JobID != o.JobID {
   131  		return false
   132  	}
   133  	if s.AllocID != o.AllocID {
   134  		return false
   135  	}
   136  	if s.Namespace != o.Namespace {
   137  		return false
   138  	}
   139  	if s.Address != o.Address {
   140  		return false
   141  	}
   142  	if s.Port != o.Port {
   143  		return false
   144  	}
   145  	if !helper.SliceSetEq(s.Tags, o.Tags) {
   146  		return false
   147  	}
   148  	return true
   149  }
   150  
   151  // Validate ensures the upserted service registration contains valid
   152  // information and routing capabilities. Objects should never fail here as
   153  // Nomad controls the entire registration process; but it's possible
   154  // configuration problems could cause failures.
   155  func (s *ServiceRegistration) Validate() error {
   156  	if ipaddr.IsAny(s.Address) {
   157  		return fmt.Errorf("invalid service registration address")
   158  	}
   159  	return nil
   160  }
   161  
   162  // GetID is a helper for getting the ID when the object may be nil and is
   163  // required for pagination.
   164  func (s *ServiceRegistration) GetID() string {
   165  	if s == nil {
   166  		return ""
   167  	}
   168  	return s.ID
   169  }
   170  
   171  // GetNamespace is a helper for getting the namespace when the object may be
   172  // nil and is required for pagination.
   173  func (s *ServiceRegistration) GetNamespace() string {
   174  	if s == nil {
   175  		return ""
   176  	}
   177  	return s.Namespace
   178  }
   179  
   180  // HashWith generates a unique value representative of s based on the contents of s.
   181  func (s *ServiceRegistration) HashWith(key string) string {
   182  	buf := make([]byte, 8)
   183  	binary.BigEndian.PutUint64(buf, uint64(s.Port))
   184  
   185  	sum := md5.New()
   186  	sum.Write(buf)
   187  	sum.Write([]byte(s.AllocID))
   188  	sum.Write([]byte(s.ID))
   189  	sum.Write([]byte(s.Namespace))
   190  	sum.Write([]byte(s.Address))
   191  	sum.Write([]byte(s.ServiceName))
   192  	for _, tag := range s.Tags {
   193  		sum.Write([]byte(tag))
   194  	}
   195  	sum.Write([]byte(key))
   196  	return fmt.Sprintf("%x", sum.Sum(nil))
   197  }
   198  
   199  // ServiceRegistrationUpsertRequest is the request object used to upsert one or
   200  // more service registrations.
   201  type ServiceRegistrationUpsertRequest struct {
   202  	Services []*ServiceRegistration
   203  	WriteRequest
   204  }
   205  
   206  // ServiceRegistrationUpsertResponse is the response object when one or more
   207  // service registrations have been successfully upserted into state.
   208  type ServiceRegistrationUpsertResponse struct {
   209  	WriteMeta
   210  }
   211  
   212  // ServiceRegistrationDeleteByIDRequest is the request object to delete a
   213  // service registration as specified by the ID parameter.
   214  type ServiceRegistrationDeleteByIDRequest struct {
   215  	ID string
   216  	WriteRequest
   217  }
   218  
   219  // ServiceRegistrationDeleteByIDResponse is the response object when performing a
   220  // deletion of an individual service registration.
   221  type ServiceRegistrationDeleteByIDResponse struct {
   222  	WriteMeta
   223  }
   224  
   225  // ServiceRegistrationDeleteByNodeIDRequest is the request object to delete all
   226  // service registrations assigned to a particular node.
   227  type ServiceRegistrationDeleteByNodeIDRequest struct {
   228  	NodeID string
   229  	WriteRequest
   230  }
   231  
   232  // ServiceRegistrationDeleteByNodeIDResponse is the response object when
   233  // performing a deletion of all service registrations assigned to a particular
   234  // node.
   235  type ServiceRegistrationDeleteByNodeIDResponse struct {
   236  	WriteMeta
   237  }
   238  
   239  // ServiceRegistrationListRequest is the request object when performing service
   240  // registration listings.
   241  type ServiceRegistrationListRequest struct {
   242  	QueryOptions
   243  }
   244  
   245  // ServiceRegistrationListResponse is the response object when performing a
   246  // list of services. This is specifically concise to reduce the serialisation
   247  // and network costs endpoint incur, particularly when performing blocking list
   248  // queries.
   249  type ServiceRegistrationListResponse struct {
   250  	Services []*ServiceRegistrationListStub
   251  	QueryMeta
   252  }
   253  
   254  // ServiceRegistrationListStub is the object which contains a list of namespace
   255  // service registrations and their tags.
   256  type ServiceRegistrationListStub struct {
   257  	Namespace string
   258  	Services  []*ServiceRegistrationStub
   259  }
   260  
   261  // ServiceRegistrationStub is the stub object describing an individual
   262  // namespaced service. The object is built in a manner which would allow us to
   263  // add additional fields in the future, if we wanted.
   264  type ServiceRegistrationStub struct {
   265  	ServiceName string
   266  	Tags        []string
   267  }
   268  
   269  // ServiceRegistrationByNameRequest is the request object to perform a lookup
   270  // of services matching a specific name.
   271  type ServiceRegistrationByNameRequest struct {
   272  	ServiceName string
   273  	Choose      string // stable selection of n services
   274  	QueryOptions
   275  }
   276  
   277  // ServiceRegistrationByNameResponse is the response object when performing a
   278  // lookup of services matching a specific name.
   279  type ServiceRegistrationByNameResponse struct {
   280  	Services []*ServiceRegistration
   281  	QueryMeta
   282  }