github.com/djenriquez/nomad-1@v0.8.1/scheduler/annotate_test.go (about)

     1  package scheduler
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  
     7  	"github.com/hashicorp/nomad/nomad/structs"
     8  )
     9  
    10  func TestAnnotateTaskGroup_Updates(t *testing.T) {
    11  	annotations := &structs.PlanAnnotations{
    12  		DesiredTGUpdates: map[string]*structs.DesiredUpdates{
    13  			"foo": {
    14  				Ignore:            1,
    15  				Place:             2,
    16  				Migrate:           3,
    17  				Stop:              4,
    18  				InPlaceUpdate:     5,
    19  				DestructiveUpdate: 6,
    20  				Canary:            7,
    21  			},
    22  		},
    23  	}
    24  
    25  	tgDiff := &structs.TaskGroupDiff{
    26  		Type: structs.DiffTypeEdited,
    27  		Name: "foo",
    28  	}
    29  	expected := &structs.TaskGroupDiff{
    30  		Type: structs.DiffTypeEdited,
    31  		Name: "foo",
    32  		Updates: map[string]uint64{
    33  			UpdateTypeIgnore:            1,
    34  			UpdateTypeCreate:            2,
    35  			UpdateTypeMigrate:           3,
    36  			UpdateTypeDestroy:           4,
    37  			UpdateTypeInplaceUpdate:     5,
    38  			UpdateTypeDestructiveUpdate: 6,
    39  			UpdateTypeCanary:            7,
    40  		},
    41  	}
    42  
    43  	if err := annotateTaskGroup(tgDiff, annotations); err != nil {
    44  		t.Fatalf("annotateTaskGroup(%#v, %#v) failed: %#v", tgDiff, annotations, err)
    45  	}
    46  
    47  	if !reflect.DeepEqual(tgDiff, expected) {
    48  		t.Fatalf("got %#v, want %#v", tgDiff, expected)
    49  	}
    50  }
    51  
    52  func TestAnnotateCountChange_NonEdited(t *testing.T) {
    53  	tg := &structs.TaskGroupDiff{}
    54  	tgOrig := &structs.TaskGroupDiff{}
    55  	annotateCountChange(tg)
    56  	if !reflect.DeepEqual(tgOrig, tg) {
    57  		t.Fatalf("annotateCountChange(%#v) should not have caused any annotation: %#v", tgOrig, tg)
    58  	}
    59  }
    60  
    61  func TestAnnotateCountChange(t *testing.T) {
    62  	up := &structs.FieldDiff{
    63  		Type: structs.DiffTypeEdited,
    64  		Name: "Count",
    65  		Old:  "1",
    66  		New:  "3",
    67  	}
    68  	down := &structs.FieldDiff{
    69  		Type: structs.DiffTypeEdited,
    70  		Name: "Count",
    71  		Old:  "3",
    72  		New:  "1",
    73  	}
    74  	tgUp := &structs.TaskGroupDiff{
    75  		Type:   structs.DiffTypeEdited,
    76  		Fields: []*structs.FieldDiff{up},
    77  	}
    78  	tgDown := &structs.TaskGroupDiff{
    79  		Type:   structs.DiffTypeEdited,
    80  		Fields: []*structs.FieldDiff{down},
    81  	}
    82  
    83  	// Test the up case
    84  	if err := annotateCountChange(tgUp); err != nil {
    85  		t.Fatalf("annotateCountChange(%#v) failed: %v", tgUp, err)
    86  	}
    87  	countDiff := tgUp.Fields[0]
    88  	if len(countDiff.Annotations) != 1 || countDiff.Annotations[0] != AnnotationForcesCreate {
    89  		t.Fatalf("incorrect annotation: %#v", tgUp)
    90  	}
    91  
    92  	// Test the down case
    93  	if err := annotateCountChange(tgDown); err != nil {
    94  		t.Fatalf("annotateCountChange(%#v) failed: %v", tgDown, err)
    95  	}
    96  	countDiff = tgDown.Fields[0]
    97  	if len(countDiff.Annotations) != 1 || countDiff.Annotations[0] != AnnotationForcesDestroy {
    98  		t.Fatalf("incorrect annotation: %#v", tgDown)
    99  	}
   100  }
   101  
   102  func TestAnnotateTask_NonEdited(t *testing.T) {
   103  	tgd := &structs.TaskGroupDiff{Type: structs.DiffTypeNone}
   104  	td := &structs.TaskDiff{Type: structs.DiffTypeNone}
   105  	tdOrig := &structs.TaskDiff{Type: structs.DiffTypeNone}
   106  	annotateTask(td, tgd)
   107  	if !reflect.DeepEqual(tdOrig, td) {
   108  		t.Fatalf("annotateTask(%#v) should not have caused any annotation: %#v", tdOrig, td)
   109  	}
   110  }
   111  
   112  func TestAnnotateTask(t *testing.T) {
   113  	cases := []struct {
   114  		Diff    *structs.TaskDiff
   115  		Parent  *structs.TaskGroupDiff
   116  		Desired string
   117  	}{
   118  		{
   119  			Diff: &structs.TaskDiff{
   120  				Type: structs.DiffTypeEdited,
   121  				Fields: []*structs.FieldDiff{
   122  					{
   123  						Type: structs.DiffTypeEdited,
   124  						Name: "Driver",
   125  						Old:  "docker",
   126  						New:  "exec",
   127  					},
   128  				},
   129  			},
   130  			Parent:  &structs.TaskGroupDiff{Type: structs.DiffTypeEdited},
   131  			Desired: AnnotationForcesDestructiveUpdate,
   132  		},
   133  		{
   134  			Diff: &structs.TaskDiff{
   135  				Type: structs.DiffTypeEdited,
   136  				Fields: []*structs.FieldDiff{
   137  					{
   138  						Type: structs.DiffTypeEdited,
   139  						Name: "User",
   140  						Old:  "alice",
   141  						New:  "bob",
   142  					},
   143  				},
   144  			},
   145  			Parent:  &structs.TaskGroupDiff{Type: structs.DiffTypeEdited},
   146  			Desired: AnnotationForcesDestructiveUpdate,
   147  		},
   148  		{
   149  			Diff: &structs.TaskDiff{
   150  				Type: structs.DiffTypeEdited,
   151  				Fields: []*structs.FieldDiff{
   152  					{
   153  						Type: structs.DiffTypeAdded,
   154  						Name: "Env[foo]",
   155  						Old:  "foo",
   156  						New:  "bar",
   157  					},
   158  				},
   159  			},
   160  			Parent:  &structs.TaskGroupDiff{Type: structs.DiffTypeEdited},
   161  			Desired: AnnotationForcesDestructiveUpdate,
   162  		},
   163  		{
   164  			Diff: &structs.TaskDiff{
   165  				Type: structs.DiffTypeEdited,
   166  				Fields: []*structs.FieldDiff{
   167  					{
   168  						Type: structs.DiffTypeAdded,
   169  						Name: "Meta[foo]",
   170  						Old:  "foo",
   171  						New:  "bar",
   172  					},
   173  				},
   174  			},
   175  			Parent:  &structs.TaskGroupDiff{Type: structs.DiffTypeEdited},
   176  			Desired: AnnotationForcesDestructiveUpdate,
   177  		},
   178  		{
   179  			Diff: &structs.TaskDiff{
   180  				Type: structs.DiffTypeEdited,
   181  				Objects: []*structs.ObjectDiff{
   182  					{
   183  						Type: structs.DiffTypeAdded,
   184  						Name: "Artifact",
   185  						Fields: []*structs.FieldDiff{
   186  							{
   187  								Type: structs.DiffTypeAdded,
   188  								Name: "GetterOptions[bam]",
   189  								Old:  "",
   190  								New:  "baz",
   191  							},
   192  							{
   193  								Type: structs.DiffTypeAdded,
   194  								Name: "GetterSource",
   195  								Old:  "",
   196  								New:  "bam",
   197  							},
   198  							{
   199  								Type: structs.DiffTypeAdded,
   200  								Name: "RelativeDest",
   201  								Old:  "",
   202  								New:  "bam",
   203  							},
   204  						},
   205  					},
   206  				},
   207  			},
   208  			Parent:  &structs.TaskGroupDiff{Type: structs.DiffTypeEdited},
   209  			Desired: AnnotationForcesDestructiveUpdate,
   210  		},
   211  		{
   212  			Diff: &structs.TaskDiff{
   213  				Type: structs.DiffTypeEdited,
   214  				Objects: []*structs.ObjectDiff{
   215  					{
   216  						Type: structs.DiffTypeEdited,
   217  						Name: "Resources",
   218  						Fields: []*structs.FieldDiff{
   219  							{
   220  								Type: structs.DiffTypeEdited,
   221  								Name: "CPU",
   222  								Old:  "100",
   223  								New:  "200",
   224  							},
   225  							{
   226  								Type: structs.DiffTypeEdited,
   227  								Name: "DiskMB",
   228  								Old:  "100",
   229  								New:  "200",
   230  							},
   231  							{
   232  								Type: structs.DiffTypeEdited,
   233  								Name: "IOPS",
   234  								Old:  "100",
   235  								New:  "200",
   236  							},
   237  							{
   238  								Type: structs.DiffTypeEdited,
   239  								Name: "MemoryMB",
   240  								Old:  "100",
   241  								New:  "200",
   242  							},
   243  						},
   244  					},
   245  				},
   246  			},
   247  			Parent:  &structs.TaskGroupDiff{Type: structs.DiffTypeEdited},
   248  			Desired: AnnotationForcesDestructiveUpdate,
   249  		},
   250  		{
   251  			Diff: &structs.TaskDiff{
   252  				Type: structs.DiffTypeEdited,
   253  				Objects: []*structs.ObjectDiff{
   254  					{
   255  						Type: structs.DiffTypeEdited,
   256  						Name: "Config",
   257  						Fields: []*structs.FieldDiff{
   258  							{
   259  								Type: structs.DiffTypeEdited,
   260  								Name: "bam[1]",
   261  								Old:  "b",
   262  								New:  "c",
   263  							},
   264  						},
   265  					},
   266  				},
   267  			},
   268  			Parent:  &structs.TaskGroupDiff{Type: structs.DiffTypeEdited},
   269  			Desired: AnnotationForcesDestructiveUpdate,
   270  		},
   271  		{
   272  			Diff: &structs.TaskDiff{
   273  				Type: structs.DiffTypeEdited,
   274  				Objects: []*structs.ObjectDiff{
   275  					{
   276  						Type: structs.DiffTypeAdded,
   277  						Name: "Constraint",
   278  						Fields: []*structs.FieldDiff{
   279  							{
   280  								Type: structs.DiffTypeAdded,
   281  								Name: "LTarget",
   282  								Old:  "",
   283  								New:  "baz",
   284  							},
   285  							{
   286  								Type: structs.DiffTypeAdded,
   287  								Name: "Operand",
   288  								Old:  "",
   289  								New:  "baz",
   290  							},
   291  							{
   292  								Type: structs.DiffTypeAdded,
   293  								Name: "RTarget",
   294  								Old:  "",
   295  								New:  "baz",
   296  							},
   297  						},
   298  					},
   299  				},
   300  			},
   301  			Parent:  &structs.TaskGroupDiff{Type: structs.DiffTypeEdited},
   302  			Desired: AnnotationForcesInplaceUpdate,
   303  		},
   304  		{
   305  			Diff: &structs.TaskDiff{
   306  				Type: structs.DiffTypeEdited,
   307  				Objects: []*structs.ObjectDiff{
   308  					{
   309  						Type: structs.DiffTypeAdded,
   310  						Name: "LogConfig",
   311  						Fields: []*structs.FieldDiff{
   312  							{
   313  								Type: structs.DiffTypeAdded,
   314  								Name: "MaxFileSizeMB",
   315  								Old:  "",
   316  								New:  "10",
   317  							},
   318  							{
   319  								Type: structs.DiffTypeAdded,
   320  								Name: "MaxFiles",
   321  								Old:  "",
   322  								New:  "1",
   323  							},
   324  						},
   325  					},
   326  				},
   327  			},
   328  			Parent:  &structs.TaskGroupDiff{Type: structs.DiffTypeEdited},
   329  			Desired: AnnotationForcesInplaceUpdate,
   330  		},
   331  		{
   332  			Diff: &structs.TaskDiff{
   333  				Type: structs.DiffTypeEdited,
   334  				Objects: []*structs.ObjectDiff{
   335  					{
   336  						Type: structs.DiffTypeEdited,
   337  						Name: "Service",
   338  						Fields: []*structs.FieldDiff{
   339  							{
   340  								Type: structs.DiffTypeEdited,
   341  								Name: "PortLabel",
   342  								Old:  "baz",
   343  								New:  "baz2",
   344  							},
   345  						},
   346  					},
   347  				},
   348  			},
   349  			Parent:  &structs.TaskGroupDiff{Type: structs.DiffTypeEdited},
   350  			Desired: AnnotationForcesInplaceUpdate,
   351  		},
   352  		{
   353  			Diff: &structs.TaskDiff{
   354  				Type: structs.DiffTypeEdited,
   355  				Fields: []*structs.FieldDiff{
   356  					{
   357  						Type: structs.DiffTypeEdited,
   358  						Name: "KillTimeout",
   359  						Old:  "200",
   360  						New:  "2000000",
   361  					},
   362  				},
   363  			},
   364  			Parent:  &structs.TaskGroupDiff{Type: structs.DiffTypeEdited},
   365  			Desired: AnnotationForcesInplaceUpdate,
   366  		},
   367  		// Task deleted new parent
   368  		{
   369  			Diff: &structs.TaskDiff{
   370  				Type: structs.DiffTypeDeleted,
   371  				Fields: []*structs.FieldDiff{
   372  					{
   373  						Type: structs.DiffTypeAdded,
   374  						Name: "Driver",
   375  						Old:  "",
   376  						New:  "exec",
   377  					},
   378  				},
   379  			},
   380  			Parent:  &structs.TaskGroupDiff{Type: structs.DiffTypeAdded},
   381  			Desired: AnnotationForcesDestroy,
   382  		},
   383  		// Task Added new parent
   384  		{
   385  			Diff: &structs.TaskDiff{
   386  				Type: structs.DiffTypeAdded,
   387  				Fields: []*structs.FieldDiff{
   388  					{
   389  						Type: structs.DiffTypeAdded,
   390  						Name: "Driver",
   391  						Old:  "",
   392  						New:  "exec",
   393  					},
   394  				},
   395  			},
   396  			Parent:  &structs.TaskGroupDiff{Type: structs.DiffTypeAdded},
   397  			Desired: AnnotationForcesCreate,
   398  		},
   399  		// Task deleted existing parent
   400  		{
   401  			Diff: &structs.TaskDiff{
   402  				Type: structs.DiffTypeDeleted,
   403  				Fields: []*structs.FieldDiff{
   404  					{
   405  						Type: structs.DiffTypeAdded,
   406  						Name: "Driver",
   407  						Old:  "",
   408  						New:  "exec",
   409  					},
   410  				},
   411  			},
   412  			Parent:  &structs.TaskGroupDiff{Type: structs.DiffTypeEdited},
   413  			Desired: AnnotationForcesDestructiveUpdate,
   414  		},
   415  		// Task Added existing parent
   416  		{
   417  			Diff: &structs.TaskDiff{
   418  				Type: structs.DiffTypeAdded,
   419  				Fields: []*structs.FieldDiff{
   420  					{
   421  						Type: structs.DiffTypeAdded,
   422  						Name: "Driver",
   423  						Old:  "",
   424  						New:  "exec",
   425  					},
   426  				},
   427  			},
   428  			Parent:  &structs.TaskGroupDiff{Type: structs.DiffTypeEdited},
   429  			Desired: AnnotationForcesDestructiveUpdate,
   430  		},
   431  	}
   432  
   433  	for i, c := range cases {
   434  		annotateTask(c.Diff, c.Parent)
   435  		if len(c.Diff.Annotations) != 1 || c.Diff.Annotations[0] != c.Desired {
   436  			t.Fatalf("case %d not properly annotated; got %s, want %s", i+1, c.Diff.Annotations[0], c.Desired)
   437  		}
   438  	}
   439  }