github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/nomad/structs/service_registration.go (about)

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