1package state
2
3import (
4	"encoding/json"
5	"fmt"
6	"strings"
7
8	"github.com/hashicorp/nomad/client/allocrunner/taskrunner/state"
9	"github.com/hashicorp/nomad/helper/uuid"
10	"github.com/hashicorp/nomad/nomad/structs"
11	"github.com/hashicorp/nomad/plugins/drivers"
12	pstructs "github.com/hashicorp/nomad/plugins/shared/structs"
13)
14
15// allocRunnerMutableState08 is state that had to be written on each save as it
16// changed over the life-cycle of the alloc_runner in Nomad 0.8.
17//
18// https://github.com/hashicorp/nomad/blob/v0.8.6/client/alloc_runner.go#L146-L153
19//
20type allocRunnerMutableState08 struct {
21	// AllocClientStatus does not need to be upgraded as it is computed
22	// from task states.
23	AllocClientStatus string
24
25	// AllocClientDescription does not need to be upgraded as it is computed
26	// from task states.
27	AllocClientDescription string
28
29	TaskStates       map[string]*structs.TaskState
30	DeploymentStatus *structs.AllocDeploymentStatus
31}
32
33// taskRunnerState08 was used to snapshot the state of the task runner in Nomad
34// 0.8.
35//
36// https://github.com/hashicorp/nomad/blob/v0.8.6/client/task_runner.go#L188-L197
37// COMPAT(0.10): Allows upgrading from 0.8.X to 0.9.0.
38type taskRunnerState08 struct {
39	Version            string
40	HandleID           string
41	ArtifactDownloaded bool
42	TaskDirBuilt       bool
43	PayloadRendered    bool
44	DriverNetwork      *drivers.DriverNetwork
45	// Created Resources are no longer used.
46	//CreatedResources   *driver.CreatedResources
47}
48
49type TaskRunnerHandle08 struct {
50	// Docker specific handle info
51	ContainerID string `json:"ContainerID"`
52	Image       string `json:"Image"`
53
54	// LXC specific handle info
55	ContainerName string `json:"ContainerName"`
56	LxcPath       string `json:"LxcPath"`
57
58	// Executor reattach config
59	PluginConfig struct {
60		Pid      int    `json:"Pid"`
61		AddrNet  string `json:"AddrNet"`
62		AddrName string `json:"AddrName"`
63	} `json:"PluginConfig"`
64}
65
66func (t *TaskRunnerHandle08) ReattachConfig() *pstructs.ReattachConfig {
67	return &pstructs.ReattachConfig{
68		Network: t.PluginConfig.AddrNet,
69		Addr:    t.PluginConfig.AddrName,
70		Pid:     t.PluginConfig.Pid,
71	}
72}
73
74func (t *taskRunnerState08) Upgrade(allocID, taskName string) (*state.LocalState, error) {
75	ls := state.NewLocalState()
76
77	// Reuse DriverNetwork
78	ls.DriverNetwork = t.DriverNetwork
79
80	// Upgrade artifact state
81	ls.Hooks["artifacts"] = &state.HookState{
82		PrestartDone: t.ArtifactDownloaded,
83	}
84
85	// Upgrade task dir state
86	ls.Hooks["task_dir"] = &state.HookState{
87		Data: map[string]string{
88			// "is_done" is equivalent to task_dir_hook.TaskDirHookIsDoneKey
89			// Does not import to avoid import cycle
90			"is_done": fmt.Sprintf("%v", t.TaskDirBuilt),
91		},
92	}
93
94	// Upgrade dispatch payload state
95	ls.Hooks["dispatch_payload"] = &state.HookState{
96		PrestartDone: t.PayloadRendered,
97	}
98
99	// Add necessary fields to TaskConfig
100	ls.TaskHandle = drivers.NewTaskHandle(drivers.Pre09TaskHandleVersion)
101	ls.TaskHandle.Config = &drivers.TaskConfig{
102		ID:      fmt.Sprintf("pre09-%s", uuid.Generate()),
103		Name:    taskName,
104		AllocID: allocID,
105	}
106
107	ls.TaskHandle.State = drivers.TaskStateUnknown
108
109	// The docker driver prefixed the handle with 'DOCKER:'
110	// Strip so that it can be unmarshalled
111	data := strings.TrimPrefix(t.HandleID, "DOCKER:")
112
113	// The pre09 driver handle ID is given to the driver. It is unmarshalled
114	// here to check for errors
115	if _, err := UnmarshalPre09HandleID([]byte(data)); err != nil {
116		return nil, err
117	}
118
119	ls.TaskHandle.DriverState = []byte(data)
120
121	return ls, nil
122}
123
124// UnmarshalPre09HandleID decodes the pre09 json encoded handle ID
125func UnmarshalPre09HandleID(raw []byte) (*TaskRunnerHandle08, error) {
126	var handle TaskRunnerHandle08
127	if err := json.Unmarshal(raw, &handle); err != nil {
128		return nil, fmt.Errorf("failed to decode 0.8 driver state: %v", err)
129	}
130
131	return &handle, nil
132}
133