github.com/aminovpavel/nomad@v0.11.8/nomad/mock/mock.go (about)

     1  package mock
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"github.com/hashicorp/nomad/helper/uuid"
     8  	"github.com/hashicorp/nomad/nomad/structs"
     9  	psstructs "github.com/hashicorp/nomad/plugins/shared/structs"
    10  )
    11  
    12  func Node() *structs.Node {
    13  	node := &structs.Node{
    14  		ID:         uuid.Generate(),
    15  		SecretID:   uuid.Generate(),
    16  		Datacenter: "dc1",
    17  		Name:       "foobar",
    18  		Drivers: map[string]*structs.DriverInfo{
    19  			"exec": {
    20  				Detected: true,
    21  				Healthy:  true,
    22  			},
    23  			"mock_driver": {
    24  				Detected: true,
    25  				Healthy:  true,
    26  			},
    27  		},
    28  		Attributes: map[string]string{
    29  			"kernel.name":        "linux",
    30  			"arch":               "x86",
    31  			"nomad.version":      "0.5.0",
    32  			"driver.exec":        "1",
    33  			"driver.mock_driver": "1",
    34  		},
    35  
    36  		// TODO Remove once clientv2 gets merged
    37  		Resources: &structs.Resources{
    38  			CPU:      4000,
    39  			MemoryMB: 8192,
    40  			DiskMB:   100 * 1024,
    41  		},
    42  		Reserved: &structs.Resources{
    43  			CPU:      100,
    44  			MemoryMB: 256,
    45  			DiskMB:   4 * 1024,
    46  			Networks: []*structs.NetworkResource{
    47  				{
    48  					Device:        "eth0",
    49  					IP:            "192.168.0.100",
    50  					ReservedPorts: []structs.Port{{Label: "ssh", Value: 22}},
    51  					MBits:         1,
    52  				},
    53  			},
    54  		},
    55  
    56  		NodeResources: &structs.NodeResources{
    57  			Cpu: structs.NodeCpuResources{
    58  				CpuShares: 4000,
    59  			},
    60  			Memory: structs.NodeMemoryResources{
    61  				MemoryMB: 8192,
    62  			},
    63  			Disk: structs.NodeDiskResources{
    64  				DiskMB: 100 * 1024,
    65  			},
    66  			Networks: []*structs.NetworkResource{
    67  				{
    68  					Device: "eth0",
    69  					CIDR:   "192.168.0.100/32",
    70  					MBits:  1000,
    71  				},
    72  			},
    73  		},
    74  		ReservedResources: &structs.NodeReservedResources{
    75  			Cpu: structs.NodeReservedCpuResources{
    76  				CpuShares: 100,
    77  			},
    78  			Memory: structs.NodeReservedMemoryResources{
    79  				MemoryMB: 256,
    80  			},
    81  			Disk: structs.NodeReservedDiskResources{
    82  				DiskMB: 4 * 1024,
    83  			},
    84  			Networks: structs.NodeReservedNetworkResources{
    85  				ReservedHostPorts: "22",
    86  			},
    87  		},
    88  		Links: map[string]string{
    89  			"consul": "foobar.dc1",
    90  		},
    91  		Meta: map[string]string{
    92  			"pci-dss":  "true",
    93  			"database": "mysql",
    94  			"version":  "5.6",
    95  		},
    96  		NodeClass:             "linux-medium-pci",
    97  		Status:                structs.NodeStatusReady,
    98  		SchedulingEligibility: structs.NodeSchedulingEligible,
    99  	}
   100  	node.ComputeClass()
   101  	return node
   102  }
   103  
   104  // NvidiaNode returns a node with two instances of an Nvidia GPU
   105  func NvidiaNode() *structs.Node {
   106  	n := Node()
   107  	n.NodeResources.Devices = []*structs.NodeDeviceResource{
   108  		{
   109  			Type:   "gpu",
   110  			Vendor: "nvidia",
   111  			Name:   "1080ti",
   112  			Attributes: map[string]*psstructs.Attribute{
   113  				"memory":           psstructs.NewIntAttribute(11, psstructs.UnitGiB),
   114  				"cuda_cores":       psstructs.NewIntAttribute(3584, ""),
   115  				"graphics_clock":   psstructs.NewIntAttribute(1480, psstructs.UnitMHz),
   116  				"memory_bandwidth": psstructs.NewIntAttribute(11, psstructs.UnitGBPerS),
   117  			},
   118  			Instances: []*structs.NodeDevice{
   119  				{
   120  					ID:      uuid.Generate(),
   121  					Healthy: true,
   122  				},
   123  				{
   124  					ID:      uuid.Generate(),
   125  					Healthy: true,
   126  				},
   127  			},
   128  		},
   129  	}
   130  	n.ComputeClass()
   131  	return n
   132  }
   133  
   134  func HCL() string {
   135  	return `job "my-job" {
   136  	datacenters = ["dc1"]
   137  	type = "service"
   138  	constraint {
   139  		attribute = "${attr.kernel.name}"
   140  		value = "linux"
   141  	}
   142  
   143  	group "web" {
   144  		count = 10
   145  		restart {
   146  			attempts = 3
   147  			interval = "10m"
   148  			delay = "1m"
   149  			mode = "delay"
   150  		}
   151  		task "web" {
   152  			driver = "exec"
   153  			config {
   154  				command = "/bin/date"
   155  			}
   156  			resources {
   157  				cpu = 500
   158  				memory = 256
   159  			}
   160  		}
   161  	}
   162  }
   163  `
   164  }
   165  
   166  func Job() *structs.Job {
   167  	job := &structs.Job{
   168  		Region:      "global",
   169  		ID:          fmt.Sprintf("mock-service-%s", uuid.Generate()),
   170  		Name:        "my-job",
   171  		Namespace:   structs.DefaultNamespace,
   172  		Type:        structs.JobTypeService,
   173  		Priority:    50,
   174  		AllAtOnce:   false,
   175  		Datacenters: []string{"dc1"},
   176  		Constraints: []*structs.Constraint{
   177  			{
   178  				LTarget: "${attr.kernel.name}",
   179  				RTarget: "linux",
   180  				Operand: "=",
   181  			},
   182  		},
   183  		TaskGroups: []*structs.TaskGroup{
   184  			{
   185  				Name:  "web",
   186  				Count: 10,
   187  				EphemeralDisk: &structs.EphemeralDisk{
   188  					SizeMB: 150,
   189  				},
   190  				RestartPolicy: &structs.RestartPolicy{
   191  					Attempts: 3,
   192  					Interval: 10 * time.Minute,
   193  					Delay:    1 * time.Minute,
   194  					Mode:     structs.RestartPolicyModeDelay,
   195  				},
   196  				ReschedulePolicy: &structs.ReschedulePolicy{
   197  					Attempts:      2,
   198  					Interval:      10 * time.Minute,
   199  					Delay:         5 * time.Second,
   200  					DelayFunction: "constant",
   201  				},
   202  				Migrate: structs.DefaultMigrateStrategy(),
   203  				Tasks: []*structs.Task{
   204  					{
   205  						Name:   "web",
   206  						Driver: "exec",
   207  						Config: map[string]interface{}{
   208  							"command": "/bin/date",
   209  						},
   210  						Env: map[string]string{
   211  							"FOO": "bar",
   212  						},
   213  						Services: []*structs.Service{
   214  							{
   215  								Name:      "${TASK}-frontend",
   216  								PortLabel: "http",
   217  								Tags:      []string{"pci:${meta.pci-dss}", "datacenter:${node.datacenter}"},
   218  								Checks: []*structs.ServiceCheck{
   219  									{
   220  										Name:     "check-table",
   221  										Type:     structs.ServiceCheckScript,
   222  										Command:  "/usr/local/check-table-${meta.database}",
   223  										Args:     []string{"${meta.version}"},
   224  										Interval: 30 * time.Second,
   225  										Timeout:  5 * time.Second,
   226  									},
   227  								},
   228  							},
   229  							{
   230  								Name:      "${TASK}-admin",
   231  								PortLabel: "admin",
   232  							},
   233  						},
   234  						LogConfig: structs.DefaultLogConfig(),
   235  						Resources: &structs.Resources{
   236  							CPU:      500,
   237  							MemoryMB: 256,
   238  							Networks: []*structs.NetworkResource{
   239  								{
   240  									MBits: 50,
   241  									DynamicPorts: []structs.Port{
   242  										{Label: "http"},
   243  										{Label: "admin"},
   244  									},
   245  								},
   246  							},
   247  						},
   248  						Meta: map[string]string{
   249  							"foo": "bar",
   250  						},
   251  					},
   252  				},
   253  				Meta: map[string]string{
   254  					"elb_check_type":     "http",
   255  					"elb_check_interval": "30s",
   256  					"elb_check_min":      "3",
   257  				},
   258  			},
   259  		},
   260  		Meta: map[string]string{
   261  			"owner": "armon",
   262  		},
   263  		Status:         structs.JobStatusPending,
   264  		Version:        0,
   265  		CreateIndex:    42,
   266  		ModifyIndex:    99,
   267  		JobModifyIndex: 99,
   268  	}
   269  	job.Canonicalize()
   270  	return job
   271  }
   272  
   273  func LifecycleSideTask(resources structs.Resources, i int) *structs.Task {
   274  	return &structs.Task{
   275  		Name:   fmt.Sprintf("side-%d", i),
   276  		Driver: "exec",
   277  		Config: map[string]interface{}{
   278  			"command": "/bin/date",
   279  		},
   280  		Lifecycle: &structs.TaskLifecycleConfig{
   281  			Hook:    structs.TaskLifecycleHookPrestart,
   282  			Sidecar: true,
   283  		},
   284  		LogConfig: structs.DefaultLogConfig(),
   285  		Resources: &resources,
   286  	}
   287  }
   288  
   289  func LifecycleInitTask(resources structs.Resources, i int) *structs.Task {
   290  	return &structs.Task{
   291  		Name:   fmt.Sprintf("init-%d", i),
   292  		Driver: "exec",
   293  		Config: map[string]interface{}{
   294  			"command": "/bin/date",
   295  		},
   296  		Lifecycle: &structs.TaskLifecycleConfig{
   297  			Hook:    structs.TaskLifecycleHookPrestart,
   298  			Sidecar: false,
   299  		},
   300  		LogConfig: structs.DefaultLogConfig(),
   301  		Resources: &resources,
   302  	}
   303  }
   304  
   305  func LifecycleMainTask(resources structs.Resources, i int) *structs.Task {
   306  	return &structs.Task{
   307  		Name:   fmt.Sprintf("main-%d", i),
   308  		Driver: "exec",
   309  		Config: map[string]interface{}{
   310  			"command": "/bin/date",
   311  		},
   312  		LogConfig: structs.DefaultLogConfig(),
   313  		Resources: &resources,
   314  	}
   315  }
   316  func VariableLifecycleJob(resources structs.Resources, main int, init int, side int) *structs.Job {
   317  	tasks := []*structs.Task{}
   318  	for i := 0; i < main; i++ {
   319  		tasks = append(tasks, LifecycleMainTask(resources, i))
   320  	}
   321  	for i := 0; i < init; i++ {
   322  		tasks = append(tasks, LifecycleInitTask(resources, i))
   323  	}
   324  	for i := 0; i < side; i++ {
   325  		tasks = append(tasks, LifecycleSideTask(resources, i))
   326  	}
   327  	job := &structs.Job{
   328  		Region:      "global",
   329  		ID:          fmt.Sprintf("mock-service-%s", uuid.Generate()),
   330  		Name:        "my-job",
   331  		Namespace:   structs.DefaultNamespace,
   332  		Type:        structs.JobTypeService,
   333  		Priority:    50,
   334  		AllAtOnce:   false,
   335  		Datacenters: []string{"dc1"},
   336  		Constraints: []*structs.Constraint{
   337  			{
   338  				LTarget: "${attr.kernel.name}",
   339  				RTarget: "linux",
   340  				Operand: "=",
   341  			},
   342  		},
   343  		TaskGroups: []*structs.TaskGroup{
   344  			{
   345  				Name:  "web",
   346  				Count: 1,
   347  				Tasks: tasks,
   348  			},
   349  		},
   350  		Meta: map[string]string{
   351  			"owner": "armon",
   352  		},
   353  		Status:         structs.JobStatusPending,
   354  		Version:        0,
   355  		CreateIndex:    42,
   356  		ModifyIndex:    99,
   357  		JobModifyIndex: 99,
   358  	}
   359  	job.Canonicalize()
   360  	return job
   361  }
   362  func LifecycleJob() *structs.Job {
   363  	job := &structs.Job{
   364  		Region:      "global",
   365  		ID:          fmt.Sprintf("mock-service-%s", uuid.Generate()),
   366  		Name:        "my-job",
   367  		Namespace:   structs.DefaultNamespace,
   368  		Type:        structs.JobTypeBatch,
   369  		Priority:    50,
   370  		AllAtOnce:   false,
   371  		Datacenters: []string{"dc1"},
   372  		Constraints: []*structs.Constraint{
   373  			{
   374  				LTarget: "${attr.kernel.name}",
   375  				RTarget: "linux",
   376  				Operand: "=",
   377  			},
   378  		},
   379  		TaskGroups: []*structs.TaskGroup{
   380  			{
   381  				Name:  "web",
   382  				Count: 1,
   383  				RestartPolicy: &structs.RestartPolicy{
   384  					Attempts: 0,
   385  					Interval: 10 * time.Minute,
   386  					Delay:    1 * time.Minute,
   387  					Mode:     structs.RestartPolicyModeFail,
   388  				},
   389  				Tasks: []*structs.Task{
   390  					{
   391  						Name:   "web",
   392  						Driver: "mock_driver",
   393  						Config: map[string]interface{}{
   394  							"run_for": "1s",
   395  						},
   396  						LogConfig: structs.DefaultLogConfig(),
   397  						Resources: &structs.Resources{
   398  							CPU:      1000,
   399  							MemoryMB: 256,
   400  						},
   401  					},
   402  					{
   403  						Name:   "side",
   404  						Driver: "mock_driver",
   405  						Config: map[string]interface{}{
   406  							"run_for": "1s",
   407  						},
   408  						Lifecycle: &structs.TaskLifecycleConfig{
   409  							Hook:    structs.TaskLifecycleHookPrestart,
   410  							Sidecar: true,
   411  						},
   412  						LogConfig: structs.DefaultLogConfig(),
   413  						Resources: &structs.Resources{
   414  							CPU:      1000,
   415  							MemoryMB: 256,
   416  						},
   417  					},
   418  					{
   419  						Name:   "init",
   420  						Driver: "mock_driver",
   421  						Config: map[string]interface{}{
   422  							"run_for": "1s",
   423  						},
   424  						Lifecycle: &structs.TaskLifecycleConfig{
   425  							Hook:    structs.TaskLifecycleHookPrestart,
   426  							Sidecar: false,
   427  						},
   428  						LogConfig: structs.DefaultLogConfig(),
   429  						Resources: &structs.Resources{
   430  							CPU:      1000,
   431  							MemoryMB: 256,
   432  						},
   433  					},
   434  				},
   435  			},
   436  		},
   437  		Meta: map[string]string{
   438  			"owner": "armon",
   439  		},
   440  		Status:         structs.JobStatusPending,
   441  		Version:        0,
   442  		CreateIndex:    42,
   443  		ModifyIndex:    99,
   444  		JobModifyIndex: 99,
   445  	}
   446  	job.Canonicalize()
   447  	return job
   448  }
   449  func LifecycleAlloc() *structs.Allocation {
   450  	alloc := &structs.Allocation{
   451  		ID:        uuid.Generate(),
   452  		EvalID:    uuid.Generate(),
   453  		NodeID:    "12345678-abcd-efab-cdef-123456789abc",
   454  		Namespace: structs.DefaultNamespace,
   455  		TaskGroup: "web",
   456  
   457  		// TODO Remove once clientv2 gets merged
   458  		Resources: &structs.Resources{
   459  			CPU:      500,
   460  			MemoryMB: 256,
   461  		},
   462  		TaskResources: map[string]*structs.Resources{
   463  			"web": {
   464  				CPU:      1000,
   465  				MemoryMB: 256,
   466  			},
   467  			"init": {
   468  				CPU:      1000,
   469  				MemoryMB: 256,
   470  			},
   471  			"side": {
   472  				CPU:      1000,
   473  				MemoryMB: 256,
   474  			},
   475  		},
   476  
   477  		AllocatedResources: &structs.AllocatedResources{
   478  			Tasks: map[string]*structs.AllocatedTaskResources{
   479  				"web": {
   480  					Cpu: structs.AllocatedCpuResources{
   481  						CpuShares: 1000,
   482  					},
   483  					Memory: structs.AllocatedMemoryResources{
   484  						MemoryMB: 256,
   485  					},
   486  				},
   487  				"init": {
   488  					Cpu: structs.AllocatedCpuResources{
   489  						CpuShares: 1000,
   490  					},
   491  					Memory: structs.AllocatedMemoryResources{
   492  						MemoryMB: 256,
   493  					},
   494  				},
   495  				"side": {
   496  					Cpu: structs.AllocatedCpuResources{
   497  						CpuShares: 1000,
   498  					},
   499  					Memory: structs.AllocatedMemoryResources{
   500  						MemoryMB: 256,
   501  					},
   502  				},
   503  			},
   504  		},
   505  		Job:           LifecycleJob(),
   506  		DesiredStatus: structs.AllocDesiredStatusRun,
   507  		ClientStatus:  structs.AllocClientStatusPending,
   508  	}
   509  	alloc.JobID = alloc.Job.ID
   510  	return alloc
   511  }
   512  
   513  func MaxParallelJob() *structs.Job {
   514  	update := *structs.DefaultUpdateStrategy
   515  	update.MaxParallel = 0
   516  	job := &structs.Job{
   517  		Region:      "global",
   518  		ID:          fmt.Sprintf("mock-service-%s", uuid.Generate()),
   519  		Name:        "my-job",
   520  		Namespace:   structs.DefaultNamespace,
   521  		Type:        structs.JobTypeService,
   522  		Priority:    50,
   523  		AllAtOnce:   false,
   524  		Datacenters: []string{"dc1"},
   525  		Constraints: []*structs.Constraint{
   526  			{
   527  				LTarget: "${attr.kernel.name}",
   528  				RTarget: "linux",
   529  				Operand: "=",
   530  			},
   531  		},
   532  		Update: update,
   533  		TaskGroups: []*structs.TaskGroup{
   534  			{
   535  				Name:  "web",
   536  				Count: 10,
   537  				EphemeralDisk: &structs.EphemeralDisk{
   538  					SizeMB: 150,
   539  				},
   540  				RestartPolicy: &structs.RestartPolicy{
   541  					Attempts: 3,
   542  					Interval: 10 * time.Minute,
   543  					Delay:    1 * time.Minute,
   544  					Mode:     structs.RestartPolicyModeDelay,
   545  				},
   546  				ReschedulePolicy: &structs.ReschedulePolicy{
   547  					Attempts:      2,
   548  					Interval:      10 * time.Minute,
   549  					Delay:         5 * time.Second,
   550  					DelayFunction: "constant",
   551  				},
   552  				Migrate: structs.DefaultMigrateStrategy(),
   553  				Update:  &update,
   554  				Tasks: []*structs.Task{
   555  					{
   556  						Name:   "web",
   557  						Driver: "exec",
   558  						Config: map[string]interface{}{
   559  							"command": "/bin/date",
   560  						},
   561  						Env: map[string]string{
   562  							"FOO": "bar",
   563  						},
   564  						Services: []*structs.Service{
   565  							{
   566  								Name:      "${TASK}-frontend",
   567  								PortLabel: "http",
   568  								Tags:      []string{"pci:${meta.pci-dss}", "datacenter:${node.datacenter}"},
   569  								Checks: []*structs.ServiceCheck{
   570  									{
   571  										Name:     "check-table",
   572  										Type:     structs.ServiceCheckScript,
   573  										Command:  "/usr/local/check-table-${meta.database}",
   574  										Args:     []string{"${meta.version}"},
   575  										Interval: 30 * time.Second,
   576  										Timeout:  5 * time.Second,
   577  									},
   578  								},
   579  							},
   580  							{
   581  								Name:      "${TASK}-admin",
   582  								PortLabel: "admin",
   583  							},
   584  						},
   585  						LogConfig: structs.DefaultLogConfig(),
   586  						Resources: &structs.Resources{
   587  							CPU:      500,
   588  							MemoryMB: 256,
   589  							Networks: []*structs.NetworkResource{
   590  								{
   591  									MBits: 50,
   592  									DynamicPorts: []structs.Port{
   593  										{Label: "http"},
   594  										{Label: "admin"},
   595  									},
   596  								},
   597  							},
   598  						},
   599  						Meta: map[string]string{
   600  							"foo": "bar",
   601  						},
   602  					},
   603  				},
   604  				Meta: map[string]string{
   605  					"elb_check_type":     "http",
   606  					"elb_check_interval": "30s",
   607  					"elb_check_min":      "3",
   608  				},
   609  			},
   610  		},
   611  		Meta: map[string]string{
   612  			"owner": "armon",
   613  		},
   614  		Status:         structs.JobStatusPending,
   615  		Version:        0,
   616  		CreateIndex:    42,
   617  		ModifyIndex:    99,
   618  		JobModifyIndex: 99,
   619  	}
   620  	job.Canonicalize()
   621  	return job
   622  }
   623  
   624  // ConnectJob adds a Connect proxy sidecar group service to mock.Job.
   625  //
   626  // Note this does *not* include the Job.Register mutation that inserts the
   627  // associated Sidecar Task (nor the hook that configures envoy as the default).
   628  func ConnectJob() *structs.Job {
   629  	job := Job()
   630  	tg := job.TaskGroups[0]
   631  	tg.Networks = []*structs.NetworkResource{
   632  		{
   633  			Mode: "bridge",
   634  		},
   635  	}
   636  	tg.Services = []*structs.Service{
   637  		{
   638  			Name:      "testconnect",
   639  			PortLabel: "9999",
   640  			Connect: &structs.ConsulConnect{
   641  				SidecarService: &structs.ConsulSidecarService{},
   642  			},
   643  		},
   644  	}
   645  	tg.Networks = structs.Networks{{
   646  		Mode: "bridge", // always bridge ... for now?
   647  	}}
   648  	return job
   649  }
   650  
   651  func BatchJob() *structs.Job {
   652  	job := &structs.Job{
   653  		Region:      "global",
   654  		ID:          fmt.Sprintf("mock-batch-%s", uuid.Generate()),
   655  		Name:        "batch-job",
   656  		Namespace:   structs.DefaultNamespace,
   657  		Type:        structs.JobTypeBatch,
   658  		Priority:    50,
   659  		AllAtOnce:   false,
   660  		Datacenters: []string{"dc1"},
   661  		TaskGroups: []*structs.TaskGroup{
   662  			{
   663  				Name:  "web",
   664  				Count: 10,
   665  				EphemeralDisk: &structs.EphemeralDisk{
   666  					SizeMB: 150,
   667  				},
   668  				RestartPolicy: &structs.RestartPolicy{
   669  					Attempts: 3,
   670  					Interval: 10 * time.Minute,
   671  					Delay:    1 * time.Minute,
   672  					Mode:     structs.RestartPolicyModeDelay,
   673  				},
   674  				ReschedulePolicy: &structs.ReschedulePolicy{
   675  					Attempts:      2,
   676  					Interval:      10 * time.Minute,
   677  					Delay:         5 * time.Second,
   678  					DelayFunction: "constant",
   679  				},
   680  				Tasks: []*structs.Task{
   681  					{
   682  						Name:   "web",
   683  						Driver: "mock_driver",
   684  						Config: map[string]interface{}{
   685  							"run_for": "500ms",
   686  						},
   687  						Env: map[string]string{
   688  							"FOO": "bar",
   689  						},
   690  						LogConfig: structs.DefaultLogConfig(),
   691  						Resources: &structs.Resources{
   692  							CPU:      100,
   693  							MemoryMB: 100,
   694  							Networks: []*structs.NetworkResource{
   695  								{
   696  									MBits: 50,
   697  								},
   698  							},
   699  						},
   700  						Meta: map[string]string{
   701  							"foo": "bar",
   702  						},
   703  					},
   704  				},
   705  			},
   706  		},
   707  		Status:         structs.JobStatusPending,
   708  		Version:        0,
   709  		CreateIndex:    43,
   710  		ModifyIndex:    99,
   711  		JobModifyIndex: 99,
   712  	}
   713  	job.Canonicalize()
   714  	return job
   715  }
   716  
   717  func SystemJob() *structs.Job {
   718  	job := &structs.Job{
   719  		Region:      "global",
   720  		Namespace:   structs.DefaultNamespace,
   721  		ID:          fmt.Sprintf("mock-system-%s", uuid.Generate()),
   722  		Name:        "my-job",
   723  		Type:        structs.JobTypeSystem,
   724  		Priority:    100,
   725  		AllAtOnce:   false,
   726  		Datacenters: []string{"dc1"},
   727  		Constraints: []*structs.Constraint{
   728  			{
   729  				LTarget: "${attr.kernel.name}",
   730  				RTarget: "linux",
   731  				Operand: "=",
   732  			},
   733  		},
   734  		TaskGroups: []*structs.TaskGroup{
   735  			{
   736  				Name:  "web",
   737  				Count: 1,
   738  				RestartPolicy: &structs.RestartPolicy{
   739  					Attempts: 3,
   740  					Interval: 10 * time.Minute,
   741  					Delay:    1 * time.Minute,
   742  					Mode:     structs.RestartPolicyModeDelay,
   743  				},
   744  				EphemeralDisk: structs.DefaultEphemeralDisk(),
   745  				Tasks: []*structs.Task{
   746  					{
   747  						Name:   "web",
   748  						Driver: "exec",
   749  						Config: map[string]interface{}{
   750  							"command": "/bin/date",
   751  						},
   752  						Env: map[string]string{},
   753  						Resources: &structs.Resources{
   754  							CPU:      500,
   755  							MemoryMB: 256,
   756  							Networks: []*structs.NetworkResource{
   757  								{
   758  									MBits:        50,
   759  									DynamicPorts: []structs.Port{{Label: "http"}},
   760  								},
   761  							},
   762  						},
   763  						LogConfig: structs.DefaultLogConfig(),
   764  					},
   765  				},
   766  			},
   767  		},
   768  		Meta: map[string]string{
   769  			"owner": "armon",
   770  		},
   771  		Status:      structs.JobStatusPending,
   772  		CreateIndex: 42,
   773  		ModifyIndex: 99,
   774  	}
   775  	job.Canonicalize()
   776  	return job
   777  }
   778  
   779  func PeriodicJob() *structs.Job {
   780  	job := Job()
   781  	job.Type = structs.JobTypeBatch
   782  	job.Periodic = &structs.PeriodicConfig{
   783  		Enabled:  true,
   784  		SpecType: structs.PeriodicSpecCron,
   785  		Spec:     "*/30 * * * *",
   786  	}
   787  	job.Status = structs.JobStatusRunning
   788  	job.TaskGroups[0].Migrate = nil
   789  	return job
   790  }
   791  
   792  func Eval() *structs.Evaluation {
   793  	now := time.Now().UTC().UnixNano()
   794  	eval := &structs.Evaluation{
   795  		ID:         uuid.Generate(),
   796  		Namespace:  structs.DefaultNamespace,
   797  		Priority:   50,
   798  		Type:       structs.JobTypeService,
   799  		JobID:      uuid.Generate(),
   800  		Status:     structs.EvalStatusPending,
   801  		CreateTime: now,
   802  		ModifyTime: now,
   803  	}
   804  	return eval
   805  }
   806  
   807  func JobSummary(jobID string) *structs.JobSummary {
   808  	js := &structs.JobSummary{
   809  		JobID:     jobID,
   810  		Namespace: structs.DefaultNamespace,
   811  		Summary: map[string]structs.TaskGroupSummary{
   812  			"web": {
   813  				Queued:   0,
   814  				Starting: 0,
   815  			},
   816  		},
   817  	}
   818  	return js
   819  }
   820  
   821  func Alloc() *structs.Allocation {
   822  	alloc := &structs.Allocation{
   823  		ID:        uuid.Generate(),
   824  		EvalID:    uuid.Generate(),
   825  		NodeID:    "12345678-abcd-efab-cdef-123456789abc",
   826  		Namespace: structs.DefaultNamespace,
   827  		TaskGroup: "web",
   828  
   829  		// TODO Remove once clientv2 gets merged
   830  		Resources: &structs.Resources{
   831  			CPU:      500,
   832  			MemoryMB: 256,
   833  			DiskMB:   150,
   834  			Networks: []*structs.NetworkResource{
   835  				{
   836  					Device:        "eth0",
   837  					IP:            "192.168.0.100",
   838  					ReservedPorts: []structs.Port{{Label: "admin", Value: 5000}},
   839  					MBits:         50,
   840  					DynamicPorts:  []structs.Port{{Label: "http"}},
   841  				},
   842  			},
   843  		},
   844  		TaskResources: map[string]*structs.Resources{
   845  			"web": {
   846  				CPU:      500,
   847  				MemoryMB: 256,
   848  				Networks: []*structs.NetworkResource{
   849  					{
   850  						Device:        "eth0",
   851  						IP:            "192.168.0.100",
   852  						ReservedPorts: []structs.Port{{Label: "admin", Value: 5000}},
   853  						MBits:         50,
   854  						DynamicPorts:  []structs.Port{{Label: "http", Value: 9876}},
   855  					},
   856  				},
   857  			},
   858  		},
   859  		SharedResources: &structs.Resources{
   860  			DiskMB: 150,
   861  		},
   862  
   863  		AllocatedResources: &structs.AllocatedResources{
   864  			Tasks: map[string]*structs.AllocatedTaskResources{
   865  				"web": {
   866  					Cpu: structs.AllocatedCpuResources{
   867  						CpuShares: 500,
   868  					},
   869  					Memory: structs.AllocatedMemoryResources{
   870  						MemoryMB: 256,
   871  					},
   872  					Networks: []*structs.NetworkResource{
   873  						{
   874  							Device:        "eth0",
   875  							IP:            "192.168.0.100",
   876  							ReservedPorts: []structs.Port{{Label: "admin", Value: 5000}},
   877  							MBits:         50,
   878  							DynamicPorts:  []structs.Port{{Label: "http", Value: 9876}},
   879  						},
   880  					},
   881  				},
   882  			},
   883  			Shared: structs.AllocatedSharedResources{
   884  				DiskMB: 150,
   885  			},
   886  		},
   887  		Job:           Job(),
   888  		DesiredStatus: structs.AllocDesiredStatusRun,
   889  		ClientStatus:  structs.AllocClientStatusPending,
   890  	}
   891  	alloc.JobID = alloc.Job.ID
   892  	return alloc
   893  }
   894  
   895  // ConnectJob adds a Connect proxy sidecar group service to mock.Alloc.
   896  func ConnectAlloc() *structs.Allocation {
   897  	alloc := Alloc()
   898  	alloc.Job = ConnectJob()
   899  	alloc.AllocatedResources.Shared.Networks = []*structs.NetworkResource{
   900  		{
   901  			Mode: "bridge",
   902  			IP:   "10.0.0.1",
   903  			DynamicPorts: []structs.Port{
   904  				{
   905  					Label: "connect-proxy-testconnect",
   906  					Value: 9999,
   907  					To:    9999,
   908  				},
   909  			},
   910  		},
   911  	}
   912  	return alloc
   913  }
   914  
   915  func BatchConnectJob() *structs.Job {
   916  	job := &structs.Job{
   917  		Region:      "global",
   918  		ID:          fmt.Sprintf("mock-connect-batch-job%s", uuid.Generate()),
   919  		Name:        "mock-connect-batch-job",
   920  		Namespace:   structs.DefaultNamespace,
   921  		Type:        structs.JobTypeBatch,
   922  		Priority:    50,
   923  		AllAtOnce:   false,
   924  		Datacenters: []string{"dc1"},
   925  		TaskGroups: []*structs.TaskGroup{{
   926  			Name:          "mock-connect-batch-job",
   927  			Count:         1,
   928  			EphemeralDisk: &structs.EphemeralDisk{SizeMB: 150},
   929  			Networks: []*structs.NetworkResource{{
   930  				Mode: "bridge",
   931  			}},
   932  			Tasks: []*structs.Task{{
   933  				Name:   "connect-proxy-testconnect",
   934  				Kind:   "connect-proxy:testconnect",
   935  				Driver: "mock_driver",
   936  				Config: map[string]interface{}{
   937  					"run_for": "500ms",
   938  				},
   939  				LogConfig: structs.DefaultLogConfig(),
   940  				Resources: &structs.Resources{
   941  					CPU:      500,
   942  					MemoryMB: 256,
   943  					Networks: []*structs.NetworkResource{{
   944  						MBits:        50,
   945  						DynamicPorts: []structs.Port{{Label: "port1"}},
   946  					}},
   947  				},
   948  			}},
   949  			Services: []*structs.Service{{
   950  				Name: "testconnect",
   951  			}},
   952  		}},
   953  		Meta:           map[string]string{"owner": "shoenig"},
   954  		Status:         structs.JobStatusPending,
   955  		Version:        0,
   956  		CreateIndex:    42,
   957  		ModifyIndex:    99,
   958  		JobModifyIndex: 99,
   959  	}
   960  	if err := job.Canonicalize(); err != nil {
   961  		panic(err)
   962  	}
   963  	return job
   964  }
   965  
   966  // BatchConnectAlloc is useful for testing task runner things.
   967  func BatchConnectAlloc() *structs.Allocation {
   968  	alloc := &structs.Allocation{
   969  		ID:        uuid.Generate(),
   970  		EvalID:    uuid.Generate(),
   971  		NodeID:    "12345678-abcd-efab-cdef-123456789abc",
   972  		Namespace: structs.DefaultNamespace,
   973  		TaskGroup: "mock-connect-batch-job",
   974  		TaskResources: map[string]*structs.Resources{
   975  			"connect-proxy-testconnect": {
   976  				CPU:      500,
   977  				MemoryMB: 256,
   978  			},
   979  		},
   980  
   981  		AllocatedResources: &structs.AllocatedResources{
   982  			Tasks: map[string]*structs.AllocatedTaskResources{
   983  				"connect-proxy-testconnect": {
   984  					Cpu:    structs.AllocatedCpuResources{CpuShares: 500},
   985  					Memory: structs.AllocatedMemoryResources{MemoryMB: 256},
   986  				},
   987  			},
   988  			Shared: structs.AllocatedSharedResources{
   989  				Networks: []*structs.NetworkResource{{
   990  					Mode: "bridge",
   991  					IP:   "10.0.0.1",
   992  					DynamicPorts: []structs.Port{{
   993  						Label: "connect-proxy-testconnect",
   994  						Value: 9999,
   995  						To:    9999,
   996  					}},
   997  				}},
   998  				DiskMB: 0,
   999  			},
  1000  		},
  1001  		Job:           BatchConnectJob(),
  1002  		DesiredStatus: structs.AllocDesiredStatusRun,
  1003  		ClientStatus:  structs.AllocClientStatusPending,
  1004  	}
  1005  	alloc.JobID = alloc.Job.ID
  1006  	return alloc
  1007  }
  1008  
  1009  func BatchAlloc() *structs.Allocation {
  1010  	alloc := &structs.Allocation{
  1011  		ID:        uuid.Generate(),
  1012  		EvalID:    uuid.Generate(),
  1013  		NodeID:    "12345678-abcd-efab-cdef-123456789abc",
  1014  		Namespace: structs.DefaultNamespace,
  1015  		TaskGroup: "web",
  1016  
  1017  		// TODO Remove once clientv2 gets merged
  1018  		Resources: &structs.Resources{
  1019  			CPU:      500,
  1020  			MemoryMB: 256,
  1021  			DiskMB:   150,
  1022  			Networks: []*structs.NetworkResource{
  1023  				{
  1024  					Device:        "eth0",
  1025  					IP:            "192.168.0.100",
  1026  					ReservedPorts: []structs.Port{{Label: "admin", Value: 5000}},
  1027  					MBits:         50,
  1028  					DynamicPorts:  []structs.Port{{Label: "http"}},
  1029  				},
  1030  			},
  1031  		},
  1032  		TaskResources: map[string]*structs.Resources{
  1033  			"web": {
  1034  				CPU:      500,
  1035  				MemoryMB: 256,
  1036  				Networks: []*structs.NetworkResource{
  1037  					{
  1038  						Device:        "eth0",
  1039  						IP:            "192.168.0.100",
  1040  						ReservedPorts: []structs.Port{{Label: "admin", Value: 5000}},
  1041  						MBits:         50,
  1042  						DynamicPorts:  []structs.Port{{Label: "http", Value: 9876}},
  1043  					},
  1044  				},
  1045  			},
  1046  		},
  1047  		SharedResources: &structs.Resources{
  1048  			DiskMB: 150,
  1049  		},
  1050  
  1051  		AllocatedResources: &structs.AllocatedResources{
  1052  			Tasks: map[string]*structs.AllocatedTaskResources{
  1053  				"web": {
  1054  					Cpu: structs.AllocatedCpuResources{
  1055  						CpuShares: 500,
  1056  					},
  1057  					Memory: structs.AllocatedMemoryResources{
  1058  						MemoryMB: 256,
  1059  					},
  1060  					Networks: []*structs.NetworkResource{
  1061  						{
  1062  							Device:        "eth0",
  1063  							IP:            "192.168.0.100",
  1064  							ReservedPorts: []structs.Port{{Label: "admin", Value: 5000}},
  1065  							MBits:         50,
  1066  							DynamicPorts:  []structs.Port{{Label: "http", Value: 9876}},
  1067  						},
  1068  					},
  1069  				},
  1070  			},
  1071  			Shared: structs.AllocatedSharedResources{
  1072  				DiskMB: 150,
  1073  			},
  1074  		},
  1075  		Job:           BatchJob(),
  1076  		DesiredStatus: structs.AllocDesiredStatusRun,
  1077  		ClientStatus:  structs.AllocClientStatusPending,
  1078  	}
  1079  	alloc.JobID = alloc.Job.ID
  1080  	return alloc
  1081  }
  1082  
  1083  func SystemAlloc() *structs.Allocation {
  1084  	alloc := &structs.Allocation{
  1085  		ID:        uuid.Generate(),
  1086  		EvalID:    uuid.Generate(),
  1087  		NodeID:    "12345678-abcd-efab-cdef-123456789abc",
  1088  		Namespace: structs.DefaultNamespace,
  1089  		TaskGroup: "web",
  1090  
  1091  		// TODO Remove once clientv2 gets merged
  1092  		Resources: &structs.Resources{
  1093  			CPU:      500,
  1094  			MemoryMB: 256,
  1095  			DiskMB:   150,
  1096  			Networks: []*structs.NetworkResource{
  1097  				{
  1098  					Device:        "eth0",
  1099  					IP:            "192.168.0.100",
  1100  					ReservedPorts: []structs.Port{{Label: "admin", Value: 5000}},
  1101  					MBits:         50,
  1102  					DynamicPorts:  []structs.Port{{Label: "http"}},
  1103  				},
  1104  			},
  1105  		},
  1106  		TaskResources: map[string]*structs.Resources{
  1107  			"web": {
  1108  				CPU:      500,
  1109  				MemoryMB: 256,
  1110  				Networks: []*structs.NetworkResource{
  1111  					{
  1112  						Device:        "eth0",
  1113  						IP:            "192.168.0.100",
  1114  						ReservedPorts: []structs.Port{{Label: "admin", Value: 5000}},
  1115  						MBits:         50,
  1116  						DynamicPorts:  []structs.Port{{Label: "http", Value: 9876}},
  1117  					},
  1118  				},
  1119  			},
  1120  		},
  1121  		SharedResources: &structs.Resources{
  1122  			DiskMB: 150,
  1123  		},
  1124  
  1125  		AllocatedResources: &structs.AllocatedResources{
  1126  			Tasks: map[string]*structs.AllocatedTaskResources{
  1127  				"web": {
  1128  					Cpu: structs.AllocatedCpuResources{
  1129  						CpuShares: 500,
  1130  					},
  1131  					Memory: structs.AllocatedMemoryResources{
  1132  						MemoryMB: 256,
  1133  					},
  1134  					Networks: []*structs.NetworkResource{
  1135  						{
  1136  							Device:        "eth0",
  1137  							IP:            "192.168.0.100",
  1138  							ReservedPorts: []structs.Port{{Label: "admin", Value: 5000}},
  1139  							MBits:         50,
  1140  							DynamicPorts:  []structs.Port{{Label: "http", Value: 9876}},
  1141  						},
  1142  					},
  1143  				},
  1144  			},
  1145  			Shared: structs.AllocatedSharedResources{
  1146  				DiskMB: 150,
  1147  			},
  1148  		},
  1149  		Job:           SystemJob(),
  1150  		DesiredStatus: structs.AllocDesiredStatusRun,
  1151  		ClientStatus:  structs.AllocClientStatusPending,
  1152  	}
  1153  	alloc.JobID = alloc.Job.ID
  1154  	return alloc
  1155  }
  1156  
  1157  func VaultAccessor() *structs.VaultAccessor {
  1158  	return &structs.VaultAccessor{
  1159  		Accessor:    uuid.Generate(),
  1160  		NodeID:      uuid.Generate(),
  1161  		AllocID:     uuid.Generate(),
  1162  		CreationTTL: 86400,
  1163  		Task:        "foo",
  1164  	}
  1165  }
  1166  
  1167  func SITokenAccessor() *structs.SITokenAccessor {
  1168  	return &structs.SITokenAccessor{
  1169  		NodeID:     uuid.Generate(),
  1170  		AllocID:    uuid.Generate(),
  1171  		AccessorID: uuid.Generate(),
  1172  		TaskName:   "foo",
  1173  	}
  1174  }
  1175  
  1176  func Deployment() *structs.Deployment {
  1177  	return &structs.Deployment{
  1178  		ID:             uuid.Generate(),
  1179  		JobID:          uuid.Generate(),
  1180  		Namespace:      structs.DefaultNamespace,
  1181  		JobVersion:     2,
  1182  		JobModifyIndex: 20,
  1183  		JobCreateIndex: 18,
  1184  		TaskGroups: map[string]*structs.DeploymentState{
  1185  			"web": {
  1186  				DesiredTotal: 10,
  1187  			},
  1188  		},
  1189  		Status:            structs.DeploymentStatusRunning,
  1190  		StatusDescription: structs.DeploymentStatusDescriptionRunning,
  1191  		ModifyIndex:       23,
  1192  		CreateIndex:       21,
  1193  	}
  1194  }
  1195  
  1196  func Plan() *structs.Plan {
  1197  	return &structs.Plan{
  1198  		Priority: 50,
  1199  	}
  1200  }
  1201  
  1202  func PlanResult() *structs.PlanResult {
  1203  	return &structs.PlanResult{}
  1204  }
  1205  
  1206  func ACLPolicy() *structs.ACLPolicy {
  1207  	ap := &structs.ACLPolicy{
  1208  		Name:        fmt.Sprintf("policy-%s", uuid.Generate()),
  1209  		Description: "Super cool policy!",
  1210  		Rules: `
  1211  		namespace "default" {
  1212  			policy = "write"
  1213  		}
  1214  		node {
  1215  			policy = "read"
  1216  		}
  1217  		agent {
  1218  			policy = "read"
  1219  		}
  1220  		`,
  1221  		CreateIndex: 10,
  1222  		ModifyIndex: 20,
  1223  	}
  1224  	ap.SetHash()
  1225  	return ap
  1226  }
  1227  
  1228  func ACLToken() *structs.ACLToken {
  1229  	tk := &structs.ACLToken{
  1230  		AccessorID:  uuid.Generate(),
  1231  		SecretID:    uuid.Generate(),
  1232  		Name:        "my cool token " + uuid.Generate(),
  1233  		Type:        "client",
  1234  		Policies:    []string{"foo", "bar"},
  1235  		Global:      false,
  1236  		CreateTime:  time.Now().UTC(),
  1237  		CreateIndex: 10,
  1238  		ModifyIndex: 20,
  1239  	}
  1240  	tk.SetHash()
  1241  	return tk
  1242  }
  1243  
  1244  func ACLManagementToken() *structs.ACLToken {
  1245  	return &structs.ACLToken{
  1246  		AccessorID:  uuid.Generate(),
  1247  		SecretID:    uuid.Generate(),
  1248  		Name:        "management " + uuid.Generate(),
  1249  		Type:        "management",
  1250  		Global:      true,
  1251  		CreateTime:  time.Now().UTC(),
  1252  		CreateIndex: 10,
  1253  		ModifyIndex: 20,
  1254  	}
  1255  }
  1256  
  1257  func ScalingPolicy() *structs.ScalingPolicy {
  1258  	return &structs.ScalingPolicy{
  1259  		ID:  uuid.Generate(),
  1260  		Min: 1,
  1261  		Max: 100,
  1262  		Target: map[string]string{
  1263  			structs.ScalingTargetNamespace: structs.DefaultNamespace,
  1264  			structs.ScalingTargetJob:       uuid.Generate(),
  1265  			structs.ScalingTargetGroup:     uuid.Generate(),
  1266  		},
  1267  		Policy: map[string]interface{}{
  1268  			"a": "b",
  1269  		},
  1270  		Enabled:     true,
  1271  		CreateIndex: 10,
  1272  		ModifyIndex: 20,
  1273  	}
  1274  }
  1275  
  1276  func JobWithScalingPolicy() (*structs.Job, *structs.ScalingPolicy) {
  1277  	job := Job()
  1278  	policy := &structs.ScalingPolicy{
  1279  		ID:      uuid.Generate(),
  1280  		Min:     int64(job.TaskGroups[0].Count),
  1281  		Max:     int64(job.TaskGroups[0].Count),
  1282  		Policy:  map[string]interface{}{},
  1283  		Enabled: true,
  1284  	}
  1285  	policy.TargetTaskGroup(job, job.TaskGroups[0])
  1286  	job.TaskGroups[0].Scaling = policy
  1287  	return job, policy
  1288  }
  1289  
  1290  func CSIPlugin() *structs.CSIPlugin {
  1291  	return &structs.CSIPlugin{
  1292  		ID:                 uuid.Generate(),
  1293  		Provider:           "com.hashicorp:mock",
  1294  		Version:            "0.1",
  1295  		ControllerRequired: true,
  1296  		Controllers:        map[string]*structs.CSIInfo{},
  1297  		Nodes:              map[string]*structs.CSIInfo{},
  1298  		Allocations:        []*structs.AllocListStub{},
  1299  		ControllersHealthy: 0,
  1300  		NodesHealthy:       0,
  1301  	}
  1302  }
  1303  
  1304  func CSIVolume(plugin *structs.CSIPlugin) *structs.CSIVolume {
  1305  	return &structs.CSIVolume{
  1306  		ID:                  uuid.Generate(),
  1307  		Name:                "test-vol",
  1308  		ExternalID:          "vol-01",
  1309  		Namespace:           "default",
  1310  		Topologies:          []*structs.CSITopology{},
  1311  		AccessMode:          structs.CSIVolumeAccessModeSingleNodeWriter,
  1312  		AttachmentMode:      structs.CSIVolumeAttachmentModeFilesystem,
  1313  		MountOptions:        &structs.CSIMountOptions{},
  1314  		Secrets:             structs.CSISecrets{},
  1315  		Parameters:          map[string]string{},
  1316  		Context:             map[string]string{},
  1317  		ReadAllocs:          map[string]*structs.Allocation{},
  1318  		WriteAllocs:         map[string]*structs.Allocation{},
  1319  		ReadClaims:          map[string]*structs.CSIVolumeClaim{},
  1320  		WriteClaims:         map[string]*structs.CSIVolumeClaim{},
  1321  		PastClaims:          map[string]*structs.CSIVolumeClaim{},
  1322  		PluginID:            plugin.ID,
  1323  		Provider:            plugin.Provider,
  1324  		ProviderVersion:     plugin.Version,
  1325  		ControllerRequired:  plugin.ControllerRequired,
  1326  		ControllersHealthy:  plugin.ControllersHealthy,
  1327  		ControllersExpected: len(plugin.Controllers),
  1328  		NodesHealthy:        plugin.NodesHealthy,
  1329  		NodesExpected:       len(plugin.Nodes),
  1330  	}
  1331  }