1package consul
2
3import (
4	"github.com/hashicorp/nomad/client/allocrunner/taskrunner/interfaces"
5	"github.com/hashicorp/nomad/client/taskenv"
6	"github.com/hashicorp/nomad/nomad/mock"
7	"github.com/hashicorp/nomad/nomad/structs"
8	"github.com/hashicorp/nomad/plugins/drivers"
9)
10
11// WorkloadServices describes services defined in either a Task or TaskGroup
12// that need to be syncronized with Consul.
13type WorkloadServices struct {
14	AllocID string
15
16	// Name of the task and task group the services are defined for. For
17	// group based services, Task will be empty.
18	Task  string
19	Group string
20
21	// Canary indicates whether or not the allocation is a canary.
22	Canary bool
23
24	// ConsulNamespace is the consul namespace in which services will be registered.
25	ConsulNamespace string
26
27	// Restarter allows restarting the task or task group depending on the
28	// check_restart stanzas.
29	Restarter WorkloadRestarter
30
31	// Services and checks to register for the task.
32	Services []*structs.Service
33
34	// Networks from the task's resources stanza.
35	// TODO: remove and use Ports
36	Networks structs.Networks
37
38	// NetworkStatus from alloc if network namespace is created.
39	// Can be nil.
40	NetworkStatus *structs.AllocNetworkStatus
41
42	// AllocatedPorts is the list of port mappings.
43	Ports structs.AllocatedPorts
44
45	// DriverExec is the script executor for the task's driver.
46	// For group services this is nil and script execution is managed by
47	// a tasklet in the taskrunner script_check_hook.
48	DriverExec interfaces.ScriptExecutor
49
50	// DriverNetwork is the network specified by the driver and may be nil.
51	DriverNetwork *drivers.DriverNetwork
52}
53
54func BuildAllocServices(node *structs.Node, alloc *structs.Allocation, restarter WorkloadRestarter) *WorkloadServices {
55
56	//TODO(schmichael) only support one network for now
57	net := alloc.AllocatedResources.Shared.Networks[0]
58
59	tg := alloc.Job.LookupTaskGroup(alloc.TaskGroup)
60
61	ws := &WorkloadServices{
62		AllocID:  alloc.ID,
63		Group:    alloc.TaskGroup,
64		Services: taskenv.InterpolateServices(taskenv.NewBuilder(mock.Node(), alloc, nil, alloc.Job.Region).Build(), tg.Services),
65		Networks: alloc.AllocatedResources.Shared.Networks,
66
67		//TODO(schmichael) there's probably a better way than hacking driver network
68		DriverNetwork: &drivers.DriverNetwork{
69			AutoAdvertise: true,
70			IP:            net.IP,
71			// Copy PortLabels from group network
72			PortMap: net.PortLabels(),
73		},
74
75		Restarter:  restarter,
76		DriverExec: nil,
77	}
78
79	if alloc.DeploymentStatus != nil {
80		ws.Canary = alloc.DeploymentStatus.Canary
81	}
82
83	return ws
84}
85
86// Copy method for easing tests
87func (ws *WorkloadServices) Copy() *WorkloadServices {
88	newTS := new(WorkloadServices)
89	*newTS = *ws
90
91	// Deep copy Services
92	newTS.Services = make([]*structs.Service, len(ws.Services))
93	for i := range ws.Services {
94		newTS.Services[i] = ws.Services[i].Copy()
95	}
96	return newTS
97}
98
99func (ws *WorkloadServices) Name() string {
100	if ws.Task != "" {
101		return ws.Task
102	}
103
104	return "group-" + ws.Group
105}
106