github.com/hernad/nomad@v1.6.112/nomad/structs/node_pool_test.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package structs
     5  
     6  import (
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/hernad/nomad/ci"
    11  	"github.com/hernad/nomad/helper/pointer"
    12  	"github.com/shoenig/test/must"
    13  )
    14  
    15  func TestNodePool_Copy(t *testing.T) {
    16  	ci.Parallel(t)
    17  
    18  	pool := &NodePool{
    19  		Name:        "original",
    20  		Description: "original node pool",
    21  		Meta:        map[string]string{"original": "true"},
    22  		SchedulerConfiguration: &NodePoolSchedulerConfiguration{
    23  			SchedulerAlgorithm:            SchedulerAlgorithmSpread,
    24  			MemoryOversubscriptionEnabled: pointer.Of(false),
    25  		},
    26  	}
    27  	poolCopy := pool.Copy()
    28  	poolCopy.Name = "copy"
    29  	poolCopy.Description = "copy of original pool"
    30  	poolCopy.Meta["original"] = "false"
    31  	poolCopy.Meta["new_key"] = "true"
    32  	poolCopy.SchedulerConfiguration.SchedulerAlgorithm = SchedulerAlgorithmBinpack
    33  	poolCopy.SchedulerConfiguration.MemoryOversubscriptionEnabled = pointer.Of(true)
    34  
    35  	must.NotEq(t, pool, poolCopy)
    36  	must.NotEq(t, pool.Meta, poolCopy.Meta)
    37  	must.NotEq(t, pool.SchedulerConfiguration, poolCopy.SchedulerConfiguration)
    38  }
    39  
    40  func TestNodePool_Validate(t *testing.T) {
    41  	ci.Parallel(t)
    42  
    43  	testCases := []struct {
    44  		name        string
    45  		pool        *NodePool
    46  		expectedErr string
    47  	}{
    48  		{
    49  			name: "valid pool",
    50  			pool: &NodePool{
    51  				Name:        "valid",
    52  				Description: "ok",
    53  			},
    54  		},
    55  		{
    56  			name: "invalid pool name character",
    57  			pool: &NodePool{
    58  				Name: "not-valid-😢",
    59  			},
    60  			expectedErr: "invalid name",
    61  		},
    62  		{
    63  			name: "missing pool name",
    64  			pool: &NodePool{
    65  				Name: "",
    66  			},
    67  			expectedErr: "invalid name",
    68  		},
    69  		{
    70  			name: "invalid pool description",
    71  			pool: &NodePool{
    72  				Name:        "valid",
    73  				Description: strings.Repeat("a", 300),
    74  			},
    75  			expectedErr: "description longer",
    76  		},
    77  	}
    78  
    79  	for _, tc := range testCases {
    80  		t.Run(tc.name, func(t *testing.T) {
    81  			err := tc.pool.Validate()
    82  
    83  			if tc.expectedErr != "" {
    84  				must.ErrorContains(t, err, tc.expectedErr)
    85  			} else {
    86  				must.NoError(t, err)
    87  			}
    88  		})
    89  	}
    90  }
    91  
    92  func TestNodePool_IsBuiltIn(t *testing.T) {
    93  	ci.Parallel(t)
    94  
    95  	testCases := []struct {
    96  		name    string
    97  		pool    *NodePool
    98  		builtIn bool
    99  	}{
   100  		{
   101  			name: "all",
   102  			pool: &NodePool{
   103  				Name: NodePoolAll,
   104  			},
   105  			builtIn: true,
   106  		},
   107  		{
   108  			name: "default",
   109  			pool: &NodePool{
   110  				Name: NodePoolDefault,
   111  			},
   112  			builtIn: true,
   113  		},
   114  		{
   115  			name: "not built-in",
   116  			pool: &NodePool{
   117  				Name: "not-built-in",
   118  			},
   119  			builtIn: false,
   120  		},
   121  	}
   122  
   123  	for _, tc := range testCases {
   124  		t.Run(tc.name, func(t *testing.T) {
   125  			got := tc.pool.IsBuiltIn()
   126  			must.Eq(t, tc.builtIn, got)
   127  		})
   128  	}
   129  }
   130  
   131  func TestNodePool_MemoryOversubscriptionEnabled(t *testing.T) {
   132  	ci.Parallel(t)
   133  
   134  	testCases := []struct {
   135  		name     string
   136  		pool     *NodePool
   137  		global   *SchedulerConfiguration
   138  		expected bool
   139  	}{
   140  		{
   141  			name: "global used if pool is nil",
   142  			pool: nil,
   143  			global: &SchedulerConfiguration{
   144  				MemoryOversubscriptionEnabled: true,
   145  			},
   146  			expected: true,
   147  		},
   148  		{
   149  			name: "global used if pool doesn't have scheduler config",
   150  			pool: &NodePool{},
   151  			global: &SchedulerConfiguration{
   152  				MemoryOversubscriptionEnabled: true,
   153  			},
   154  			expected: true,
   155  		},
   156  		{
   157  			name: "global used if pool doesn't specify memory oversub",
   158  			pool: &NodePool{
   159  				SchedulerConfiguration: &NodePoolSchedulerConfiguration{},
   160  			},
   161  			global: &SchedulerConfiguration{
   162  				MemoryOversubscriptionEnabled: true,
   163  			},
   164  			expected: true,
   165  		},
   166  		{
   167  			name: "pool overrides global if it defines memory oversub",
   168  			pool: &NodePool{
   169  				SchedulerConfiguration: &NodePoolSchedulerConfiguration{
   170  					MemoryOversubscriptionEnabled: pointer.Of(false),
   171  				},
   172  			},
   173  			global: &SchedulerConfiguration{
   174  				MemoryOversubscriptionEnabled: true,
   175  			},
   176  			expected: false,
   177  		},
   178  		{
   179  			name: "pool used if global is nil",
   180  			pool: &NodePool{
   181  				SchedulerConfiguration: &NodePoolSchedulerConfiguration{
   182  					MemoryOversubscriptionEnabled: pointer.Of(true),
   183  				},
   184  			},
   185  			global:   nil,
   186  			expected: true,
   187  		},
   188  	}
   189  
   190  	for _, tc := range testCases {
   191  		t.Run(tc.name, func(t *testing.T) {
   192  			got := tc.pool.MemoryOversubscriptionEnabled(tc.global)
   193  			must.Eq(t, got, tc.expected)
   194  		})
   195  	}
   196  }