consul/agent/structs/config_entry_exports.go

146 lines
3.6 KiB
Go

package structs
import (
"fmt"
"github.com/hashicorp/consul/acl"
)
// ServiceExportsConfigEntry is the top-level struct for exporting a service to be exposed
// across other admin partitions.
type ServiceExportsConfigEntry struct {
Partition string
// Services is a list of services to be exported and the list of partitions
// to expose them to.
Services []ExportedService
Meta map[string]string `json:",omitempty"`
EnterpriseMeta `hcl:",squash" mapstructure:",squash"`
RaftIndex
}
// ExportedService manages the exporting of a service in the local partition to
// other partitions.
type ExportedService struct {
// Name is the name of the service to be exported.
Name string
// Namespace is the namespace to export the service from.
Namespace string `json:",omitempty"`
// Consumers is a list of downstream consumers of the service to be exported.
Consumers []ServiceConsumer
}
// ServiceConsumer represents a downstream consumer of the service to be exported.
type ServiceConsumer struct {
// Partition is the admin partition to export the service to.
Partition string
}
func (e *ServiceExportsConfigEntry) Clone() *ServiceExportsConfigEntry {
e2 := *e
e2.Services = make([]ExportedService, len(e.Services))
for _, svc := range e.Services {
exportedSvc := svc
exportedSvc.Consumers = make([]ServiceConsumer, len(svc.Consumers))
for _, consumer := range svc.Consumers {
exportedSvc.Consumers = append(exportedSvc.Consumers, consumer)
}
e2.Services = append(e2.Services, exportedSvc)
}
return &e2
}
func (e *ServiceExportsConfigEntry) GetKind() string {
return ServiceExports
}
func (e *ServiceExportsConfigEntry) GetName() string {
if e == nil {
return ""
}
return e.Partition
}
func (e *ServiceExportsConfigEntry) GetMeta() map[string]string {
if e == nil {
return nil
}
return e.Meta
}
func (e *ServiceExportsConfigEntry) Normalize() error {
if e == nil {
return fmt.Errorf("config entry is nil")
}
meta := DefaultEnterpriseMetaInPartition(e.Partition)
e.EnterpriseMeta.Merge(meta)
e.EnterpriseMeta.Normalize()
for i := range e.Services {
e.Services[i].Namespace = NamespaceOrDefault(e.Services[i].Namespace)
}
return nil
}
func (e *ServiceExportsConfigEntry) Validate() error {
if e.Partition == "" {
return fmt.Errorf("Partition is required")
}
if e.Partition == WildcardSpecifier {
return fmt.Errorf("service-exports Partition must be the name of a partition, and not a wildcard")
}
validationErr := validateConfigEntryMeta(e.Meta)
for _, svc := range e.Services {
if svc.Name == "" {
return fmt.Errorf("service name cannot be empty")
}
if len(svc.Consumers) == 0 {
return fmt.Errorf("service %q must have at least one consumer", svc.Name)
}
for _, consumer := range svc.Consumers {
if consumer.Partition == WildcardSpecifier {
return fmt.Errorf("exporting to all partitions (wildcard) is not yet supported")
}
}
}
return validationErr
}
func (e *ServiceExportsConfigEntry) CanRead(authz acl.Authorizer) bool {
var authzContext acl.AuthorizerContext
e.FillAuthzContext(&authzContext)
return authz.MeshRead(&authzContext) == acl.Allow
}
func (e *ServiceExportsConfigEntry) CanWrite(authz acl.Authorizer) bool {
var authzContext acl.AuthorizerContext
e.FillAuthzContext(&authzContext)
return authz.MeshWrite(&authzContext) == acl.Allow
}
func (e *ServiceExportsConfigEntry) GetRaftIndex() *RaftIndex {
if e == nil {
return &RaftIndex{}
}
return &e.RaftIndex
}
func (e *ServiceExportsConfigEntry) GetEnterpriseMeta() *EnterpriseMeta {
if e == nil {
return nil
}
return &e.EnterpriseMeta
}