...

Source file src/edge-infra.dev/pkg/edge/api/graph/resolver/bootstrap_queries_orchestrator_test.go

Documentation: edge-infra.dev/pkg/edge/api/graph/resolver

     1  package resolver
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"net/http"
     8  	"testing"
     9  
    10  	"cloud.google.com/go/secretmanager/apiv1/secretmanagerpb"
    11  
    12  	"edge-infra.dev/pkg/edge/api/graph/model"
    13  	seeding "edge-infra.dev/pkg/edge/api/graph/test"
    14  	"edge-infra.dev/pkg/edge/api/middleware"
    15  	"edge-infra.dev/pkg/edge/api/mocks"
    16  	"edge-infra.dev/pkg/edge/api/types"
    17  	"edge-infra.dev/pkg/edge/constants"
    18  	"edge-infra.dev/pkg/edge/k8objectsutils"
    19  	"edge-infra.dev/pkg/lib/runtime/version"
    20  	"edge-infra.dev/pkg/sds/clustersecrets/breakglass"
    21  	"edge-infra.dev/pkg/sds/clustersecrets/grub"
    22  
    23  	"github.com/golang/mock/gomock"
    24  	"github.com/stretchr/testify/assert"
    25  	corev1 "k8s.io/api/core/v1"
    26  )
    27  
    28  var testKeyValues = []*model.KeyValuesOutput{
    29  	{
    30  		Key:   "",
    31  		Value: "docker config vals",
    32  	},
    33  }
    34  var DockerPullSM = []*model.SecretManagerResponse{{
    35  	Name:    "name",
    36  	Project: "project",
    37  	Values:  testKeyValues,
    38  }}
    39  var terminalBootstrapConfig = `ack_bootstrap: true
    40  first_node: true
    41  grub_hash: sensitiveGrubHash
    42  grub_user: recovery
    43  hostname: testNode
    44  ncr-edge:
    45    bootstrap-payload:
    46      clusterCaHash: sensitiveClusterHash
    47      clusterEdgeId: d2eda5c6-7dc5-4b38-9ea1-136756887628
    48    edge-infra-version: 0.20.7
    49    parameters:
    50      api-endpoint: https://dev1.edge-preprod.dev/api/v2
    51      cluster-edge-id: d2eda5c6-7dc5-4b38-9ea1-136756887628
    52      organization: edge-org
    53      upload-ca-hash: /etc/kubernetes/pki/ca.crt
    54  	token: sesitiveBootstrapToken
    55  pod_subnet: x.x.x.x/x
    56  role: controlplane
    57  service_subnet: x.x.x.x/x
    58  vip_address: x.x.x.x
    59  zylevel0_hash: 'sensitiveHash123'`
    60  
    61  var sanitizedTerminalBootstrapConfig = `ack_bootstrap: true
    62  first_node: true
    63  grub_hash: ******************
    64  grub_user: ******************
    65  hostname: testNode
    66  ncr-edge:
    67    bootstrap-payload:
    68      clusterCaHash: ******************
    69      clusterEdgeId: d2eda5c6-7dc5-4b38-9ea1-136756887628
    70    edge-infra-version: 0.20.7
    71    parameters:
    72      api-endpoint: https://dev1.edge-preprod.dev/api/v2
    73      cluster-edge-id: d2eda5c6-7dc5-4b38-9ea1-136756887628
    74      organization: edge-org
    75      upload-ca-hash: /etc/kubernetes/pki/ca.crt
    76  	token: ******************
    77  pod_subnet: x.x.x.x/x
    78  role: controlplane
    79  service_subnet: x.x.x.x/x
    80  vip_address: x.x.x.x
    81  zylevel0_hash: ******************`
    82  
    83  var edgeOSVersion = "1.10.0"
    84  
    85  func TestGetBootrapperRoles(t *testing.T) {
    86  	ls := getRoleForLumper(false)
    87  	assert.Equal(t, 1, len(ls))
    88  	ls = getRoleForLumper(true)
    89  	assert.Equal(t, 2, len(ls))
    90  }
    91  
    92  func TestSanitizeTerminalBootstrapConfig(t *testing.T) {
    93  	sanitized := sanitizeTerminalBootstrapConfig(terminalBootstrapConfig)
    94  	assert.Equal(t, sanitizedTerminalBootstrapConfig, sanitized)
    95  }
    96  
    97  func TestGetDockerPullSecret(t *testing.T) {
    98  	mock := gomock.NewController(t)
    99  	service := mocks.NewMockGCPService(mock)
   100  	service.EXPECT().
   101  		GetSecrets(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
   102  		Return(DockerPullSM, nil).AnyTimes()
   103  
   104  	r := &Resolver{GCPService: service, Config: &types.Config{Bff: types.BffConfig{TopLevelProjectID: "test"}}}
   105  	secret, err := r.getDockerPullSecret(context.Background(), "lumper-system")
   106  	assert.NoError(t, err)
   107  	k8sSec := corev1.Secret{}
   108  	err = json.Unmarshal([]byte(secret), &k8sSec)
   109  	assert.NoError(t, err)
   110  	assert.Equal(t, "lumper-system", k8sSec.Namespace)
   111  	assert.Equal(t, constants.EdgeDockerSecret, k8sSec.Name)
   112  	assert.Equal(t, corev1.SecretTypeDockerConfigJson, k8sSec.Type)
   113  	val, ok := k8sSec.Data[corev1.DockerConfigJsonKey]
   114  	assert.Equal(t, true, ok)
   115  	assert.Equal(t, []byte("docker config vals"), val)
   116  }
   117  
   118  func TestBeginTerminalBootstrap(t *testing.T) {
   119  	mock := gomock.NewController(t)
   120  
   121  	mockGCP := mocks.NewMockGcpClientService(mock)
   122  	mockSecretManager := mocks.NewMockSecretManagerService(mock)
   123  	mockGCP.EXPECT().GetSecretClient(gomock.Any(), gomock.Any()).Return(mockSecretManager, nil).AnyTimes()
   124  
   125  	cluster := seeding.Clusters[0].ConvertToModel()
   126  
   127  	grubSecret, _ := grub.New("")
   128  	grubBytes, _ := grubSecret.ToBytes()
   129  	breakglassSecret, _ := breakglass.New("")
   130  	breakglassBytes, _ := breakglassSecret.ToBytes()
   131  
   132  	mockSecretManager.EXPECT().GetLatestSecretValueInfo(gomock.Any(), k8objectsutils.NameWithPrefix(breakglass.HashedSecretName, cluster.ClusterEdgeID)).Return(&secretmanagerpb.SecretVersion{Name: "projects/*/secrets/*/versions/1"}, nil).AnyTimes()
   133  	mockSecretManager.EXPECT().GetLatestSecretValueInfo(gomock.Any(), k8objectsutils.NameWithPrefix(grub.HashedSecretName, cluster.ClusterEdgeID)).Return(&secretmanagerpb.SecretVersion{Name: "projects/*/secrets/*/versions/1"}, nil).AnyTimes()
   134  	mockSecretManager.EXPECT().GetSecretVersionValue(gomock.Any(), k8objectsutils.NameWithPrefix(breakglass.HashedSecretName, cluster.ClusterEdgeID), "1").Return(breakglassBytes, nil).AnyTimes()
   135  	mockSecretManager.EXPECT().GetSecretVersionValue(gomock.Any(), k8objectsutils.NameWithPrefix(grub.HashedSecretName, cluster.ClusterEdgeID), "1").Return(grubBytes, nil).AnyTimes()
   136  	mockSecretManager.EXPECT().GetSecretVersionValue(gomock.Any(), k8objectsutils.NameWithPrefix(breakglass.PlainSecretName, cluster.ClusterEdgeID), "hashedVersion-1").Return([]byte(breakglassSecret.Plain()), nil).AnyTimes()
   137  	mockSecretManager.EXPECT().GetSecretVersionValue(gomock.Any(), k8objectsutils.NameWithPrefix(grub.PlainSecretName, cluster.ClusterEdgeID), "hashedVersion-1").Return([]byte(grubSecret.Plain()), nil).AnyTimes()
   138  
   139  	gcpService := mocks.NewMockGCPService(mock)
   140  	gcpService.EXPECT().
   141  		GetSecrets(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
   142  		Return(DockerPullSM, nil).AnyTimes()
   143  	gcpService.EXPECT().
   144  		AddSecret(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
   145  		Return(nil).AnyTimes()
   146  	gcpService.EXPECT().
   147  		DeleteSecret(gomock.Any(), gomock.Any(), gomock.Any()).Return(true, nil).AnyTimes()
   148  
   149  	terminal := seeding.Terminals[0].ConvertToModel()
   150  	terminal.Interfaces = []*model.TerminalInterface{seeding.TerminalInterfaces[0].ConvertToModel()}
   151  	terminal.Interfaces[0].Addresses = []*model.TerminalAddress{seeding.TerminalAddresses[0].ConvertToModel()}
   152  	terminalService := mocks.NewMockTerminalService(mock)
   153  	activationCodeService := mocks.NewMockActivationCode(mock)
   154  	terminalService.EXPECT().GetTerminal(gomock.Any(), gomock.Any(), gomock.Any()).Return(&terminal, nil).AnyTimes()
   155  
   156  	bannerService := mocks.NewMockBannerService(mock)
   157  	bannerService.EXPECT().GetClusterInfraInfo(gomock.Any(), gomock.Any()).Return(&model.Cluster{ClusterEdgeID: "resr"}, nil).AnyTimes()
   158  	bannerService.EXPECT().GetBanner(gomock.Any(), gomock.Any()).Return(&model.Banner{}, nil).AnyTimes()
   159  
   160  	clusterConfig := model.ClusterConfig{ClusterEdgeID: seeding.ClusterConfig[0].ClusterEdgeID}
   161  	for _, config := range seeding.ClusterConfig {
   162  		clusterConfig, _ = config.ConvertToModel(clusterConfig)
   163  	}
   164  	terminalService.EXPECT().
   165  		GetTerminalBootstrapConfig(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Eq("testEdgeAPIURL.dev")).
   166  		Return("cluster-config", nil).AnyTimes()
   167  
   168  	activationCodeService.EXPECT().MarkUsed(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
   169  
   170  	storeClusterService := mocks.NewMockStoreClusterService(mock)
   171  	storeClusterService.EXPECT().GetCluster(gomock.Any(), gomock.Any()).Return(&cluster, nil).AnyTimes()
   172  	storeClusterService.EXPECT().GetClusterByClusterEdgeID(gomock.Any(), gomock.Any()).Return(types.Cluster{}, nil).AnyTimes()
   173  
   174  	tenant := model.Tenant{}
   175  	tenantService := mocks.NewMockTenantService(mock)
   176  	tenantService.EXPECT().GetTenantByBannerID(gomock.Any(), gomock.Any()).Return(&tenant, nil).AnyTimes()
   177  
   178  	compatibilityService := mocks.NewMockCompatibilityService(mock)
   179  	artifactCompatibility := model.ArtifactCompatibility{
   180  		Artifact: &model.ArtifactVersion{
   181  			Name:    "store",
   182  			Version: version.New().SemVer,
   183  		},
   184  		NthIndex: 2,
   185  		CompatibleArtifacts: []*model.ArtifactVersion{
   186  			{
   187  				Name:    "edge-os",
   188  				Version: "1.10",
   189  			},
   190  		},
   191  	}
   192  	compatibilityService.EXPECT().GetArtifactVersionCompatibility(gomock.Any(), gomock.Any(), gomock.Any()).Return(&artifactCompatibility, nil).AnyTimes()
   193  	clusterNetworkServices := []*model.ClusterNetworkServiceInfo{}
   194  	storeClusterService.EXPECT().GetClusterNetworkServices(gomock.Any(), gomock.Any()).Return(clusterNetworkServices, nil).AnyTimes()
   195  
   196  	clusterConfigService := mocks.NewMockClusterConfigService(mock)
   197  	clusterConfigService.EXPECT().GetClusterConfig(gomock.Any(), gomock.Any()).Return(&clusterConfig, nil).AnyTimes()
   198  
   199  	secretService := mocks.NewMockSecretService(mock)
   200  	secretService.EXPECT().
   201  		DeleteExternalSecret(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
   202  		Return(nil).AnyTimes()
   203  
   204  	bootstrapService := mocks.NewMockBootstrapService(mock)
   205  	bootstrapService.EXPECT().CreateClusterBootstrapTokenEntry(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
   206  
   207  	clusterCaHash := "cluster-ca-hash"
   208  	registrationService := mocks.NewMockRegistrationService(mock)
   209  	registrationService.EXPECT().ClusterCaHash(gomock.Any(), gomock.Any()).Return(clusterCaHash, nil).AnyTimes()
   210  
   211  	r := &Resolver{
   212  		GCPService: gcpService,
   213  		Config: &types.Config{
   214  			EdgeAPIEndpoint: "testEdgeAPIURL.dev",
   215  			Bff:             types.BffConfig{TopLevelProjectID: "test"},
   216  		},
   217  		TerminalService:       terminalService,
   218  		StoreClusterService:   storeClusterService,
   219  		TenantService:         tenantService,
   220  		ClusterConfigService:  clusterConfigService,
   221  		SecretService:         secretService,
   222  		RegistrationService:   registrationService,
   223  		BootstrapService:      bootstrapService,
   224  		CompatibilityService:  compatibilityService,
   225  		GCPClientService:      mockGCP,
   226  		ActivationCodeService: activationCodeService,
   227  		BannerService:         bannerService,
   228  	}
   229  	qr := queryResolver{r}
   230  
   231  	ctx := context.WithValue(context.Background(), middleware.TerminalIDCtxKey, terminal.TerminalID)
   232  	ctx = context.WithValue(ctx, middleware.EdgeAPIEndpointCtxKey, "mockEdgeAPIURL.dev")
   233  	terminalBootstrap, err := qr.beginTerminalBootstrap(ctx, nil, nil)
   234  	assert.NoError(t, err)
   235  	assert.Equal(t, "cluster-config", terminalBootstrap.Configuration)
   236  
   237  	terminalBootstrap, err = qr.beginTerminalBootstrap(ctx, []string{"fa:79:6a:6c:38:bb"}, &edgeOSVersion)
   238  	expectedErr := fmt.Sprintf(`status code %d: the MAC address of this terminal does not match the MAC registered for this activation
   239  		code - please check the activation code and try again`, http.StatusBadRequest)
   240  	assert.EqualError(t, err, expectedErr)
   241  	assert.Nil(t, terminalBootstrap)
   242  
   243  	terminalBootstrap, err = qr.beginTerminalBootstrap(ctx, []string{"fa:79:6a:6c:38:bb", "00:00:5e:00:53:af"}, &edgeOSVersion)
   244  	assert.NoError(t, err)
   245  	assert.Equal(t, "cluster-config", terminalBootstrap.Configuration)
   246  }
   247  

View as plain text