github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/nomad/mock/mock.go (about)

     1  package mock
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"github.com/hashicorp/nomad/helper"
     8  	"github.com/hashicorp/nomad/helper/envoy"
     9  	"github.com/hashicorp/nomad/helper/uuid"
    10  	"github.com/hashicorp/nomad/nomad/structs"
    11  	psstructs "github.com/hashicorp/nomad/plugins/shared/structs"
    12  )
    13  
    14  func Node() *structs.Node {
    15  	node := &structs.Node{
    16  		ID:         uuid.Generate(),
    17  		SecretID:   uuid.Generate(),
    18  		Datacenter: "dc1",
    19  		Name:       "foobar",
    20  		Drivers: map[string]*structs.DriverInfo{
    21  			"exec": {
    22  				Detected: true,
    23  				Healthy:  true,
    24  			},
    25  			"mock_driver": {
    26  				Detected: true,
    27  				Healthy:  true,
    28  			},
    29  		},
    30  		Attributes: map[string]string{
    31  			"kernel.name":        "linux",
    32  			"arch":               "x86",
    33  			"nomad.version":      "0.5.0",
    34  			"driver.exec":        "1",
    35  			"driver.mock_driver": "1",
    36  		},
    37  
    38  		// TODO Remove once clientv2 gets merged
    39  		Resources: &structs.Resources{
    40  			CPU:      4000,
    41  			MemoryMB: 8192,
    42  			DiskMB:   100 * 1024,
    43  		},
    44  		Reserved: &structs.Resources{
    45  			CPU:      100,
    46  			MemoryMB: 256,
    47  			DiskMB:   4 * 1024,
    48  			Networks: []*structs.NetworkResource{
    49  				{
    50  					Device:        "eth0",
    51  					IP:            "192.168.0.100",
    52  					ReservedPorts: []structs.Port{{Label: "ssh", Value: 22}},
    53  					MBits:         1,
    54  				},
    55  			},
    56  		},
    57  
    58  		NodeResources: &structs.NodeResources{
    59  			Cpu: structs.NodeCpuResources{
    60  				CpuShares: 4000,
    61  			},
    62  			Memory: structs.NodeMemoryResources{
    63  				MemoryMB: 8192,
    64  			},
    65  			Disk: structs.NodeDiskResources{
    66  				DiskMB: 100 * 1024,
    67  			},
    68  			Networks: []*structs.NetworkResource{
    69  				{
    70  					Mode:   "host",
    71  					Device: "eth0",
    72  					CIDR:   "192.168.0.100/32",
    73  					MBits:  1000,
    74  				},
    75  			},
    76  			NodeNetworks: []*structs.NodeNetworkResource{
    77  				{
    78  					Mode:   "host",
    79  					Device: "eth0",
    80  					Speed:  1000,
    81  					Addresses: []structs.NodeNetworkAddress{
    82  						{
    83  							Alias:   "default",
    84  							Address: "192.168.0.100",
    85  							Family:  structs.NodeNetworkAF_IPv4,
    86  						},
    87  					},
    88  				},
    89  			},
    90  		},
    91  		ReservedResources: &structs.NodeReservedResources{
    92  			Cpu: structs.NodeReservedCpuResources{
    93  				CpuShares: 100,
    94  			},
    95  			Memory: structs.NodeReservedMemoryResources{
    96  				MemoryMB: 256,
    97  			},
    98  			Disk: structs.NodeReservedDiskResources{
    99  				DiskMB: 4 * 1024,
   100  			},
   101  			Networks: structs.NodeReservedNetworkResources{
   102  				ReservedHostPorts: "22",
   103  			},
   104  		},
   105  		Links: map[string]string{
   106  			"consul": "foobar.dc1",
   107  		},
   108  		Meta: map[string]string{
   109  			"pci-dss":  "true",
   110  			"database": "mysql",
   111  			"version":  "5.6",
   112  		},
   113  		NodeClass:             "linux-medium-pci",
   114  		Status:                structs.NodeStatusReady,
   115  		SchedulingEligibility: structs.NodeSchedulingEligible,
   116  	}
   117  	node.ComputeClass()
   118  	return node
   119  }
   120  
   121  // NvidiaNode returns a node with two instances of an Nvidia GPU
   122  func NvidiaNode() *structs.Node {
   123  	n := Node()
   124  	n.NodeResources.Devices = []*structs.NodeDeviceResource{
   125  		{
   126  			Type:   "gpu",
   127  			Vendor: "nvidia",
   128  			Name:   "1080ti",
   129  			Attributes: map[string]*psstructs.Attribute{
   130  				"memory":           psstructs.NewIntAttribute(11, psstructs.UnitGiB),
   131  				"cuda_cores":       psstructs.NewIntAttribute(3584, ""),
   132  				"graphics_clock":   psstructs.NewIntAttribute(1480, psstructs.UnitMHz),
   133  				"memory_bandwidth": psstructs.NewIntAttribute(11, psstructs.UnitGBPerS),
   134  			},
   135  			Instances: []*structs.NodeDevice{
   136  				{
   137  					ID:      uuid.Generate(),
   138  					Healthy: true,
   139  				},
   140  				{
   141  					ID:      uuid.Generate(),
   142  					Healthy: true,
   143  				},
   144  			},
   145  		},
   146  	}
   147  	n.ComputeClass()
   148  	return n
   149  }
   150  
   151  func HCL() string {
   152  	return `job "my-job" {
   153  	datacenters = ["dc1"]
   154  	type = "service"
   155  	constraint {
   156  		attribute = "${attr.kernel.name}"
   157  		value = "linux"
   158  	}
   159  
   160  	group "web" {
   161  		count = 10
   162  		restart {
   163  			attempts = 3
   164  			interval = "10m"
   165  			delay = "1m"
   166  			mode = "delay"
   167  		}
   168  		task "web" {
   169  			driver = "exec"
   170  			config {
   171  				command = "/bin/date"
   172  			}
   173  			resources {
   174  				cpu = 500
   175  				memory = 256
   176  			}
   177  		}
   178  	}
   179  }
   180  `
   181  }
   182  
   183  func Job() *structs.Job {
   184  	job := &structs.Job{
   185  		Region:      "global",
   186  		ID:          fmt.Sprintf("mock-service-%s", uuid.Generate()),
   187  		Name:        "my-job",
   188  		Namespace:   structs.DefaultNamespace,
   189  		Type:        structs.JobTypeService,
   190  		Priority:    50,
   191  		AllAtOnce:   false,
   192  		Datacenters: []string{"dc1"},
   193  		Constraints: []*structs.Constraint{
   194  			{
   195  				LTarget: "${attr.kernel.name}",
   196  				RTarget: "linux",
   197  				Operand: "=",
   198  			},
   199  		},
   200  		TaskGroups: []*structs.TaskGroup{
   201  			{
   202  				Name:  "web",
   203  				Count: 10,
   204  				EphemeralDisk: &structs.EphemeralDisk{
   205  					SizeMB: 150,
   206  				},
   207  				RestartPolicy: &structs.RestartPolicy{
   208  					Attempts: 3,
   209  					Interval: 10 * time.Minute,
   210  					Delay:    1 * time.Minute,
   211  					Mode:     structs.RestartPolicyModeDelay,
   212  				},
   213  				ReschedulePolicy: &structs.ReschedulePolicy{
   214  					Attempts:      2,
   215  					Interval:      10 * time.Minute,
   216  					Delay:         5 * time.Second,
   217  					DelayFunction: "constant",
   218  				},
   219  				Migrate: structs.DefaultMigrateStrategy(),
   220  				Networks: []*structs.NetworkResource{
   221  					{
   222  						Mode: "host",
   223  						DynamicPorts: []structs.Port{
   224  							{Label: "http"},
   225  							{Label: "admin"},
   226  						},
   227  					},
   228  				},
   229  				Tasks: []*structs.Task{
   230  					{
   231  						Name:   "web",
   232  						Driver: "exec",
   233  						Config: map[string]interface{}{
   234  							"command": "/bin/date",
   235  						},
   236  						Env: map[string]string{
   237  							"FOO": "bar",
   238  						},
   239  						Services: []*structs.Service{
   240  							{
   241  								Name:      "${TASK}-frontend",
   242  								PortLabel: "http",
   243  								Tags:      []string{"pci:${meta.pci-dss}", "datacenter:${node.datacenter}"},
   244  								Checks: []*structs.ServiceCheck{
   245  									{
   246  										Name:     "check-table",
   247  										Type:     structs.ServiceCheckScript,
   248  										Command:  "/usr/local/check-table-${meta.database}",
   249  										Args:     []string{"${meta.version}"},
   250  										Interval: 30 * time.Second,
   251  										Timeout:  5 * time.Second,
   252  									},
   253  								},
   254  							},
   255  							{
   256  								Name:      "${TASK}-admin",
   257  								PortLabel: "admin",
   258  							},
   259  						},
   260  						LogConfig: structs.DefaultLogConfig(),
   261  						Resources: &structs.Resources{
   262  							CPU:      500,
   263  							MemoryMB: 256,
   264  						},
   265  						Meta: map[string]string{
   266  							"foo": "bar",
   267  						},
   268  					},
   269  				},
   270  				Meta: map[string]string{
   271  					"elb_check_type":     "http",
   272  					"elb_check_interval": "30s",
   273  					"elb_check_min":      "3",
   274  				},
   275  			},
   276  		},
   277  		Meta: map[string]string{
   278  			"owner": "armon",
   279  		},
   280  		Status:         structs.JobStatusPending,
   281  		Version:        0,
   282  		CreateIndex:    42,
   283  		ModifyIndex:    99,
   284  		JobModifyIndex: 99,
   285  	}
   286  	job.Canonicalize()
   287  	return job
   288  }
   289  
   290  func LifecycleSideTask(resources structs.Resources, i int) *structs.Task {
   291  	return &structs.Task{
   292  		Name:   fmt.Sprintf("side-%d", i),
   293  		Driver: "exec",
   294  		Config: map[string]interface{}{
   295  			"command": "/bin/date",
   296  		},
   297  		Lifecycle: &structs.TaskLifecycleConfig{
   298  			Hook:    structs.TaskLifecycleHookPrestart,
   299  			Sidecar: true,
   300  		},
   301  		LogConfig: structs.DefaultLogConfig(),
   302  		Resources: &resources,
   303  	}
   304  }
   305  
   306  func LifecycleInitTask(resources structs.Resources, i int) *structs.Task {
   307  	return &structs.Task{
   308  		Name:   fmt.Sprintf("init-%d", i),
   309  		Driver: "exec",
   310  		Config: map[string]interface{}{
   311  			"command": "/bin/date",
   312  		},
   313  		Lifecycle: &structs.TaskLifecycleConfig{
   314  			Hook:    structs.TaskLifecycleHookPrestart,
   315  			Sidecar: false,
   316  		},
   317  		LogConfig: structs.DefaultLogConfig(),
   318  		Resources: &resources,
   319  	}
   320  }
   321  
   322  func LifecycleMainTask(resources structs.Resources, i int) *structs.Task {
   323  	return &structs.Task{
   324  		Name:   fmt.Sprintf("main-%d", i),
   325  		Driver: "exec",
   326  		Config: map[string]interface{}{
   327  			"command": "/bin/date",
   328  		},
   329  		LogConfig: structs.DefaultLogConfig(),
   330  		Resources: &resources,
   331  	}
   332  }
   333  func VariableLifecycleJob(resources structs.Resources, main int, init int, side int) *structs.Job {
   334  	tasks := []*structs.Task{}
   335  	for i := 0; i < main; i++ {
   336  		tasks = append(tasks, LifecycleMainTask(resources, i))
   337  	}
   338  	for i := 0; i < init; i++ {
   339  		tasks = append(tasks, LifecycleInitTask(resources, i))
   340  	}
   341  	for i := 0; i < side; i++ {
   342  		tasks = append(tasks, LifecycleSideTask(resources, i))
   343  	}
   344  	job := &structs.Job{
   345  		Region:      "global",
   346  		ID:          fmt.Sprintf("mock-service-%s", uuid.Generate()),
   347  		Name:        "my-job",
   348  		Namespace:   structs.DefaultNamespace,
   349  		Type:        structs.JobTypeService,
   350  		Priority:    50,
   351  		AllAtOnce:   false,
   352  		Datacenters: []string{"dc1"},
   353  		Constraints: []*structs.Constraint{
   354  			{
   355  				LTarget: "${attr.kernel.name}",
   356  				RTarget: "linux",
   357  				Operand: "=",
   358  			},
   359  		},
   360  		TaskGroups: []*structs.TaskGroup{
   361  			{
   362  				Name:  "web",
   363  				Count: 1,
   364  				Tasks: tasks,
   365  			},
   366  		},
   367  		Meta: map[string]string{
   368  			"owner": "armon",
   369  		},
   370  		Status:         structs.JobStatusPending,
   371  		Version:        0,
   372  		CreateIndex:    42,
   373  		ModifyIndex:    99,
   374  		JobModifyIndex: 99,
   375  	}
   376  	job.Canonicalize()
   377  	return job
   378  }
   379  
   380  func LifecycleJob() *structs.Job {
   381  	job := &structs.Job{
   382  		Region:      "global",
   383  		ID:          fmt.Sprintf("mock-service-%s", uuid.Generate()),
   384  		Name:        "my-job",
   385  		Namespace:   structs.DefaultNamespace,
   386  		Type:        structs.JobTypeBatch,
   387  		Priority:    50,
   388  		AllAtOnce:   false,
   389  		Datacenters: []string{"dc1"},
   390  		Constraints: []*structs.Constraint{
   391  			{
   392  				LTarget: "${attr.kernel.name}",
   393  				RTarget: "linux",
   394  				Operand: "=",
   395  			},
   396  		},
   397  		TaskGroups: []*structs.TaskGroup{
   398  			{
   399  				Name:  "web",
   400  				Count: 1,
   401  				RestartPolicy: &structs.RestartPolicy{
   402  					Attempts: 0,
   403  					Interval: 10 * time.Minute,
   404  					Delay:    1 * time.Minute,
   405  					Mode:     structs.RestartPolicyModeFail,
   406  				},
   407  				Tasks: []*structs.Task{
   408  					{
   409  						Name:   "web",
   410  						Driver: "mock_driver",
   411  						Config: map[string]interface{}{
   412  							"run_for": "1s",
   413  						},
   414  						LogConfig: structs.DefaultLogConfig(),
   415  						Resources: &structs.Resources{
   416  							CPU:      1000,
   417  							MemoryMB: 256,
   418  						},
   419  					},
   420  					{
   421  						Name:   "side",
   422  						Driver: "mock_driver",
   423  						Config: map[string]interface{}{
   424  							"run_for": "1s",
   425  						},
   426  						Lifecycle: &structs.TaskLifecycleConfig{
   427  							Hook:    structs.TaskLifecycleHookPrestart,
   428  							Sidecar: true,
   429  						},
   430  						LogConfig: structs.DefaultLogConfig(),
   431  						Resources: &structs.Resources{
   432  							CPU:      1000,
   433  							MemoryMB: 256,
   434  						},
   435  					},
   436  					{
   437  						Name:   "init",
   438  						Driver: "mock_driver",
   439  						Config: map[string]interface{}{
   440  							"run_for": "1s",
   441  						},
   442  						Lifecycle: &structs.TaskLifecycleConfig{
   443  							Hook:    structs.TaskLifecycleHookPrestart,
   444  							Sidecar: false,
   445  						},
   446  						LogConfig: structs.DefaultLogConfig(),
   447  						Resources: &structs.Resources{
   448  							CPU:      1000,
   449  							MemoryMB: 256,
   450  						},
   451  					},
   452  				},
   453  			},
   454  		},
   455  		Meta: map[string]string{
   456  			"owner": "armon",
   457  		},
   458  		Status:         structs.JobStatusPending,
   459  		Version:        0,
   460  		CreateIndex:    42,
   461  		ModifyIndex:    99,
   462  		JobModifyIndex: 99,
   463  	}
   464  	job.Canonicalize()
   465  	return job
   466  }
   467  
   468  func LifecycleAlloc() *structs.Allocation {
   469  	alloc := &structs.Allocation{
   470  		ID:        uuid.Generate(),
   471  		EvalID:    uuid.Generate(),
   472  		NodeID:    "12345678-abcd-efab-cdef-123456789abc",
   473  		Namespace: structs.DefaultNamespace,
   474  		TaskGroup: "web",
   475  
   476  		// TODO Remove once clientv2 gets merged
   477  		Resources: &structs.Resources{
   478  			CPU:      500,
   479  			MemoryMB: 256,
   480  		},
   481  		TaskResources: map[string]*structs.Resources{
   482  			"web": {
   483  				CPU:      1000,
   484  				MemoryMB: 256,
   485  			},
   486  			"init": {
   487  				CPU:      1000,
   488  				MemoryMB: 256,
   489  			},
   490  			"side": {
   491  				CPU:      1000,
   492  				MemoryMB: 256,
   493  			},
   494  		},
   495  
   496  		AllocatedResources: &structs.AllocatedResources{
   497  			Tasks: map[string]*structs.AllocatedTaskResources{
   498  				"web": {
   499  					Cpu: structs.AllocatedCpuResources{
   500  						CpuShares: 1000,
   501  					},
   502  					Memory: structs.AllocatedMemoryResources{
   503  						MemoryMB: 256,
   504  					},
   505  				},
   506  				"init": {
   507  					Cpu: structs.AllocatedCpuResources{
   508  						CpuShares: 1000,
   509  					},
   510  					Memory: structs.AllocatedMemoryResources{
   511  						MemoryMB: 256,
   512  					},
   513  				},
   514  				"side": {
   515  					Cpu: structs.AllocatedCpuResources{
   516  						CpuShares: 1000,
   517  					},
   518  					Memory: structs.AllocatedMemoryResources{
   519  						MemoryMB: 256,
   520  					},
   521  				},
   522  			},
   523  		},
   524  		Job:           LifecycleJob(),
   525  		DesiredStatus: structs.AllocDesiredStatusRun,
   526  		ClientStatus:  structs.AllocClientStatusPending,
   527  	}
   528  	alloc.JobID = alloc.Job.ID
   529  	return alloc
   530  }
   531  
   532  func LifecycleJobWithPoststopDeploy() *structs.Job {
   533  	job := &structs.Job{
   534  		Region:      "global",
   535  		ID:          fmt.Sprintf("mock-service-%s", uuid.Generate()),
   536  		Name:        "my-job",
   537  		Namespace:   structs.DefaultNamespace,
   538  		Type:        structs.JobTypeBatch,
   539  		Priority:    50,
   540  		AllAtOnce:   false,
   541  		Datacenters: []string{"dc1"},
   542  		Constraints: []*structs.Constraint{
   543  			{
   544  				LTarget: "${attr.kernel.name}",
   545  				RTarget: "linux",
   546  				Operand: "=",
   547  			},
   548  		},
   549  		TaskGroups: []*structs.TaskGroup{
   550  			{
   551  				Name:    "web",
   552  				Count:   1,
   553  				Migrate: structs.DefaultMigrateStrategy(),
   554  				RestartPolicy: &structs.RestartPolicy{
   555  					Attempts: 0,
   556  					Interval: 10 * time.Minute,
   557  					Delay:    1 * time.Minute,
   558  					Mode:     structs.RestartPolicyModeFail,
   559  				},
   560  				Tasks: []*structs.Task{
   561  					{
   562  						Name:   "web",
   563  						Driver: "mock_driver",
   564  						Config: map[string]interface{}{
   565  							"run_for": "1s",
   566  						},
   567  						LogConfig: structs.DefaultLogConfig(),
   568  						Resources: &structs.Resources{
   569  							CPU:      1000,
   570  							MemoryMB: 256,
   571  						},
   572  					},
   573  					{
   574  						Name:   "side",
   575  						Driver: "mock_driver",
   576  						Config: map[string]interface{}{
   577  							"run_for": "1s",
   578  						},
   579  						Lifecycle: &structs.TaskLifecycleConfig{
   580  							Hook:    structs.TaskLifecycleHookPrestart,
   581  							Sidecar: true,
   582  						},
   583  						LogConfig: structs.DefaultLogConfig(),
   584  						Resources: &structs.Resources{
   585  							CPU:      1000,
   586  							MemoryMB: 256,
   587  						},
   588  					},
   589  					{
   590  						Name:   "post",
   591  						Driver: "mock_driver",
   592  						Config: map[string]interface{}{
   593  							"run_for": "1s",
   594  						},
   595  						Lifecycle: &structs.TaskLifecycleConfig{
   596  							Hook: structs.TaskLifecycleHookPoststop,
   597  						},
   598  						LogConfig: structs.DefaultLogConfig(),
   599  						Resources: &structs.Resources{
   600  							CPU:      1000,
   601  							MemoryMB: 256,
   602  						},
   603  					},
   604  					{
   605  						Name:   "init",
   606  						Driver: "mock_driver",
   607  						Config: map[string]interface{}{
   608  							"run_for": "1s",
   609  						},
   610  						Lifecycle: &structs.TaskLifecycleConfig{
   611  							Hook:    structs.TaskLifecycleHookPrestart,
   612  							Sidecar: false,
   613  						},
   614  						LogConfig: structs.DefaultLogConfig(),
   615  						Resources: &structs.Resources{
   616  							CPU:      1000,
   617  							MemoryMB: 256,
   618  						},
   619  					},
   620  				},
   621  			},
   622  		},
   623  		Meta: map[string]string{
   624  			"owner": "armon",
   625  		},
   626  		Status:         structs.JobStatusPending,
   627  		Version:        0,
   628  		CreateIndex:    42,
   629  		ModifyIndex:    99,
   630  		JobModifyIndex: 99,
   631  	}
   632  	job.Canonicalize()
   633  	return job
   634  }
   635  
   636  func LifecycleAllocWithPoststopDeploy() *structs.Allocation {
   637  	alloc := &structs.Allocation{
   638  		ID:        uuid.Generate(),
   639  		EvalID:    uuid.Generate(),
   640  		NodeID:    "12345678-abcd-efab-cdef-123456789abc",
   641  		Namespace: structs.DefaultNamespace,
   642  		TaskGroup: "web",
   643  
   644  		// TODO Remove once clientv2 gets merged
   645  		Resources: &structs.Resources{
   646  			CPU:      500,
   647  			MemoryMB: 256,
   648  		},
   649  		TaskResources: map[string]*structs.Resources{
   650  			"web": {
   651  				CPU:      1000,
   652  				MemoryMB: 256,
   653  			},
   654  			"init": {
   655  				CPU:      1000,
   656  				MemoryMB: 256,
   657  			},
   658  			"side": {
   659  				CPU:      1000,
   660  				MemoryMB: 256,
   661  			},
   662  			"post": {
   663  				CPU:      1000,
   664  				MemoryMB: 256,
   665  			},
   666  		},
   667  
   668  		AllocatedResources: &structs.AllocatedResources{
   669  			Tasks: map[string]*structs.AllocatedTaskResources{
   670  				"web": {
   671  					Cpu: structs.AllocatedCpuResources{
   672  						CpuShares: 1000,
   673  					},
   674  					Memory: structs.AllocatedMemoryResources{
   675  						MemoryMB: 256,
   676  					},
   677  				},
   678  				"init": {
   679  					Cpu: structs.AllocatedCpuResources{
   680  						CpuShares: 1000,
   681  					},
   682  					Memory: structs.AllocatedMemoryResources{
   683  						MemoryMB: 256,
   684  					},
   685  				},
   686  				"side": {
   687  					Cpu: structs.AllocatedCpuResources{
   688  						CpuShares: 1000,
   689  					},
   690  					Memory: structs.AllocatedMemoryResources{
   691  						MemoryMB: 256,
   692  					},
   693  				},
   694  				"post": {
   695  					Cpu: structs.AllocatedCpuResources{
   696  						CpuShares: 1000,
   697  					},
   698  					Memory: structs.AllocatedMemoryResources{
   699  						MemoryMB: 256,
   700  					},
   701  				},
   702  			},
   703  		},
   704  		Job:           LifecycleJobWithPoststopDeploy(),
   705  		DesiredStatus: structs.AllocDesiredStatusRun,
   706  		ClientStatus:  structs.AllocClientStatusPending,
   707  	}
   708  	alloc.JobID = alloc.Job.ID
   709  	return alloc
   710  }
   711  
   712  func MaxParallelJob() *structs.Job {
   713  	update := *structs.DefaultUpdateStrategy
   714  	update.MaxParallel = 0
   715  	job := &structs.Job{
   716  		Region:      "global",
   717  		ID:          fmt.Sprintf("mock-service-%s", uuid.Generate()),
   718  		Name:        "my-job",
   719  		Namespace:   structs.DefaultNamespace,
   720  		Type:        structs.JobTypeService,
   721  		Priority:    50,
   722  		AllAtOnce:   false,
   723  		Datacenters: []string{"dc1"},
   724  		Constraints: []*structs.Constraint{
   725  			{
   726  				LTarget: "${attr.kernel.name}",
   727  				RTarget: "linux",
   728  				Operand: "=",
   729  			},
   730  		},
   731  		Update: update,
   732  		TaskGroups: []*structs.TaskGroup{
   733  			{
   734  				Name:  "web",
   735  				Count: 10,
   736  				EphemeralDisk: &structs.EphemeralDisk{
   737  					SizeMB: 150,
   738  				},
   739  				RestartPolicy: &structs.RestartPolicy{
   740  					Attempts: 3,
   741  					Interval: 10 * time.Minute,
   742  					Delay:    1 * time.Minute,
   743  					Mode:     structs.RestartPolicyModeDelay,
   744  				},
   745  				ReschedulePolicy: &structs.ReschedulePolicy{
   746  					Attempts:      2,
   747  					Interval:      10 * time.Minute,
   748  					Delay:         5 * time.Second,
   749  					DelayFunction: "constant",
   750  				},
   751  				Migrate: structs.DefaultMigrateStrategy(),
   752  				Update:  &update,
   753  				Tasks: []*structs.Task{
   754  					{
   755  						Name:   "web",
   756  						Driver: "exec",
   757  						Config: map[string]interface{}{
   758  							"command": "/bin/date",
   759  						},
   760  						Env: map[string]string{
   761  							"FOO": "bar",
   762  						},
   763  						Services: []*structs.Service{
   764  							{
   765  								Name:      "${TASK}-frontend",
   766  								PortLabel: "http",
   767  								Tags:      []string{"pci:${meta.pci-dss}", "datacenter:${node.datacenter}"},
   768  								Checks: []*structs.ServiceCheck{
   769  									{
   770  										Name:     "check-table",
   771  										Type:     structs.ServiceCheckScript,
   772  										Command:  "/usr/local/check-table-${meta.database}",
   773  										Args:     []string{"${meta.version}"},
   774  										Interval: 30 * time.Second,
   775  										Timeout:  5 * time.Second,
   776  									},
   777  								},
   778  							},
   779  							{
   780  								Name:      "${TASK}-admin",
   781  								PortLabel: "admin",
   782  							},
   783  						},
   784  						LogConfig: structs.DefaultLogConfig(),
   785  						Resources: &structs.Resources{
   786  							CPU:      500,
   787  							MemoryMB: 256,
   788  							Networks: []*structs.NetworkResource{
   789  								{
   790  									MBits: 50,
   791  									DynamicPorts: []structs.Port{
   792  										{Label: "http"},
   793  										{Label: "admin"},
   794  									},
   795  								},
   796  							},
   797  						},
   798  						Meta: map[string]string{
   799  							"foo": "bar",
   800  						},
   801  					},
   802  				},
   803  				Meta: map[string]string{
   804  					"elb_check_type":     "http",
   805  					"elb_check_interval": "30s",
   806  					"elb_check_min":      "3",
   807  				},
   808  			},
   809  		},
   810  		Meta: map[string]string{
   811  			"owner": "armon",
   812  		},
   813  		Status:         structs.JobStatusPending,
   814  		Version:        0,
   815  		CreateIndex:    42,
   816  		ModifyIndex:    99,
   817  		JobModifyIndex: 99,
   818  	}
   819  	job.Canonicalize()
   820  	return job
   821  }
   822  
   823  // ConnectJob adds a Connect proxy sidecar group service to mock.Job.
   824  //
   825  // Note this does *not* include the Job.Register mutation that inserts the
   826  // associated Sidecar Task (nor the hook that configures envoy as the default).
   827  func ConnectJob() *structs.Job {
   828  	job := Job()
   829  	tg := job.TaskGroups[0]
   830  	tg.Services = []*structs.Service{{
   831  		Name:      "testconnect",
   832  		PortLabel: "9999",
   833  		Connect: &structs.ConsulConnect{
   834  			SidecarService: new(structs.ConsulSidecarService),
   835  		},
   836  	}}
   837  	tg.Networks = structs.Networks{{
   838  		Mode: "bridge", // always bridge ... for now?
   839  	}}
   840  	return job
   841  }
   842  
   843  func ConnectNativeJob(mode string) *structs.Job {
   844  	job := Job()
   845  	tg := job.TaskGroups[0]
   846  	tg.Networks = []*structs.NetworkResource{{
   847  		Mode: mode,
   848  	}}
   849  	tg.Services = []*structs.Service{{
   850  		Name:      "test_connect_native",
   851  		PortLabel: "9999",
   852  		Connect: &structs.ConsulConnect{
   853  			Native: true,
   854  		},
   855  	}}
   856  	tg.Tasks = []*structs.Task{{
   857  		Name: "native_task",
   858  	}}
   859  	return job
   860  }
   861  
   862  // ConnectIngressGatewayJob creates a structs.Job that contains the definition
   863  // of a Consul Ingress Gateway service. The mode is the name of the network
   864  // mode assumed by the task group. If inject is true, a corresponding Task is
   865  // set on the group's Tasks (i.e. what the job would look like after job mutation).
   866  func ConnectIngressGatewayJob(mode string, inject bool) *structs.Job {
   867  	job := Job()
   868  	tg := job.TaskGroups[0]
   869  	tg.Networks = []*structs.NetworkResource{{
   870  		Mode: mode,
   871  	}}
   872  	tg.Services = []*structs.Service{{
   873  		Name:      "my-ingress-service",
   874  		PortLabel: "9999",
   875  		Connect: &structs.ConsulConnect{
   876  			Gateway: &structs.ConsulGateway{
   877  				Proxy: &structs.ConsulGatewayProxy{
   878  					ConnectTimeout:            helper.TimeToPtr(3 * time.Second),
   879  					EnvoyGatewayBindAddresses: make(map[string]*structs.ConsulGatewayBindAddress),
   880  				},
   881  				Ingress: &structs.ConsulIngressConfigEntry{
   882  					Listeners: []*structs.ConsulIngressListener{{
   883  						Port:     2000,
   884  						Protocol: "tcp",
   885  						Services: []*structs.ConsulIngressService{{
   886  							Name: "service1",
   887  						}},
   888  					}},
   889  				},
   890  			},
   891  		},
   892  	}}
   893  	// some tests need to assume the gateway proxy task has already been injected
   894  	if inject {
   895  		tg.Tasks = []*structs.Task{{
   896  			Name:          fmt.Sprintf("%s-%s", structs.ConnectIngressPrefix, "my-ingress-service"),
   897  			Kind:          structs.NewTaskKind(structs.ConnectIngressPrefix, "my-ingress-service"),
   898  			Driver:        "docker",
   899  			Config:        make(map[string]interface{}),
   900  			ShutdownDelay: 5 * time.Second,
   901  			LogConfig: &structs.LogConfig{
   902  				MaxFiles:      2,
   903  				MaxFileSizeMB: 2,
   904  			},
   905  		}}
   906  	} else {
   907  		// otherwise there are no tasks in the group yet
   908  		tg.Tasks = nil
   909  	}
   910  	return job
   911  }
   912  
   913  func ConnectSidecarTask() *structs.Task {
   914  	return &structs.Task{
   915  		Name:   "mysidecar-sidecar-task",
   916  		Driver: "docker",
   917  		User:   "nobody",
   918  		Config: map[string]interface{}{
   919  			"image": envoy.SidecarConfigVar,
   920  		},
   921  		Env: nil,
   922  		Resources: &structs.Resources{
   923  			CPU:      150,
   924  			MemoryMB: 350,
   925  		},
   926  		Kind: structs.NewTaskKind(structs.ConnectProxyPrefix, "mysidecar"),
   927  	}
   928  }
   929  
   930  func BatchJob() *structs.Job {
   931  	job := &structs.Job{
   932  		Region:      "global",
   933  		ID:          fmt.Sprintf("mock-batch-%s", uuid.Generate()),
   934  		Name:        "batch-job",
   935  		Namespace:   structs.DefaultNamespace,
   936  		Type:        structs.JobTypeBatch,
   937  		Priority:    50,
   938  		AllAtOnce:   false,
   939  		Datacenters: []string{"dc1"},
   940  		TaskGroups: []*structs.TaskGroup{
   941  			{
   942  				Name:  "web",
   943  				Count: 10,
   944  				EphemeralDisk: &structs.EphemeralDisk{
   945  					SizeMB: 150,
   946  				},
   947  				RestartPolicy: &structs.RestartPolicy{
   948  					Attempts: 3,
   949  					Interval: 10 * time.Minute,
   950  					Delay:    1 * time.Minute,
   951  					Mode:     structs.RestartPolicyModeDelay,
   952  				},
   953  				ReschedulePolicy: &structs.ReschedulePolicy{
   954  					Attempts:      2,
   955  					Interval:      10 * time.Minute,
   956  					Delay:         5 * time.Second,
   957  					DelayFunction: "constant",
   958  				},
   959  				Tasks: []*structs.Task{
   960  					{
   961  						Name:   "web",
   962  						Driver: "mock_driver",
   963  						Config: map[string]interface{}{
   964  							"run_for": "500ms",
   965  						},
   966  						Env: map[string]string{
   967  							"FOO": "bar",
   968  						},
   969  						LogConfig: structs.DefaultLogConfig(),
   970  						Resources: &structs.Resources{
   971  							CPU:      100,
   972  							MemoryMB: 100,
   973  							Networks: []*structs.NetworkResource{
   974  								{
   975  									MBits: 50,
   976  								},
   977  							},
   978  						},
   979  						Meta: map[string]string{
   980  							"foo": "bar",
   981  						},
   982  					},
   983  				},
   984  			},
   985  		},
   986  		Status:         structs.JobStatusPending,
   987  		Version:        0,
   988  		CreateIndex:    43,
   989  		ModifyIndex:    99,
   990  		JobModifyIndex: 99,
   991  	}
   992  	job.Canonicalize()
   993  	return job
   994  }
   995  
   996  func SystemJob() *structs.Job {
   997  	job := &structs.Job{
   998  		Region:      "global",
   999  		Namespace:   structs.DefaultNamespace,
  1000  		ID:          fmt.Sprintf("mock-system-%s", uuid.Generate()),
  1001  		Name:        "my-job",
  1002  		Type:        structs.JobTypeSystem,
  1003  		Priority:    100,
  1004  		AllAtOnce:   false,
  1005  		Datacenters: []string{"dc1"},
  1006  		Constraints: []*structs.Constraint{
  1007  			{
  1008  				LTarget: "${attr.kernel.name}",
  1009  				RTarget: "linux",
  1010  				Operand: "=",
  1011  			},
  1012  		},
  1013  		TaskGroups: []*structs.TaskGroup{
  1014  			{
  1015  				Name:  "web",
  1016  				Count: 1,
  1017  				RestartPolicy: &structs.RestartPolicy{
  1018  					Attempts: 3,
  1019  					Interval: 10 * time.Minute,
  1020  					Delay:    1 * time.Minute,
  1021  					Mode:     structs.RestartPolicyModeDelay,
  1022  				},
  1023  				EphemeralDisk: structs.DefaultEphemeralDisk(),
  1024  				Tasks: []*structs.Task{
  1025  					{
  1026  						Name:   "web",
  1027  						Driver: "exec",
  1028  						Config: map[string]interface{}{
  1029  							"command": "/bin/date",
  1030  						},
  1031  						Env: map[string]string{},
  1032  						Resources: &structs.Resources{
  1033  							CPU:      500,
  1034  							MemoryMB: 256,
  1035  							Networks: []*structs.NetworkResource{
  1036  								{
  1037  									MBits:        50,
  1038  									DynamicPorts: []structs.Port{{Label: "http"}},
  1039  								},
  1040  							},
  1041  						},
  1042  						LogConfig: structs.DefaultLogConfig(),
  1043  					},
  1044  				},
  1045  			},
  1046  		},
  1047  		Meta: map[string]string{
  1048  			"owner": "armon",
  1049  		},
  1050  		Status:      structs.JobStatusPending,
  1051  		CreateIndex: 42,
  1052  		ModifyIndex: 99,
  1053  	}
  1054  	job.Canonicalize()
  1055  	return job
  1056  }
  1057  
  1058  func PeriodicJob() *structs.Job {
  1059  	job := Job()
  1060  	job.Type = structs.JobTypeBatch
  1061  	job.Periodic = &structs.PeriodicConfig{
  1062  		Enabled:  true,
  1063  		SpecType: structs.PeriodicSpecCron,
  1064  		Spec:     "*/30 * * * *",
  1065  	}
  1066  	job.Status = structs.JobStatusRunning
  1067  	job.TaskGroups[0].Migrate = nil
  1068  	return job
  1069  }
  1070  
  1071  func Eval() *structs.Evaluation {
  1072  	now := time.Now().UTC().UnixNano()
  1073  	eval := &structs.Evaluation{
  1074  		ID:         uuid.Generate(),
  1075  		Namespace:  structs.DefaultNamespace,
  1076  		Priority:   50,
  1077  		Type:       structs.JobTypeService,
  1078  		JobID:      uuid.Generate(),
  1079  		Status:     structs.EvalStatusPending,
  1080  		CreateTime: now,
  1081  		ModifyTime: now,
  1082  	}
  1083  	return eval
  1084  }
  1085  
  1086  func JobSummary(jobID string) *structs.JobSummary {
  1087  	js := &structs.JobSummary{
  1088  		JobID:     jobID,
  1089  		Namespace: structs.DefaultNamespace,
  1090  		Summary: map[string]structs.TaskGroupSummary{
  1091  			"web": {
  1092  				Queued:   0,
  1093  				Starting: 0,
  1094  			},
  1095  		},
  1096  	}
  1097  	return js
  1098  }
  1099  
  1100  func Alloc() *structs.Allocation {
  1101  	alloc := &structs.Allocation{
  1102  		ID:        uuid.Generate(),
  1103  		EvalID:    uuid.Generate(),
  1104  		NodeID:    "12345678-abcd-efab-cdef-123456789abc",
  1105  		Namespace: structs.DefaultNamespace,
  1106  		TaskGroup: "web",
  1107  
  1108  		// TODO Remove once clientv2 gets merged
  1109  		Resources: &structs.Resources{
  1110  			CPU:      500,
  1111  			MemoryMB: 256,
  1112  			DiskMB:   150,
  1113  			Networks: []*structs.NetworkResource{
  1114  				{
  1115  					Device:        "eth0",
  1116  					IP:            "192.168.0.100",
  1117  					ReservedPorts: []structs.Port{{Label: "admin", Value: 5000}},
  1118  					MBits:         50,
  1119  					DynamicPorts:  []structs.Port{{Label: "http"}},
  1120  				},
  1121  			},
  1122  		},
  1123  		TaskResources: map[string]*structs.Resources{
  1124  			"web": {
  1125  				CPU:      500,
  1126  				MemoryMB: 256,
  1127  				Networks: []*structs.NetworkResource{
  1128  					{
  1129  						Device:        "eth0",
  1130  						IP:            "192.168.0.100",
  1131  						ReservedPorts: []structs.Port{{Label: "admin", Value: 5000}},
  1132  						MBits:         50,
  1133  						DynamicPorts:  []structs.Port{{Label: "http", Value: 9876}},
  1134  					},
  1135  				},
  1136  			},
  1137  		},
  1138  		SharedResources: &structs.Resources{
  1139  			DiskMB: 150,
  1140  		},
  1141  
  1142  		AllocatedResources: &structs.AllocatedResources{
  1143  			Tasks: map[string]*structs.AllocatedTaskResources{
  1144  				"web": {
  1145  					Cpu: structs.AllocatedCpuResources{
  1146  						CpuShares: 500,
  1147  					},
  1148  					Memory: structs.AllocatedMemoryResources{
  1149  						MemoryMB: 256,
  1150  					},
  1151  					Networks: []*structs.NetworkResource{
  1152  						{
  1153  							Device:        "eth0",
  1154  							IP:            "192.168.0.100",
  1155  							ReservedPorts: []structs.Port{{Label: "admin", Value: 5000}},
  1156  							MBits:         50,
  1157  							DynamicPorts:  []structs.Port{{Label: "http", Value: 9876}},
  1158  						},
  1159  					},
  1160  				},
  1161  			},
  1162  			Shared: structs.AllocatedSharedResources{
  1163  				DiskMB: 150,
  1164  			},
  1165  		},
  1166  		Job:           Job(),
  1167  		DesiredStatus: structs.AllocDesiredStatusRun,
  1168  		ClientStatus:  structs.AllocClientStatusPending,
  1169  	}
  1170  	alloc.JobID = alloc.Job.ID
  1171  	return alloc
  1172  }
  1173  
  1174  // ConnectJob adds a Connect proxy sidecar group service to mock.Alloc.
  1175  func ConnectAlloc() *structs.Allocation {
  1176  	alloc := Alloc()
  1177  	alloc.Job = ConnectJob()
  1178  	alloc.AllocatedResources.Shared.Networks = []*structs.NetworkResource{
  1179  		{
  1180  			Mode: "bridge",
  1181  			IP:   "10.0.0.1",
  1182  			DynamicPorts: []structs.Port{
  1183  				{
  1184  					Label: "connect-proxy-testconnect",
  1185  					Value: 9999,
  1186  					To:    9999,
  1187  				},
  1188  			},
  1189  		},
  1190  	}
  1191  	return alloc
  1192  }
  1193  
  1194  // ConnectNativeAlloc creates an alloc with a connect native task.
  1195  func ConnectNativeAlloc(mode string) *structs.Allocation {
  1196  	alloc := Alloc()
  1197  	alloc.Job = ConnectNativeJob(mode)
  1198  	alloc.AllocatedResources.Shared.Networks = []*structs.NetworkResource{{
  1199  		Mode: mode,
  1200  		IP:   "10.0.0.1",
  1201  	}}
  1202  	return alloc
  1203  }
  1204  
  1205  func ConnectIngressGatewayAlloc(mode string) *structs.Allocation {
  1206  	alloc := Alloc()
  1207  	alloc.Job = ConnectIngressGatewayJob(mode, true)
  1208  	alloc.AllocatedResources.Shared.Networks = []*structs.NetworkResource{{
  1209  		Mode: mode,
  1210  		IP:   "10.0.0.1",
  1211  	}}
  1212  	return alloc
  1213  }
  1214  
  1215  func BatchConnectJob() *structs.Job {
  1216  	job := &structs.Job{
  1217  		Region:      "global",
  1218  		ID:          fmt.Sprintf("mock-connect-batch-job%s", uuid.Generate()),
  1219  		Name:        "mock-connect-batch-job",
  1220  		Namespace:   structs.DefaultNamespace,
  1221  		Type:        structs.JobTypeBatch,
  1222  		Priority:    50,
  1223  		AllAtOnce:   false,
  1224  		Datacenters: []string{"dc1"},
  1225  		TaskGroups: []*structs.TaskGroup{{
  1226  			Name:          "mock-connect-batch-job",
  1227  			Count:         1,
  1228  			EphemeralDisk: &structs.EphemeralDisk{SizeMB: 150},
  1229  			Networks: []*structs.NetworkResource{{
  1230  				Mode: "bridge",
  1231  			}},
  1232  			Tasks: []*structs.Task{{
  1233  				Name:   "connect-proxy-testconnect",
  1234  				Kind:   "connect-proxy:testconnect",
  1235  				Driver: "mock_driver",
  1236  				Config: map[string]interface{}{
  1237  					"run_for": "500ms",
  1238  				},
  1239  				LogConfig: structs.DefaultLogConfig(),
  1240  				Resources: &structs.Resources{
  1241  					CPU:      500,
  1242  					MemoryMB: 256,
  1243  					Networks: []*structs.NetworkResource{{
  1244  						MBits:        50,
  1245  						DynamicPorts: []structs.Port{{Label: "port1"}},
  1246  					}},
  1247  				},
  1248  			}},
  1249  			Services: []*structs.Service{{
  1250  				Name: "testconnect",
  1251  			}},
  1252  		}},
  1253  		Meta:           map[string]string{"owner": "shoenig"},
  1254  		Status:         structs.JobStatusPending,
  1255  		Version:        0,
  1256  		CreateIndex:    42,
  1257  		ModifyIndex:    99,
  1258  		JobModifyIndex: 99,
  1259  	}
  1260  	job.Canonicalize()
  1261  	return job
  1262  }
  1263  
  1264  // BatchConnectAlloc is useful for testing task runner things.
  1265  func BatchConnectAlloc() *structs.Allocation {
  1266  	alloc := &structs.Allocation{
  1267  		ID:        uuid.Generate(),
  1268  		EvalID:    uuid.Generate(),
  1269  		NodeID:    "12345678-abcd-efab-cdef-123456789abc",
  1270  		Namespace: structs.DefaultNamespace,
  1271  		TaskGroup: "mock-connect-batch-job",
  1272  		TaskResources: map[string]*structs.Resources{
  1273  			"connect-proxy-testconnect": {
  1274  				CPU:      500,
  1275  				MemoryMB: 256,
  1276  			},
  1277  		},
  1278  
  1279  		AllocatedResources: &structs.AllocatedResources{
  1280  			Tasks: map[string]*structs.AllocatedTaskResources{
  1281  				"connect-proxy-testconnect": {
  1282  					Cpu:    structs.AllocatedCpuResources{CpuShares: 500},
  1283  					Memory: structs.AllocatedMemoryResources{MemoryMB: 256},
  1284  				},
  1285  			},
  1286  			Shared: structs.AllocatedSharedResources{
  1287  				Networks: []*structs.NetworkResource{{
  1288  					Mode: "bridge",
  1289  					IP:   "10.0.0.1",
  1290  					DynamicPorts: []structs.Port{{
  1291  						Label: "connect-proxy-testconnect",
  1292  						Value: 9999,
  1293  						To:    9999,
  1294  					}},
  1295  				}},
  1296  				DiskMB: 0,
  1297  			},
  1298  		},
  1299  		Job:           BatchConnectJob(),
  1300  		DesiredStatus: structs.AllocDesiredStatusRun,
  1301  		ClientStatus:  structs.AllocClientStatusPending,
  1302  	}
  1303  	alloc.JobID = alloc.Job.ID
  1304  	return alloc
  1305  }
  1306  
  1307  func BatchAlloc() *structs.Allocation {
  1308  	alloc := &structs.Allocation{
  1309  		ID:        uuid.Generate(),
  1310  		EvalID:    uuid.Generate(),
  1311  		NodeID:    "12345678-abcd-efab-cdef-123456789abc",
  1312  		Namespace: structs.DefaultNamespace,
  1313  		TaskGroup: "web",
  1314  
  1315  		// TODO Remove once clientv2 gets merged
  1316  		Resources: &structs.Resources{
  1317  			CPU:      500,
  1318  			MemoryMB: 256,
  1319  			DiskMB:   150,
  1320  			Networks: []*structs.NetworkResource{
  1321  				{
  1322  					Device:        "eth0",
  1323  					IP:            "192.168.0.100",
  1324  					ReservedPorts: []structs.Port{{Label: "admin", Value: 5000}},
  1325  					MBits:         50,
  1326  					DynamicPorts:  []structs.Port{{Label: "http"}},
  1327  				},
  1328  			},
  1329  		},
  1330  		TaskResources: map[string]*structs.Resources{
  1331  			"web": {
  1332  				CPU:      500,
  1333  				MemoryMB: 256,
  1334  				Networks: []*structs.NetworkResource{
  1335  					{
  1336  						Device:        "eth0",
  1337  						IP:            "192.168.0.100",
  1338  						ReservedPorts: []structs.Port{{Label: "admin", Value: 5000}},
  1339  						MBits:         50,
  1340  						DynamicPorts:  []structs.Port{{Label: "http", Value: 9876}},
  1341  					},
  1342  				},
  1343  			},
  1344  		},
  1345  		SharedResources: &structs.Resources{
  1346  			DiskMB: 150,
  1347  		},
  1348  
  1349  		AllocatedResources: &structs.AllocatedResources{
  1350  			Tasks: map[string]*structs.AllocatedTaskResources{
  1351  				"web": {
  1352  					Cpu: structs.AllocatedCpuResources{
  1353  						CpuShares: 500,
  1354  					},
  1355  					Memory: structs.AllocatedMemoryResources{
  1356  						MemoryMB: 256,
  1357  					},
  1358  					Networks: []*structs.NetworkResource{
  1359  						{
  1360  							Device:        "eth0",
  1361  							IP:            "192.168.0.100",
  1362  							ReservedPorts: []structs.Port{{Label: "admin", Value: 5000}},
  1363  							MBits:         50,
  1364  							DynamicPorts:  []structs.Port{{Label: "http", Value: 9876}},
  1365  						},
  1366  					},
  1367  				},
  1368  			},
  1369  			Shared: structs.AllocatedSharedResources{
  1370  				DiskMB: 150,
  1371  			},
  1372  		},
  1373  		Job:           BatchJob(),
  1374  		DesiredStatus: structs.AllocDesiredStatusRun,
  1375  		ClientStatus:  structs.AllocClientStatusPending,
  1376  	}
  1377  	alloc.JobID = alloc.Job.ID
  1378  	return alloc
  1379  }
  1380  
  1381  func SystemAlloc() *structs.Allocation {
  1382  	alloc := &structs.Allocation{
  1383  		ID:        uuid.Generate(),
  1384  		EvalID:    uuid.Generate(),
  1385  		NodeID:    "12345678-abcd-efab-cdef-123456789abc",
  1386  		Namespace: structs.DefaultNamespace,
  1387  		TaskGroup: "web",
  1388  
  1389  		// TODO Remove once clientv2 gets merged
  1390  		Resources: &structs.Resources{
  1391  			CPU:      500,
  1392  			MemoryMB: 256,
  1393  			DiskMB:   150,
  1394  			Networks: []*structs.NetworkResource{
  1395  				{
  1396  					Device:        "eth0",
  1397  					IP:            "192.168.0.100",
  1398  					ReservedPorts: []structs.Port{{Label: "admin", Value: 5000}},
  1399  					MBits:         50,
  1400  					DynamicPorts:  []structs.Port{{Label: "http"}},
  1401  				},
  1402  			},
  1403  		},
  1404  		TaskResources: map[string]*structs.Resources{
  1405  			"web": {
  1406  				CPU:      500,
  1407  				MemoryMB: 256,
  1408  				Networks: []*structs.NetworkResource{
  1409  					{
  1410  						Device:        "eth0",
  1411  						IP:            "192.168.0.100",
  1412  						ReservedPorts: []structs.Port{{Label: "admin", Value: 5000}},
  1413  						MBits:         50,
  1414  						DynamicPorts:  []structs.Port{{Label: "http", Value: 9876}},
  1415  					},
  1416  				},
  1417  			},
  1418  		},
  1419  		SharedResources: &structs.Resources{
  1420  			DiskMB: 150,
  1421  		},
  1422  
  1423  		AllocatedResources: &structs.AllocatedResources{
  1424  			Tasks: map[string]*structs.AllocatedTaskResources{
  1425  				"web": {
  1426  					Cpu: structs.AllocatedCpuResources{
  1427  						CpuShares: 500,
  1428  					},
  1429  					Memory: structs.AllocatedMemoryResources{
  1430  						MemoryMB: 256,
  1431  					},
  1432  					Networks: []*structs.NetworkResource{
  1433  						{
  1434  							Device:        "eth0",
  1435  							IP:            "192.168.0.100",
  1436  							ReservedPorts: []structs.Port{{Label: "admin", Value: 5000}},
  1437  							MBits:         50,
  1438  							DynamicPorts:  []structs.Port{{Label: "http", Value: 9876}},
  1439  						},
  1440  					},
  1441  				},
  1442  			},
  1443  			Shared: structs.AllocatedSharedResources{
  1444  				DiskMB: 150,
  1445  			},
  1446  		},
  1447  		Job:           SystemJob(),
  1448  		DesiredStatus: structs.AllocDesiredStatusRun,
  1449  		ClientStatus:  structs.AllocClientStatusPending,
  1450  	}
  1451  	alloc.JobID = alloc.Job.ID
  1452  	return alloc
  1453  }
  1454  
  1455  func VaultAccessor() *structs.VaultAccessor {
  1456  	return &structs.VaultAccessor{
  1457  		Accessor:    uuid.Generate(),
  1458  		NodeID:      uuid.Generate(),
  1459  		AllocID:     uuid.Generate(),
  1460  		CreationTTL: 86400,
  1461  		Task:        "foo",
  1462  	}
  1463  }
  1464  
  1465  func SITokenAccessor() *structs.SITokenAccessor {
  1466  	return &structs.SITokenAccessor{
  1467  		NodeID:     uuid.Generate(),
  1468  		AllocID:    uuid.Generate(),
  1469  		AccessorID: uuid.Generate(),
  1470  		TaskName:   "foo",
  1471  	}
  1472  }
  1473  
  1474  func Deployment() *structs.Deployment {
  1475  	return &structs.Deployment{
  1476  		ID:             uuid.Generate(),
  1477  		JobID:          uuid.Generate(),
  1478  		Namespace:      structs.DefaultNamespace,
  1479  		JobVersion:     2,
  1480  		JobModifyIndex: 20,
  1481  		JobCreateIndex: 18,
  1482  		TaskGroups: map[string]*structs.DeploymentState{
  1483  			"web": {
  1484  				DesiredTotal: 10,
  1485  			},
  1486  		},
  1487  		Status:            structs.DeploymentStatusRunning,
  1488  		StatusDescription: structs.DeploymentStatusDescriptionRunning,
  1489  		ModifyIndex:       23,
  1490  		CreateIndex:       21,
  1491  	}
  1492  }
  1493  
  1494  func Plan() *structs.Plan {
  1495  	return &structs.Plan{
  1496  		Priority: 50,
  1497  	}
  1498  }
  1499  
  1500  func PlanResult() *structs.PlanResult {
  1501  	return &structs.PlanResult{}
  1502  }
  1503  
  1504  func ACLPolicy() *structs.ACLPolicy {
  1505  	ap := &structs.ACLPolicy{
  1506  		Name:        fmt.Sprintf("policy-%s", uuid.Generate()),
  1507  		Description: "Super cool policy!",
  1508  		Rules: `
  1509  		namespace "default" {
  1510  			policy = "write"
  1511  		}
  1512  		node {
  1513  			policy = "read"
  1514  		}
  1515  		agent {
  1516  			policy = "read"
  1517  		}
  1518  		`,
  1519  		CreateIndex: 10,
  1520  		ModifyIndex: 20,
  1521  	}
  1522  	ap.SetHash()
  1523  	return ap
  1524  }
  1525  
  1526  func ACLToken() *structs.ACLToken {
  1527  	tk := &structs.ACLToken{
  1528  		AccessorID:  uuid.Generate(),
  1529  		SecretID:    uuid.Generate(),
  1530  		Name:        "my cool token " + uuid.Generate(),
  1531  		Type:        "client",
  1532  		Policies:    []string{"foo", "bar"},
  1533  		Global:      false,
  1534  		CreateTime:  time.Now().UTC(),
  1535  		CreateIndex: 10,
  1536  		ModifyIndex: 20,
  1537  	}
  1538  	tk.SetHash()
  1539  	return tk
  1540  }
  1541  
  1542  func ACLManagementToken() *structs.ACLToken {
  1543  	return &structs.ACLToken{
  1544  		AccessorID:  uuid.Generate(),
  1545  		SecretID:    uuid.Generate(),
  1546  		Name:        "management " + uuid.Generate(),
  1547  		Type:        "management",
  1548  		Global:      true,
  1549  		CreateTime:  time.Now().UTC(),
  1550  		CreateIndex: 10,
  1551  		ModifyIndex: 20,
  1552  	}
  1553  }
  1554  
  1555  func ScalingPolicy() *structs.ScalingPolicy {
  1556  	return &structs.ScalingPolicy{
  1557  		ID:   uuid.Generate(),
  1558  		Min:  1,
  1559  		Max:  100,
  1560  		Type: structs.ScalingPolicyTypeHorizontal,
  1561  		Target: map[string]string{
  1562  			structs.ScalingTargetNamespace: structs.DefaultNamespace,
  1563  			structs.ScalingTargetJob:       uuid.Generate(),
  1564  			structs.ScalingTargetGroup:     uuid.Generate(),
  1565  			structs.ScalingTargetTask:      uuid.Generate(),
  1566  		},
  1567  		Policy: map[string]interface{}{
  1568  			"a": "b",
  1569  		},
  1570  		Enabled: true,
  1571  	}
  1572  }
  1573  
  1574  func JobWithScalingPolicy() (*structs.Job, *structs.ScalingPolicy) {
  1575  	job := Job()
  1576  	policy := &structs.ScalingPolicy{
  1577  		ID:      uuid.Generate(),
  1578  		Min:     int64(job.TaskGroups[0].Count),
  1579  		Max:     int64(job.TaskGroups[0].Count),
  1580  		Type:    structs.ScalingPolicyTypeHorizontal,
  1581  		Policy:  map[string]interface{}{},
  1582  		Enabled: true,
  1583  	}
  1584  	policy.TargetTaskGroup(job, job.TaskGroups[0])
  1585  	job.TaskGroups[0].Scaling = policy
  1586  	return job, policy
  1587  }
  1588  
  1589  func MultiregionJob() *structs.Job {
  1590  	job := Job()
  1591  	update := *structs.DefaultUpdateStrategy
  1592  	job.Update = update
  1593  	job.TaskGroups[0].Update = &update
  1594  	job.Multiregion = &structs.Multiregion{
  1595  		Strategy: &structs.MultiregionStrategy{
  1596  			MaxParallel: 1,
  1597  			OnFailure:   "fail_all",
  1598  		},
  1599  		Regions: []*structs.MultiregionRegion{
  1600  			{
  1601  				Name:        "west",
  1602  				Count:       2,
  1603  				Datacenters: []string{"west-1", "west-2"},
  1604  				Meta:        map[string]string{"region_code": "W"},
  1605  			},
  1606  			{
  1607  				Name:        "east",
  1608  				Count:       1,
  1609  				Datacenters: []string{"east-1"},
  1610  				Meta:        map[string]string{"region_code": "E"},
  1611  			},
  1612  		},
  1613  	}
  1614  	return job
  1615  }
  1616  
  1617  func CSIPlugin() *structs.CSIPlugin {
  1618  	return &structs.CSIPlugin{
  1619  		ID:                 uuid.Generate(),
  1620  		Provider:           "com.hashicorp:mock",
  1621  		Version:            "0.1",
  1622  		ControllerRequired: true,
  1623  		Controllers:        map[string]*structs.CSIInfo{},
  1624  		Nodes:              map[string]*structs.CSIInfo{},
  1625  		Allocations:        []*structs.AllocListStub{},
  1626  		ControllersHealthy: 0,
  1627  		NodesHealthy:       0,
  1628  	}
  1629  }
  1630  
  1631  func CSIVolume(plugin *structs.CSIPlugin) *structs.CSIVolume {
  1632  	return &structs.CSIVolume{
  1633  		ID:                  uuid.Generate(),
  1634  		Name:                "test-vol",
  1635  		ExternalID:          "vol-01",
  1636  		Namespace:           "default",
  1637  		Topologies:          []*structs.CSITopology{},
  1638  		AccessMode:          structs.CSIVolumeAccessModeSingleNodeWriter,
  1639  		AttachmentMode:      structs.CSIVolumeAttachmentModeFilesystem,
  1640  		MountOptions:        &structs.CSIMountOptions{},
  1641  		Secrets:             structs.CSISecrets{},
  1642  		Parameters:          map[string]string{},
  1643  		Context:             map[string]string{},
  1644  		ReadAllocs:          map[string]*structs.Allocation{},
  1645  		WriteAllocs:         map[string]*structs.Allocation{},
  1646  		ReadClaims:          map[string]*structs.CSIVolumeClaim{},
  1647  		WriteClaims:         map[string]*structs.CSIVolumeClaim{},
  1648  		PastClaims:          map[string]*structs.CSIVolumeClaim{},
  1649  		PluginID:            plugin.ID,
  1650  		Provider:            plugin.Provider,
  1651  		ProviderVersion:     plugin.Version,
  1652  		ControllerRequired:  plugin.ControllerRequired,
  1653  		ControllersHealthy:  plugin.ControllersHealthy,
  1654  		ControllersExpected: len(plugin.Controllers),
  1655  		NodesHealthy:        plugin.NodesHealthy,
  1656  		NodesExpected:       len(plugin.Nodes),
  1657  	}
  1658  }
  1659  
  1660  func Events(index uint64) *structs.Events {
  1661  	return &structs.Events{
  1662  		Index: index,
  1663  		Events: []structs.Event{
  1664  			{
  1665  				Index:   index,
  1666  				Topic:   "Node",
  1667  				Type:    "update",
  1668  				Key:     uuid.Generate(),
  1669  				Payload: Node(),
  1670  			},
  1671  			{
  1672  				Index:   index,
  1673  				Topic:   "Eval",
  1674  				Type:    "update",
  1675  				Key:     uuid.Generate(),
  1676  				Payload: Eval(),
  1677  			},
  1678  		},
  1679  	}
  1680  }
  1681  
  1682  func AllocNetworkStatus() *structs.AllocNetworkStatus {
  1683  	return &structs.AllocNetworkStatus{
  1684  		InterfaceName: "eth0",
  1685  		Address:       "192.168.0.100",
  1686  		DNS: &structs.DNSConfig{
  1687  			Servers:  []string{"1.1.1.1"},
  1688  			Searches: []string{"localdomain"},
  1689  			Options:  []string{"ndots:5"},
  1690  		},
  1691  	}
  1692  }
  1693  
  1694  func Namespace() *structs.Namespace {
  1695  	ns := &structs.Namespace{
  1696  		Name:        fmt.Sprintf("team-%s", uuid.Generate()),
  1697  		Description: "test namespace",
  1698  		CreateIndex: 100,
  1699  		ModifyIndex: 200,
  1700  	}
  1701  	ns.SetHash()
  1702  	return ns
  1703  }