github.com/gravitational/teleport/api@v0.0.0-20240507183017-3110591cbafc/types/instance_test.go (about)

     1  /*
     2  Copyright 2022 Gravitational, Inc.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package types
    18  
    19  import (
    20  	"testing"
    21  	"time"
    22  
    23  	"github.com/coreos/go-semver/semver"
    24  	"github.com/stretchr/testify/require"
    25  )
    26  
    27  func TestInstanceFilter(t *testing.T) {
    28  	iis := []struct {
    29  		id       string
    30  		version  string
    31  		services []SystemRole
    32  		upgrader string
    33  	}{
    34  		{
    35  			id:       "a1",
    36  			version:  "v1.2.3",
    37  			services: []SystemRole{RoleAuth},
    38  		},
    39  		{
    40  			id:       "a2",
    41  			version:  "v2.3.4",
    42  			services: []SystemRole{RoleAuth, RoleNode},
    43  			upgrader: "kube",
    44  		},
    45  		{
    46  			id:       "p1",
    47  			version:  "v1.2.1",
    48  			services: []SystemRole{RoleProxy},
    49  		},
    50  		{
    51  			id:       "p2",
    52  			version:  "v2.3.1",
    53  			services: []SystemRole{RoleProxy, RoleNode},
    54  			upgrader: "unit",
    55  		},
    56  	}
    57  
    58  	// set up group of test instances
    59  	var instances []Instance
    60  	for _, ii := range iis {
    61  		ins, err := NewInstance(ii.id, InstanceSpecV1{
    62  			Version:          ii.version,
    63  			Services:         ii.services,
    64  			ExternalUpgrader: ii.upgrader,
    65  		})
    66  
    67  		require.NoError(t, err, "id=%s", ii.id)
    68  		instances = append(instances, ins)
    69  	}
    70  
    71  	// set up test scenarios
    72  	tts := []struct {
    73  		desc    string
    74  		filter  InstanceFilter
    75  		matches []string
    76  	}{
    77  		{
    78  			desc:   "match-all",
    79  			filter: InstanceFilter{},
    80  			matches: []string{
    81  				"a1",
    82  				"a2",
    83  				"p1",
    84  				"p2",
    85  			},
    86  		},
    87  		{
    88  			desc: "match-proxies",
    89  			filter: InstanceFilter{
    90  				Services: []SystemRole{
    91  					RoleProxy,
    92  				},
    93  			},
    94  			matches: []string{
    95  				"p1",
    96  				"p2",
    97  			},
    98  		},
    99  		{
   100  			desc: "match-old",
   101  			filter: InstanceFilter{
   102  				OlderThanVersion: "v2",
   103  			},
   104  			matches: []string{
   105  				"a1",
   106  				"p1",
   107  			},
   108  		},
   109  		{
   110  			desc: "match-new",
   111  			filter: InstanceFilter{
   112  				NewerThanVersion: "v2",
   113  			},
   114  			matches: []string{
   115  				"a2",
   116  				"p2",
   117  			},
   118  		},
   119  		{
   120  			desc: "match-version-range",
   121  			filter: InstanceFilter{
   122  				NewerThanVersion: "v1.2.2",
   123  				OlderThanVersion: "v2.3.3",
   124  			},
   125  			matches: []string{
   126  				"a1",
   127  				"p2",
   128  			},
   129  		},
   130  		{
   131  			desc: "match-kube-upgrader",
   132  			filter: InstanceFilter{
   133  				ExternalUpgrader: "kube",
   134  			},
   135  			matches: []string{
   136  				"a2",
   137  			},
   138  		},
   139  		{
   140  			desc: "match-no-upgrader",
   141  			filter: InstanceFilter{
   142  				NoExtUpgrader: true,
   143  			},
   144  			matches: []string{
   145  				"a1",
   146  				"p1",
   147  			},
   148  		},
   149  	}
   150  
   151  	for _, tt := range tts {
   152  		var matches []string
   153  		for _, ins := range instances {
   154  			if tt.filter.Match(ins) {
   155  				matches = append(matches, ins.GetName())
   156  			}
   157  		}
   158  
   159  		require.Equal(t, tt.matches, matches)
   160  	}
   161  }
   162  
   163  // TestVersionShorthand verifies our ability to decode go-style semver with the more
   164  // opinionated semver library.
   165  func TestVersionShorthand(t *testing.T) {
   166  	tts := []struct {
   167  		version string
   168  		expect  string
   169  		invalid bool
   170  	}{
   171  		{
   172  			version: "v1",
   173  			expect:  "1.0.0",
   174  		},
   175  		{
   176  			version: "1.1",
   177  			expect:  "1.1.0",
   178  		},
   179  		{
   180  			version: "1",
   181  			expect:  "1.0.0",
   182  		},
   183  		{
   184  			version: "v1.2.3",
   185  			expect:  "1.2.3",
   186  		},
   187  		{
   188  			version: "v1.2",
   189  			expect:  "1.2.0",
   190  		},
   191  		{
   192  			version: "1.2.3-alpha.1",
   193  			expect:  "1.2.3-alpha.1",
   194  		},
   195  		{
   196  			version: "v1.2.3-alpha.1",
   197  			expect:  "1.2.3-alpha.1",
   198  		},
   199  		{
   200  			version: "1.2.3+amd64",
   201  			expect:  "1.2.3+amd64",
   202  		},
   203  		{
   204  			version: "1.2.3-alpha.1+amd64",
   205  			expect:  "1.2.3-alpha.1+amd64",
   206  		},
   207  		{
   208  			version: "v1.2.3-alpha.1+amd64",
   209  			expect:  "1.2.3-alpha.1+amd64",
   210  		},
   211  		{
   212  			version: "1v2.3",
   213  			invalid: true,
   214  		},
   215  		{
   216  			version: "",
   217  			invalid: true,
   218  		},
   219  		{
   220  			version: ".",
   221  			invalid: true,
   222  		},
   223  		{
   224  			version: "v",
   225  			invalid: true,
   226  		},
   227  		{
   228  			version: "vv",
   229  			invalid: true,
   230  		},
   231  		{
   232  			version: "v1-alpha.1",
   233  			invalid: true,
   234  		},
   235  		{
   236  			version: "v1.2-alpha.1",
   237  			invalid: true,
   238  		},
   239  	}
   240  
   241  	for _, tt := range tts {
   242  		vr, ok := parseVersionRelaxed(tt.version)
   243  		if tt.invalid {
   244  			require.False(t, ok, "tt=%+v", tt)
   245  			continue
   246  		}
   247  
   248  		require.True(t, ok, "tt=%+v", tt)
   249  
   250  		vs, err := semver.NewVersion(tt.expect)
   251  		require.NoError(t, err, "tt=%+v", tt)
   252  
   253  		require.Equal(t, tt.expect, vr.String(), "tt=%+v", tt)
   254  		require.True(t, vr.Equal(*vs), "tt=%+v", tt)
   255  	}
   256  }
   257  
   258  func TestInstanceControlLogExpiry(t *testing.T) {
   259  	const ttl = time.Minute
   260  	now := time.Now()
   261  	instance, err := NewInstance("test-instance", InstanceSpecV1{
   262  		LastSeen: now,
   263  	})
   264  	require.NoError(t, err)
   265  
   266  	instance.AppendControlLog(
   267  		InstanceControlLogEntry{
   268  			Type: "foo",
   269  			Time: now,
   270  			TTL:  ttl,
   271  		},
   272  		InstanceControlLogEntry{
   273  			Type: "bar",
   274  			Time: now.Add(-ttl / 2),
   275  			TTL:  ttl,
   276  		},
   277  		InstanceControlLogEntry{
   278  			Type: "bin",
   279  			Time: now.Add(-ttl * 2),
   280  			TTL:  ttl,
   281  		},
   282  		InstanceControlLogEntry{
   283  			Type: "baz",
   284  			Time: now,
   285  			TTL:  time.Hour,
   286  		},
   287  	)
   288  
   289  	require.Len(t, instance.GetControlLog(), 4)
   290  
   291  	instance.SyncLogAndResourceExpiry(ttl)
   292  
   293  	require.Len(t, instance.GetControlLog(), 3)
   294  	require.Equal(t, now.Add(time.Hour).UTC(), instance.Expiry())
   295  
   296  	instance.SetLastSeen(now.Add(ttl))
   297  
   298  	instance.SyncLogAndResourceExpiry(ttl)
   299  
   300  	require.Len(t, instance.GetControlLog(), 2)
   301  	require.Equal(t, now.Add(time.Hour).UTC(), instance.Expiry())
   302  
   303  	instance.AppendControlLog(
   304  		InstanceControlLogEntry{
   305  			Type: "long-lived",
   306  			Time: now,
   307  			TTL:  time.Hour * 2,
   308  		},
   309  	)
   310  
   311  	instance.SyncLogAndResourceExpiry(ttl)
   312  
   313  	require.Len(t, instance.GetControlLog(), 3)
   314  	require.Equal(t, now.Add(time.Hour*2).UTC(), instance.Expiry())
   315  }