...

Source file src/edge-infra.dev/pkg/edge/api/services/store_service_test.go

Documentation: edge-infra.dev/pkg/edge/api/services

     1  package services
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"encoding/json"
     7  	"errors"
     8  	"fmt"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/DATA-DOG/go-sqlmock"
    13  	kustomizeApi "github.com/fluxcd/kustomize-controller/api/v1"
    14  	sourceApi "github.com/fluxcd/source-controller/api/v1"
    15  	"github.com/lib/pq"
    16  	"github.com/stretchr/testify/assert"
    17  
    18  	"edge-infra.dev/pkg/edge/api/graph/model"
    19  	"edge-infra.dev/pkg/edge/api/services/artifacts"
    20  	sqlquery "edge-infra.dev/pkg/edge/api/sql"
    21  	"edge-infra.dev/pkg/edge/api/status"
    22  	"edge-infra.dev/pkg/edge/constants"
    23  	"edge-infra.dev/pkg/edge/constants/api/fleet"
    24  	"edge-infra.dev/pkg/edge/ctlfish/monitor"
    25  	whv1 "edge-infra.dev/pkg/f8n/warehouse/k8s/apis/v1alpha1"
    26  	"edge-infra.dev/pkg/lib/runtime/version"
    27  )
    28  
    29  var (
    30  	testStoreClusterEdgeID = "test-store-cluster-edge-id"
    31  	testNetworkID          = "dfsdgjskgsad"
    32  	testNetworkID2         = "omeromgserga"
    33  	testIP                 = "8.8.8.8"
    34  	testIP2                = "0.0.0.0"
    35  	testFamily             = "inet"
    36  	testDNSServiceType     = "dns"
    37  	testNTPServiceType     = "ntp"
    38  	testPriority           = 100
    39  	testPriority2          = 99
    40  	testNetworkIDmap       = map[string]string{testNetworkID: testDNSServiceType, testNetworkID2: testNTPServiceType}
    41  )
    42  
    43  const (
    44  	supportVersionResource     = `["{\"metadata\":{\"name\":\"test\",\"labels\":{\"feature.node.kubernetes.io/ien-version\":\"v1.15.0\"}}}","test-support-status-cluster"]`
    45  	unsupportedVersionResource = `["{\"metadata\":{\"name\":\"test\",\"labels\":{\"feature.node.kubernetes.io/ien-version\":\"v1.2.0\"}}}","test-unsupported-status-cluster"]`
    46  	noVersionResource          = `["{\"metadata\":{\"name\":\"test\",\"labels\":{\"feature.node.kubernetes.io/ien-version\":\"\"}}}","test-no-terminal-version-status-cluster"]`
    47  )
    48  
    49  func TestDeleteClusterSQLEntry(t *testing.T) {
    50  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
    51  	if err != nil {
    52  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
    53  	}
    54  	defer db.Close()
    55  	testStoreClusterEdgeID := "mv8wx3jwjgtg"
    56  	mock.ExpectExec(sqlquery.ClusterDeleteQuery).WithArgs(testStoreClusterEdgeID).
    57  		WillReturnResult(sqlmock.NewResult(1, 1))
    58  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
    59  	if err := service.DeleteStoreEntry(context.Background(), testStoreClusterEdgeID); err != nil {
    60  		t.Errorf("error was not expected while deleting cluster: %s", err)
    61  	}
    62  
    63  	if err := mock.ExpectationsWereMet(); err != nil {
    64  		t.Errorf("there were unfulfilled expectations: %s", err)
    65  	}
    66  }
    67  
    68  func TestGetClusterFromSQL(t *testing.T) {
    69  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
    70  	if err != nil {
    71  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
    72  	}
    73  	defer db.Close()
    74  	mock.ExpectQuery(sqlquery.GetClusterByEdgeID).
    75  		WithArgs("uuid-1").
    76  		WillReturnRows(mock.NewRows([]string{"cluster_edge_id", "cluster_name", "project_id", "registered", "active", "banner_edge_id", "bsl_site_id", "fleet_version"}).
    77  			AddRow("uuid-1", "test-store", "test_project_id", true, true, "banner_edge_id", "bsl_site_id", "latest"))
    78  	mock.ExpectQuery(sqlquery.SelectEdgeLabelsForCluster).
    79  		WithArgs("uuid-1").
    80  		WillReturnRows(mock.NewRows([]string{"label_edge_id", "label_key", "color", "visible", "editable", "banner_edge_id", "label_unique", "description", "label_type"}).
    81  			AddRow("label_edge_id", "test-label-key", "color", true, true, nil, true, "description", "label_type"))
    82  	mock.ExpectQuery(sqlquery.GetArtifactVersionsAndCompatibility).WithArgs(fleet.Store, version.New().SemVer).
    83  		WillReturnRows(mock.NewRows([]string{"artifact_name", "artifact_version", "nth_index", "compatible_artifact_name", "compatible_artifact_version"}).
    84  			AddRow(fleet.Store, version.New().SemVer, 2, compatibleArtifactVersionA.Name, compatibleArtifactVersionA.Version).
    85  			AddRow(fleet.Store, version.New().SemVer, 2, compatibleArtifactVersionB.Name, compatibleArtifactVersionB.Version))
    86  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
    87  	c, err := service.GetCluster(context.Background(), "uuid-1")
    88  	assert.Nil(t, err)
    89  	assert.Equal(t, "test-store", c.Name)
    90  	assert.Equal(t, "test-label-key", c.Labels[0].Key)
    91  }
    92  
    93  func TestGetClustersFromSQL(t *testing.T) {
    94  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
    95  	if err != nil {
    96  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
    97  	}
    98  	defer db.Close()
    99  	mock.ExpectQuery(sqlquery.GetClustersWithLabelQuery).
   100  		WithArgs(projectID, pq.Array([]string{"test-label-key"})).
   101  		WillReturnRows(mock.NewRows([]string{"uuid-1", "cluster_name", "project_id", "registered", "active", "banner_edge_id", "bsl_site_id", "fleet_version"}).
   102  			AddRow("uuid-2", "test-store", "test_project_id", true, true, "banner_edge_id", "bsl_site_id", "latest"))
   103  	mock.ExpectQuery(sqlquery.SelectEdgeLabelsForCluster).
   104  		WithArgs("uuid-2").
   105  		WillReturnRows(mock.NewRows([]string{"label_edge_id", "label_key", "color", "visible", "editable", "banner_edge_id", "label_unique", "description", "label_type"}).
   106  			AddRow("label_edge_id", "test-label-key", "color", true, true, nil, true, "description", "label_type"))
   107  	mock.ExpectQuery(sqlquery.GetClustersQuery).
   108  		WithArgs(projectID).
   109  		WillReturnRows(mock.NewRows([]string{"uuid", "cluster_name", "project_id", "registered", "active", "banner_edge_id", "bsl_site_id", "fleet_version"}).
   110  			AddRow("uuid-1", "test-store-1", "test_project_id", true, true, "banner_edge_id", "bsl_site_id", "latest").
   111  			AddRow("uuid-2", "test-store-2", "test_project_id", true, true, "banner_edge_id", "bsl_site_id", "latest"))
   112  	mock.ExpectQuery(sqlquery.SelectEdgeLabelsForCluster).
   113  		WithArgs("uuid-1").
   114  		WillReturnRows(mock.NewRows([]string{"label_edge_id", "label_key", "color", "visible", "editable", "banner_edge_id", "label_unique", "description", "label_type"}).
   115  			AddRow("label_edge_id", "test-label-key-1", "color", true, true, "banner_edge_id", true, "description", "label_type").
   116  			AddRow("label_edge_id", "test-label-key-2", "color", true, true, "banner_edge_id", true, "description", "label_type"))
   117  	mock.ExpectQuery(sqlquery.SelectEdgeLabelsForCluster).
   118  		WithArgs("uuid-2").
   119  		WillReturnRows(mock.NewRows([]string{"label_edge_id", "label_key", "color", "visible", "editable", "banner_edge_id", "label_unique", "description", "label_type"}).
   120  			AddRow("label_edge_id", "test-label-key-2", "color", true, true, "banner_edge_id", true, "description", "label_type"))
   121  
   122  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
   123  	clusters, err := service.GetClusters(context.Background(), projectID, []string{"test-label-key"})
   124  	assert.Nil(t, err)
   125  	assert.Equal(t, 1, len(clusters))
   126  	assert.Equal(t, "test-store", clusters[0].Name)
   127  	assert.Equal(t, "test-label-key", clusters[0].Labels[0].Key)
   128  	clusters, err = service.GetClusters(context.Background(), projectID, nil)
   129  	assert.Nil(t, err)
   130  	assert.Equal(t, 2, len(clusters))
   131  	assert.Equal(t, "test-store-1", clusters[0].Name)
   132  	assert.Equal(t, 2, len(clusters[0].Labels))
   133  	assert.Equal(t, "test-label-key-1", clusters[0].Labels[0].Key)
   134  	assert.Equal(t, "test-label-key-2", clusters[0].Labels[1].Key)
   135  	assert.Equal(t, "test-store-2", clusters[1].Name)
   136  	assert.Equal(t, 1, len(clusters[1].Labels))
   137  	assert.Equal(t, "test-label-key-2", clusters[1].Labels[0].Key)
   138  }
   139  
   140  func TestGetClustersFromSQLEmptyResponse(t *testing.T) {
   141  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   142  	if err != nil {
   143  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   144  	}
   145  	defer db.Close()
   146  	mock.ExpectQuery(sqlquery.GetClustersWithLabelQuery).
   147  		WithArgs(projectID, pq.Array([]string{"test-label-key"})).
   148  		WillReturnRows(mock.NewRows([]string{"uuid", "cluster_name", "project_id", "registered", "active", "banner_edge_id", "bsl_site_id", "labels"}))
   149  	mock.ExpectQuery(sqlquery.GetClustersQuery).
   150  		WithArgs(projectID).
   151  		WillReturnRows(mock.NewRows([]string{"uuid", "cluster_name", "project_id", "registered", "active", "banner_edge_id", "bsl_site_id", "labels"}))
   152  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
   153  	clusters, err := service.GetClusters(context.Background(), projectID, []string{"test-label-key"})
   154  	assert.Nil(t, err)
   155  	assert.Equal(t, []*model.Cluster{}, clusters)
   156  	clusters, err = service.GetClusters(context.Background(), projectID, nil)
   157  	assert.Nil(t, err)
   158  	assert.Equal(t, []*model.Cluster{}, clusters)
   159  }
   160  
   161  func TestToBucketStatusInformation(t *testing.T) {
   162  	testSyncInfo := monitor.SyncInfo{
   163  		LastUpdated:   "test-last-updated",
   164  		Revision:      "test-revision",
   165  		StatusMessage: "test-status-message",
   166  		Error:         false,
   167  		Suspended:     true,
   168  	}
   169  	bucketInfo := map[string]monitor.BucketInfo{
   170  		"test-bucket-1": {
   171  			Excludes:   "test-excludes-1",
   172  			BucketName: "test-bucket-name-1",
   173  			FluxStatus: testSyncInfo,
   174  		},
   175  	}
   176  	buckets := toBucketStatusInformation(bucketInfo)
   177  	assert.Equal(t, 1, len(buckets))
   178  	assert.Equal(t, "test-excludes-1", buckets[0].Excludes)
   179  	assert.Equal(t, "test-bucket-name-1", buckets[0].BucketName)
   180  	assert.Equal(t, "test-bucket-1", buckets[0].FluxStatus.Name)
   181  }
   182  
   183  func TestToKustomizationStatusInformation(t *testing.T) {
   184  	testSyncInfo := monitor.SyncInfo{
   185  		LastUpdated:   "test-last-updated",
   186  		Revision:      "test-revision",
   187  		StatusMessage: "test-status-message",
   188  		Error:         false,
   189  		Suspended:     true,
   190  	}
   191  	kustomizationInfo := map[string]monitor.KustomizationInfo{
   192  		"test-kustomization-1": {Path: "test-path-1", Source: "test-source-1", FluxStatus: testSyncInfo},
   193  		"test-kustomization-2": {Path: "test-path-2", Source: "test-source-2", FluxStatus: testSyncInfo},
   194  	}
   195  	kustomizations := toKustomizationStatusInformation(kustomizationInfo)
   196  	assert.Equal(t, 2, len(kustomizations))
   197  	assert.Contains(t, "test-path-1, test-path-2", kustomizations[0].Path)
   198  	assert.Contains(t, "test-source-1, test-source-2", kustomizations[0].Source)
   199  	assert.Contains(t, "test-path-1, test-path-2", kustomizations[1].Path)
   200  	assert.Contains(t, "test-source-1, test-source-2", kustomizations[1].Source)
   201  	assert.Contains(t, "test-kustomization-1 test-kustomization-2", kustomizations[0].FluxStatus.Name)
   202  	assert.Contains(t, "test-kustomization-1 test-kustomization-2", kustomizations[1].FluxStatus.Name)
   203  }
   204  
   205  func TestGetFluxStatusInfo(t *testing.T) {
   206  	testSyncInfo := monitor.SyncInfo{
   207  		LastUpdated:   "test-last-updated",
   208  		Revision:      "test-revision",
   209  		StatusMessage: "test-status-message",
   210  		Error:         false,
   211  		Suspended:     true,
   212  	}
   213  	fluxStatus := getFluxStatusInfo("test-flux-name", &testSyncInfo)
   214  	assert.Equal(t, "test-flux-name", fluxStatus.Name)
   215  	assert.Equal(t, "test-last-updated", fluxStatus.LastUpdated)
   216  	assert.Equal(t, "test-revision", fluxStatus.Revision)
   217  	assert.Equal(t, "test-status-message", fluxStatus.StatusMessage)
   218  	assert.Equal(t, false, fluxStatus.Error)
   219  	assert.Equal(t, true, fluxStatus.Suspended)
   220  }
   221  
   222  func TestCreateClusterNetworkServiceSQLEntry(t *testing.T) {
   223  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   224  	if err != nil {
   225  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   226  	}
   227  	defer db.Close()
   228  
   229  	newClusterNetworkService := model.CreateNetworkServiceInfo{
   230  		ServiceType: testDNSServiceType,
   231  		IP:          testIP2,
   232  		Family:      testFamily,
   233  		Priority:    &testPriority,
   234  	}
   235  
   236  	newClusterNetworkServices := []*model.CreateNetworkServiceInfo{&newClusterNetworkService}
   237  
   238  	mock.ExpectQuery(sqlquery.GetClusterNetworkServices).WithArgs(testStoreClusterEdgeID).WillReturnRows(mock.NewRows([]string{"network_service_id", "ip", "family", "service_type", "priority"}).
   239  		AddRow(testNetworkID, testIP, testFamily, testDNSServiceType, testPriority))
   240  	mock.ExpectQuery(sqlquery.CreateClusterNetworkServices).WithArgs(testStoreClusterEdgeID, testIP2, testFamily, testDNSServiceType, testPriority).WillReturnRows(mock.NewRows([]string{"network_service_id", "ip", "family", "service_type", "priority"}).
   241  		AddRow(testNetworkID2, testIP2, testFamily, testDNSServiceType, testPriority))
   242  
   243  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
   244  
   245  	clusterNetworkServices, err := service.CreateClusterNetworkServices(context.Background(), testStoreClusterEdgeID, newClusterNetworkServices)
   246  	if err != nil {
   247  		t.Errorf("error was not expected while creating cluster network services: %s", err)
   248  	}
   249  
   250  	expected := model.ClusterNetworkServiceInfo{
   251  		NetworkServiceID: testNetworkID2,
   252  		ServiceType:      testDNSServiceType,
   253  		IP:               testIP2,
   254  		Family:           testFamily,
   255  		Priority:         &testPriority,
   256  	}
   257  
   258  	returnedEntry := *clusterNetworkServices[0]
   259  	assert.Equal(t, returnedEntry, expected)
   260  }
   261  
   262  func TestGetClusterNetworkServiceSQLEntry(t *testing.T) {
   263  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   264  	if err != nil {
   265  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   266  	}
   267  	defer db.Close()
   268  
   269  	cluster := model.Cluster{
   270  		ClusterEdgeID: testStoreClusterEdgeID,
   271  	}
   272  
   273  	mock.ExpectQuery(sqlquery.GetClusterNetworkServices).WithArgs(testStoreClusterEdgeID).WillReturnRows(mock.NewRows([]string{"network_service_id", "ip", "family", "service_type", "priority"}).
   274  		AddRow(testNetworkID, testIP, testFamily, testDNSServiceType, testPriority))
   275  
   276  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
   277  
   278  	clusterNetworkServices, err := service.GetClusterNetworkServices(context.Background(), cluster.ClusterEdgeID)
   279  	if err != nil {
   280  		t.Errorf("error was not expected while getting cluster network services: %s", err)
   281  	}
   282  
   283  	expected := model.ClusterNetworkServiceInfo{
   284  		NetworkServiceID: testNetworkID,
   285  		ServiceType:      testDNSServiceType,
   286  		IP:               testIP,
   287  		Family:           testFamily,
   288  		Priority:         &testPriority,
   289  	}
   290  
   291  	returnedEntry := *clusterNetworkServices[0]
   292  	assert.Equal(t, returnedEntry, expected)
   293  }
   294  
   295  func TestDeleteClusterNetworkServiceSQLEntry(t *testing.T) {
   296  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   297  	if err != nil {
   298  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   299  	}
   300  	defer db.Close()
   301  
   302  	mock.ExpectQuery(sqlquery.GetClusterNetworkServiceByNetworkID).WithArgs(testStoreClusterEdgeID, testNetworkID).WillReturnRows(mock.NewRows([]string{"network_service_id", "ip", "family", "service_type", "priority"}).
   303  		AddRow(testNetworkID, testIP, testFamily, testDNSServiceType, testPriority))
   304  	mock.ExpectExec(sqlquery.DeleteClusterNetworkService).WithArgs(testStoreClusterEdgeID, testNetworkID).
   305  		WillReturnResult(sqlmock.NewResult(1, 1))
   306  
   307  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
   308  
   309  	deleted, err := service.DeleteClusterNetworkService(context.Background(), testStoreClusterEdgeID, testNetworkID)
   310  	if err != nil {
   311  		t.Errorf("error was not expected while deleting cluster network services: %s", err)
   312  	}
   313  
   314  	assert.True(t, deleted)
   315  }
   316  
   317  func TestUpdateClusterNetworkServiceSQLEntry(t *testing.T) {
   318  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   319  	if err != nil {
   320  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   321  	}
   322  	defer db.Close()
   323  
   324  	newClusterNetworkService := model.UpdateNetworkServiceInfo{
   325  		NetworkServiceID: testNetworkID,
   326  		IP:               testIP,
   327  		Family:           testFamily,
   328  		Priority:         &testPriority2,
   329  	}
   330  
   331  	newClusterNetworkServices := []*model.UpdateNetworkServiceInfo{&newClusterNetworkService}
   332  
   333  	mock.ExpectQuery(sqlquery.GetClusterNetworkServices).WithArgs(testStoreClusterEdgeID).WillReturnRows(mock.NewRows([]string{"network_service_id", "ip", "family", "service_type", "priority"}).
   334  		AddRow(testNetworkID, testIP, testFamily, testDNSServiceType, testPriority))
   335  	mock.ExpectQuery(sqlquery.UpdateClusterNetworkServices).WithArgs(testIP, testFamily, testPriority2, testNetworkID, testStoreClusterEdgeID).WillReturnRows(mock.NewRows([]string{"network_service_id", "ip", "family", "service_type", "priority"}).
   336  		AddRow(testNetworkID, testIP, testFamily, testDNSServiceType, testPriority2))
   337  
   338  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
   339  
   340  	clusterNetworkServices, err := service.UpdateClusterNetworkServices(context.Background(), testStoreClusterEdgeID, newClusterNetworkServices, testNetworkIDmap)
   341  	if err != nil {
   342  		t.Errorf("error was not expected while updating cluster network services: %s", err)
   343  	}
   344  
   345  	expected := model.ClusterNetworkServiceInfo{
   346  		NetworkServiceID: testNetworkID,
   347  		ServiceType:      testDNSServiceType,
   348  		IP:               testIP,
   349  		Family:           testFamily,
   350  		Priority:         &testPriority2,
   351  	}
   352  
   353  	returnedEntry := *clusterNetworkServices[0]
   354  	assert.Equal(t, returnedEntry, expected)
   355  }
   356  
   357  func TestCreateClusterNetworkServiceSQLEntryInvalidNTP(t *testing.T) {
   358  	db, _, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   359  	if err != nil {
   360  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   361  	}
   362  	defer db.Close()
   363  
   364  	newClusterNetworkService := model.CreateNetworkServiceInfo{
   365  		ServiceType: "ntp",
   366  		IP:          "domain!.test",
   367  		Family:      testFamily,
   368  		Priority:    &testPriority,
   369  	}
   370  
   371  	newClusterNetworkServices := []*model.CreateNetworkServiceInfo{&newClusterNetworkService}
   372  
   373  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
   374  
   375  	_, err = service.CreateClusterNetworkServices(context.Background(), testStoreClusterEdgeID, newClusterNetworkServices)
   376  	assert.Error(t, err)
   377  }
   378  
   379  func TestUpdateClusterNetworkServiceSQLEntryInvalidNTP(t *testing.T) {
   380  	db, _, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   381  	if err != nil {
   382  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   383  	}
   384  	defer db.Close()
   385  
   386  	newClusterNetworkService := model.UpdateNetworkServiceInfo{
   387  		NetworkServiceID: testNetworkID,
   388  		IP:               "8.8.8.",
   389  		Family:           testFamily,
   390  		Priority:         &testPriority,
   391  	}
   392  
   393  	newClusterNetworkServices := []*model.UpdateNetworkServiceInfo{&newClusterNetworkService}
   394  
   395  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
   396  
   397  	_, err = service.UpdateClusterNetworkServices(context.Background(), testStoreClusterEdgeID, newClusterNetworkServices, testNetworkIDmap)
   398  	assert.Error(t, err)
   399  }
   400  
   401  func TestUpdateClusterNetworkServiceSQLEntryValidNTP(t *testing.T) {
   402  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   403  	if err != nil {
   404  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   405  	}
   406  	defer db.Close()
   407  
   408  	newClusterNetworkService := model.UpdateNetworkServiceInfo{
   409  		NetworkServiceID: testNetworkID2,
   410  		IP:               "time.google.com",
   411  		Family:           testFamily,
   412  		Priority:         &testPriority,
   413  	}
   414  
   415  	newClusterNetworkServices := []*model.UpdateNetworkServiceInfo{&newClusterNetworkService}
   416  
   417  	mock.ExpectQuery(sqlquery.GetClusterNetworkServices).WithArgs(testStoreClusterEdgeID).WillReturnRows(mock.NewRows([]string{"network_service_id", "ip", "family", "service_type", "priority"}).
   418  		AddRow(testNetworkID2, testIP, testFamily, testNTPServiceType, testPriority))
   419  	mock.ExpectQuery(sqlquery.UpdateClusterNetworkServices).WithArgs("time.google.com", testFamily, testPriority, testNetworkID2, testStoreClusterEdgeID).WillReturnRows(mock.NewRows([]string{"network_service_id", "ip", "family", "service_type", "priority"}).
   420  		AddRow(testNetworkID2, "time.google.com", testFamily, testNTPServiceType, testPriority))
   421  
   422  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
   423  
   424  	clusterNetworkServices, err := service.UpdateClusterNetworkServices(context.Background(), testStoreClusterEdgeID, newClusterNetworkServices, testNetworkIDmap)
   425  	if err != nil {
   426  		t.Errorf("error was not expected while updating cluster network services: %s", err)
   427  	}
   428  
   429  	expected := model.ClusterNetworkServiceInfo{
   430  		NetworkServiceID: testNetworkID2,
   431  		ServiceType:      "ntp",
   432  		IP:               "time.google.com",
   433  		Family:           testFamily,
   434  		Priority:         &testPriority,
   435  	}
   436  
   437  	returnedEntry := *clusterNetworkServices[0]
   438  	assert.Equal(t, returnedEntry, expected)
   439  }
   440  
   441  func TestCreateClusterNetworkServiceSQLEntryNoPrioritySet(t *testing.T) {
   442  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   443  	if err != nil {
   444  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   445  	}
   446  	defer db.Close()
   447  
   448  	newClusterNetworkService := model.CreateNetworkServiceInfo{
   449  		ServiceType: testDNSServiceType,
   450  		IP:          testIP2,
   451  		Family:      testFamily,
   452  	}
   453  
   454  	newClusterNetworkServices := []*model.CreateNetworkServiceInfo{&newClusterNetworkService}
   455  
   456  	mock.ExpectQuery(sqlquery.GetClusterNetworkServices).WithArgs(testStoreClusterEdgeID).WillReturnRows(mock.NewRows([]string{"network_service_id", "ip", "family", "service_type", "priority"}).
   457  		AddRow(testNetworkID, testIP, testFamily, testDNSServiceType, testPriority))
   458  	mock.ExpectQuery(sqlquery.CreateClusterNetworkServices).WithArgs(testStoreClusterEdgeID, testIP2, testFamily, testDNSServiceType, testPriority).WillReturnRows(mock.NewRows([]string{"network_service_id", "ip", "family", "service_type", "priority"}).
   459  		AddRow(testNetworkID2, testIP2, testFamily, testDNSServiceType, testPriority))
   460  
   461  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
   462  
   463  	clusterNetworkServices, err := service.CreateClusterNetworkServices(context.Background(), testStoreClusterEdgeID, newClusterNetworkServices)
   464  	if err != nil {
   465  		t.Errorf("error was not expected while creating cluster network services: %s", err)
   466  	}
   467  
   468  	expected := model.ClusterNetworkServiceInfo{
   469  		NetworkServiceID: testNetworkID2,
   470  		ServiceType:      testDNSServiceType,
   471  		IP:               testIP2,
   472  		Family:           testFamily,
   473  		Priority:         &testPriority,
   474  	}
   475  
   476  	returnedEntry := *clusterNetworkServices[0]
   477  	assert.Equal(t, returnedEntry, expected)
   478  }
   479  
   480  func TestCreateClusterNetworkServiceSQLEntryPrioritySetToNegativeInt(t *testing.T) {
   481  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   482  	if err != nil {
   483  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   484  	}
   485  	defer db.Close()
   486  	negativePriority := -10
   487  	newClusterNetworkService := model.CreateNetworkServiceInfo{
   488  		ServiceType: testDNSServiceType,
   489  		IP:          testIP2,
   490  		Family:      testFamily,
   491  		Priority:    &negativePriority,
   492  	}
   493  
   494  	newClusterNetworkServices := []*model.CreateNetworkServiceInfo{&newClusterNetworkService}
   495  
   496  	mock.ExpectQuery(sqlquery.GetClusterNetworkServices).WithArgs(testStoreClusterEdgeID).WillReturnRows(mock.NewRows([]string{"network_service_id", "ip", "family", "service_type", "priority"}).
   497  		AddRow(testNetworkID, testIP, testFamily, testDNSServiceType, testPriority))
   498  	mock.ExpectQuery(sqlquery.CreateClusterNetworkServices).WithArgs(testStoreClusterEdgeID, testIP2, testFamily, testDNSServiceType, testPriority).WillReturnRows(mock.NewRows([]string{"network_service_id", "ip", "family", "service_type", "priority"}).
   499  		AddRow(testNetworkID2, testIP2, testFamily, testDNSServiceType, testPriority))
   500  
   501  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
   502  
   503  	clusterNetworkServices, err := service.CreateClusterNetworkServices(context.Background(), testStoreClusterEdgeID, newClusterNetworkServices)
   504  	if err != nil {
   505  		t.Errorf("error was not expected while creating cluster network services: %s", err)
   506  	}
   507  
   508  	expected := model.ClusterNetworkServiceInfo{
   509  		NetworkServiceID: testNetworkID2,
   510  		ServiceType:      testDNSServiceType,
   511  		IP:               testIP2,
   512  		Family:           testFamily,
   513  		Priority:         &testPriority,
   514  	}
   515  
   516  	returnedEntry := *clusterNetworkServices[0]
   517  	assert.Equal(t, returnedEntry, expected)
   518  }
   519  
   520  func TestCreateClusterNetworkServiceSQLEntryDuplicateIP(t *testing.T) {
   521  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   522  	if err != nil {
   523  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   524  	}
   525  	defer db.Close()
   526  
   527  	newClusterNetworkServiceWithDuplicateIP := &model.CreateNetworkServiceInfo{
   528  		ServiceType: testDNSServiceType,
   529  		IP:          testIP,
   530  		Family:      testFamily,
   531  		Priority:    &testPriority,
   532  	}
   533  	newClusterNetworkServices := []*model.CreateNetworkServiceInfo{newClusterNetworkServiceWithDuplicateIP}
   534  
   535  	mock.ExpectQuery(sqlquery.GetClusterNetworkServices).WithArgs(testStoreClusterEdgeID).WillReturnRows(mock.NewRows([]string{"network_service_id", "ip", "family", "service_type", "priority"}).
   536  		AddRow(testNetworkID, testIP, testFamily, testDNSServiceType, testPriority))
   537  
   538  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
   539  
   540  	_, err = service.CreateClusterNetworkServices(context.Background(), testStoreClusterEdgeID, newClusterNetworkServices)
   541  	assert.Error(t, err)
   542  }
   543  
   544  func TestUpdateClusterNetworkServiceSQLEntryDuplicateIP(t *testing.T) {
   545  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   546  	if err != nil {
   547  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   548  	}
   549  	defer db.Close()
   550  
   551  	clusterNetworkServiceWithDuplicateIP := &model.UpdateNetworkServiceInfo{
   552  		NetworkServiceID: testNetworkID,
   553  		IP:               testIP2,
   554  		Family:           testFamily,
   555  		Priority:         &testPriority,
   556  	}
   557  	newClusterNetworkServices := []*model.UpdateNetworkServiceInfo{clusterNetworkServiceWithDuplicateIP}
   558  
   559  	mock.ExpectQuery(sqlquery.GetClusterNetworkServices).WithArgs(testStoreClusterEdgeID).WillReturnRows(mock.NewRows([]string{"network_service_id", "ip", "family", "service_type", "priority"}).
   560  		AddRow(testNetworkID, testIP, testFamily, testNTPServiceType, testPriority).
   561  		AddRow(testNetworkID2, testIP2, testFamily, testNTPServiceType, testPriority))
   562  
   563  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
   564  
   565  	testNetworkIDmapNTP := map[string]string{testNetworkID: testNTPServiceType, testNetworkID2: testNTPServiceType}
   566  	_, err = service.UpdateClusterNetworkServices(context.Background(), testStoreClusterEdgeID, newClusterNetworkServices, testNetworkIDmapNTP)
   567  	assert.Error(t, err)
   568  }
   569  
   570  func TestUpdateStoreSiteID(t *testing.T) {
   571  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   572  	if err != nil {
   573  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   574  	}
   575  	defer db.Close()
   576  	mock.ExpectExec(sqlquery.UpdateStoreSiteIDQuery).WithArgs("testSiteID", testStoreClusterEdgeID).
   577  		WillReturnResult(sqlmock.NewResult(1, 1))
   578  
   579  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
   580  
   581  	err = service.UpdateStoreSiteID(context.Background(), testStoreClusterEdgeID, "testSiteID")
   582  
   583  	if err != nil {
   584  		t.Errorf("error was not expected while updating siteID: %s", err)
   585  	}
   586  
   587  	assert.NoError(t, err)
   588  }
   589  
   590  func TestGetEventsForCluster(t *testing.T) {
   591  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   592  	if err != nil {
   593  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   594  	}
   595  	defer db.Close()
   596  	shipmentMessage := "Applied 11 pallets: [...]"
   597  	kustoMessage := "Reconciliation finished in 4s, next run in 1m0s"
   598  	createdAt := time.Now().Format(time.RFC3339)
   599  	annotations := map[string]string{
   600  		"pallet.edge.ncr.com/created": createdAt,
   601  		"pallet.edge.ncr.com/name":    "fluxcd-syncing-config",
   602  		"pallet.edge.ncr.com/version": "0.18.0-rc.0123456789+commit.a01234b",
   603  	}
   604  	jsonData, err := json.Marshal(annotations)
   605  	assert.NoError(t, err)
   606  	mock.ExpectQuery(sqlquery.GetClusterEvents).
   607  		WithArgs("uuid-1").
   608  		WillReturnRows(mock.NewRows([]string{"event_edge_id", "event_name", "involved_kind", "involved_namespace", "involved_name", "reason", "message", "status", "source_component", "annotations", "terminal_id", "cluster_edge_id", "created_at"}).
   609  			AddRow("event_edge_id", "test-event-name", "Shipment", "", "test-shipment-name", "Succeeded", shipmentMessage, "Normal", "lumperctl", "", "terminal_id", "uuid-1", createdAt).
   610  			AddRow("event_edge_id2", "test-event-name2", "Kustomization", "flux-config", "test-kusto-name", "ReconciliationSucceeded", kustoMessage, "Normal", "kustomize-controller", string(jsonData), "terminal_id", "uuid-1", createdAt))
   611  
   612  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
   613  	events, err := service.GetEventsForCluster(context.Background(), "uuid-1")
   614  	assert.NoError(t, err)
   615  	assert.NotNil(t, events)
   616  	assert.Equal(t, 2, len(events))
   617  
   618  	for _, event := range events {
   619  		if event.EventEdgeID == "event_edge_id2" {
   620  			assert.Equal(t, "test-event-name2", event.Name)
   621  			assert.Equal(t, "Kustomization", event.InvolvedObject.Kind)
   622  			assert.Equal(t, "flux-config", *event.InvolvedObject.Namespace)
   623  			assert.Equal(t, "test-kusto-name", event.InvolvedObject.Name)
   624  			assert.Equal(t, "ReconciliationSucceeded", event.Reason)
   625  			assert.Equal(t, kustoMessage, event.Message)
   626  			assert.Equal(t, "kustomize-controller", event.Source)
   627  			assert.Equal(t, string(jsonData), *event.Annotations)
   628  			assert.Equal(t, "Normal", event.Status)
   629  			assert.Equal(t, "terminal_id", *event.TerminalID)
   630  			assert.Equal(t, "uuid-1", event.ClusterEdgeID)
   631  			assert.Equal(t, createdAt, event.CreatedAt)
   632  		}
   633  	}
   634  }
   635  
   636  func TestGetInfraStatusForCluster(t *testing.T) {
   637  	clusterEdgeID := "test-infra-status"
   638  
   639  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   640  	if err != nil {
   641  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   642  	}
   643  	defer db.Close()
   644  
   645  	expectedCombinedStatus := &model.ClusterStatus{
   646  		Status:  "HEALTHY",
   647  		Message: "SYNCED",
   648  	}
   649  
   650  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
   651  
   652  	type test struct {
   653  		testName      string
   654  		clusterEdgeID string
   655  		expected      *model.ClusterStatus
   656  		mockSQLQuery  func() *sqlmock.ExpectedQuery
   657  	}
   658  
   659  	tests := []test{{
   660  		testName:      "ClusterInfraReadyStatus",
   661  		clusterEdgeID: clusterEdgeID,
   662  		expected:      expectedCombinedStatus,
   663  		mockSQLQuery: func() *sqlmock.ExpectedQuery {
   664  			return mock.ExpectQuery(sqlquery.GetClusterInfraStatusByID).
   665  				WithArgs(clusterEdgeID).
   666  				WillReturnRows(sqlmock.NewRows([]string{"cluster_edge_id", "cluster_name", "infra_status", "infra_status_details"}).
   667  					AddRow(clusterEdgeID, "test-cluster", "READY", "SYNCED"))
   668  		},
   669  	},
   670  		{
   671  			testName:      "ClusterInfraStatusNotReady",
   672  			clusterEdgeID: clusterEdgeID,
   673  			expected: &model.ClusterStatus{
   674  				Status:  "UNHEALTHY",
   675  				Message: "ReconcileFailed",
   676  			},
   677  			mockSQLQuery: func() *sqlmock.ExpectedQuery {
   678  				return mock.ExpectQuery(sqlquery.GetClusterInfraStatusByID).
   679  					WithArgs(clusterEdgeID).
   680  					WillReturnRows(sqlmock.NewRows([]string{"cluster_edge_id", "cluster_name", "infra_status", "infra_status_details"}).
   681  						AddRow(clusterEdgeID, "test-cluster", "ERROR", "ReconcileFailed"))
   682  			},
   683  		},
   684  		{
   685  			testName:      "ClusterInfraStatusProvisioning",
   686  			clusterEdgeID: clusterEdgeID,
   687  			expected: &model.ClusterStatus{
   688  				Status:  "PROVISIONING",
   689  				Message: "",
   690  			},
   691  			mockSQLQuery: func() *sqlmock.ExpectedQuery {
   692  				return mock.ExpectQuery(sqlquery.GetClusterInfraStatusByID).
   693  					WithArgs(clusterEdgeID).
   694  					WillReturnRows(sqlmock.NewRows([]string{"cluster_edge_id", "cluster_name", "infra_status", "infra_status_details"}).
   695  						AddRow(clusterEdgeID, "test-cluster", "PROVISIONING", ""))
   696  			},
   697  		},
   698  	}
   699  
   700  	for _, tc := range tests {
   701  		tc.mockSQLQuery()
   702  
   703  		t.Run(tc.testName, func(t *testing.T) {
   704  			clusterInfraStatus, err := service.GetInfraStatus(context.Background(), clusterEdgeID)
   705  			assert.NoError(t, err)
   706  			assert.Equal(t, tc.expected.Status, clusterInfraStatus.Status)
   707  		})
   708  	}
   709  }
   710  
   711  func TestReplicationStatus(t *testing.T) {
   712  	clusterEdgeID := "test-replication-status"
   713  
   714  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   715  	if err != nil {
   716  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   717  	}
   718  	defer db.Close()
   719  
   720  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
   721  
   722  	type test struct {
   723  		testName      string
   724  		clusterEdgeID string
   725  		expected      []*model.ReplicationStatus
   726  		mockSQLQuery  func() *sqlmock.ExpectedQuery
   727  	}
   728  
   729  	tests := []test{{
   730  		testName:      "ReplicationStatusFound",
   731  		clusterEdgeID: clusterEdgeID,
   732  		expected:      []*model.ReplicationStatus{{Name: "test-db", Status: "True"}},
   733  		mockSQLQuery: func() *sqlmock.ExpectedQuery {
   734  			return mock.ExpectQuery(sqlquery.GetReplicationStatus).
   735  				WithArgs(clusterEdgeID).
   736  				WillReturnRows(sqlmock.NewRows([]string{"name", "value"}).
   737  					AddRow("test-db", "True"))
   738  		},
   739  	},
   740  		{
   741  			testName:      "ReplicationStatusEmpty",
   742  			clusterEdgeID: clusterEdgeID,
   743  			expected:      []*model.ReplicationStatus{},
   744  			mockSQLQuery: func() *sqlmock.ExpectedQuery {
   745  				return mock.ExpectQuery(sqlquery.GetReplicationStatus).
   746  					WithArgs(clusterEdgeID).
   747  					WillReturnRows(sqlmock.NewRows([]string{"name", "value"}))
   748  			},
   749  		},
   750  		{
   751  			testName:      "ReplicationStatusNotFound",
   752  			clusterEdgeID: clusterEdgeID,
   753  			expected:      []*model.ReplicationStatus{{Name: "test-db", Status: "False"}},
   754  			mockSQLQuery: func() *sqlmock.ExpectedQuery {
   755  				return mock.ExpectQuery(sqlquery.GetReplicationStatus).
   756  					WithArgs(clusterEdgeID).
   757  					WillReturnRows(sqlmock.NewRows([]string{"name", "value"}).
   758  						AddRow("test-db", "False"))
   759  			},
   760  		},
   761  	}
   762  
   763  	for _, tc := range tests {
   764  		tc.mockSQLQuery()
   765  
   766  		t.Run(tc.testName, func(t *testing.T) {
   767  			replicationStatus, err := service.GetReplicationStatus(context.Background(), clusterEdgeID)
   768  			assert.NoError(t, err)
   769  			assert.Equal(t, tc.expected, replicationStatus)
   770  		})
   771  	}
   772  }
   773  
   774  func TestGetCombinedClusterStatus(t *testing.T) {
   775  	clusterEdgeID := "11fd4df6-db4c-422b-ac9d-2b43dae86d7e"
   776  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   777  	if err != nil {
   778  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   779  	}
   780  	defer db.Close()
   781  
   782  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
   783  
   784  	testCases := []struct {
   785  		testName       string
   786  		cluster        *model.CombinedStatus
   787  		expected       *model.ClusterStatus
   788  		mockSQLQueries []func() *sqlmock.ExpectedQuery
   789  		err            error
   790  	}{
   791  		{
   792  			testName:       "missing-cluster",
   793  			cluster:        nil,
   794  			err:            ErrClusterMissing,
   795  			expected:       nil,
   796  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{},
   797  		},
   798  		{
   799  			testName: "cluster-not-active",
   800  			cluster: &model.CombinedStatus{
   801  				ClusterEdgeID: clusterEdgeID,
   802  				Active:        false,
   803  			},
   804  			err: nil,
   805  			expected: &model.ClusterStatus{
   806  				Status:  status.Registered,
   807  				Message: status.RegisteredMessage,
   808  			},
   809  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{},
   810  		},
   811  		{
   812  			testName: "ready-status",
   813  			cluster: &model.CombinedStatus{
   814  				ClusterEdgeID: clusterEdgeID,
   815  				Active:        true,
   816  			},
   817  			err: nil,
   818  			expected: &model.ClusterStatus{
   819  				Status:  status.Ready,
   820  				Message: status.ReadyMessage,
   821  			},
   822  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
   823  				func() *sqlmock.ExpectedQuery {
   824  					return mock.ExpectQuery(sqlquery.GetClusterStatuses).
   825  						WithArgs(clusterEdgeID, false).
   826  						WillReturnRows(sqlmock.NewRows([]string{"kind", "jsonpath", "value"}).
   827  							AddRow("Shipment", `$.status.conditions[?(@.type == "Ready")].status`, "True").
   828  							AddRow("Kustomization", `$.status.conditions[?(@.type == "Ready")].status`, "True").
   829  							AddRow("Bucket", `$.status.conditions[?(@.type == "Ready")].status`, "True"),
   830  						)
   831  				},
   832  			},
   833  		},
   834  		{
   835  			testName: "error-status-one-error-resource",
   836  			cluster: &model.CombinedStatus{
   837  				ClusterEdgeID: clusterEdgeID,
   838  				Active:        true,
   839  			},
   840  			err: nil,
   841  			expected: &model.ClusterStatus{
   842  				Status:  status.Error,
   843  				Message: "timeout waiting for: [UnpackedPallet/vncserver-76d26410 status: 'InProgress', UnpackedPallet/display-76d26410 status: 'InProgress']",
   844  			},
   845  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
   846  				func() *sqlmock.ExpectedQuery {
   847  					return mock.ExpectQuery(sqlquery.GetClusterStatuses).
   848  						WithArgs(clusterEdgeID, false).
   849  						WillReturnRows(sqlmock.NewRows([]string{"kind", "jsonpath", "value"}).
   850  							AddRow("Shipment", `$.status.conditions[?(@.type == "Ready")].status`, "False").
   851  							AddRow("Kustomization", `$.status.conditions[?(@.type == "Ready")].status`, "True").
   852  							AddRow("Bucket", `$.status.conditions[?(@.type == "Ready")].status`, "True"),
   853  						)
   854  				},
   855  				func() *sqlmock.ExpectedQuery {
   856  					return mock.ExpectQuery(sqlquery.GetClusterErrorStatusMessage).
   857  						WithArgs("Shipment", clusterEdgeID, false).
   858  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
   859  							AddRow("timeout waiting for: [UnpackedPallet/vncserver-76d26410 status: 'InProgress', UnpackedPallet/display-76d26410 status: 'InProgress']"),
   860  						)
   861  				},
   862  			},
   863  		},
   864  		{
   865  			testName: "error-status-two-not-ready-resources-one-not-reported",
   866  			cluster: &model.CombinedStatus{
   867  				ClusterEdgeID: clusterEdgeID,
   868  				Active:        true,
   869  			},
   870  			err: nil,
   871  			expected: &model.ClusterStatus{
   872  				Status:  status.Installing,
   873  				Message: "timeout waiting for: [UnpackedPallet/vncserver-76d26410 status: 'InProgress', UnpackedPallet/display-76d26410 status: 'InProgress'] and Waiting for Kustomization status",
   874  			},
   875  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
   876  				func() *sqlmock.ExpectedQuery {
   877  					return mock.ExpectQuery(sqlquery.GetClusterStatuses).
   878  						WithArgs(clusterEdgeID, false).
   879  						WillReturnRows(sqlmock.NewRows([]string{"kind", "jsonpath", "value"}).
   880  							AddRow("Shipment", `$.status.conditions[?(@.type == "Ready")].status`, "False").
   881  							AddRow("Kustomization", `$.status.conditions[?(@.type == "Ready")].status`, "False").
   882  							AddRow("Bucket", `$.status.conditions[?(@.type == "Ready")].status`, "True"),
   883  						)
   884  				},
   885  				func() *sqlmock.ExpectedQuery {
   886  					return mock.ExpectQuery(sqlquery.GetClusterErrorStatusMessage).
   887  						WithArgs("Shipment", clusterEdgeID, false).
   888  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
   889  							AddRow("timeout waiting for: [UnpackedPallet/vncserver-76d26410 status: 'InProgress', UnpackedPallet/display-76d26410 status: 'InProgress']"),
   890  						)
   891  				},
   892  				func() *sqlmock.ExpectedQuery {
   893  					return mock.ExpectQuery(sqlquery.GetClusterErrorStatusMessage).
   894  						WithArgs("Kustomization", clusterEdgeID, false).
   895  						WillReturnError(sql.ErrNoRows)
   896  				},
   897  			},
   898  		},
   899  		{
   900  			testName: "error-status-three-not-ready-resources-three-errors",
   901  			cluster: &model.CombinedStatus{
   902  				ClusterEdgeID: clusterEdgeID,
   903  				Active:        true,
   904  			},
   905  			err: nil,
   906  			expected: &model.ClusterStatus{
   907  				Status:  status.Error,
   908  				Message: `timeout waiting for: [UnpackedPallet/vncserver-76d26410 status: 'InProgress', UnpackedPallet/display-76d26410 status: 'InProgress'], kustomization path not found: stat /tmp/kustomization-2906021254/e0da4d18-0786-440e-acc7-b37ea6198c09/shipments: no such file or directory, and failed to confirm existence of 'ret-edge-y95i8vtpeyfqmv99fx0i4' bucket: Get "https://storage.googleapis.com/storage/v1/b/ret-edge-y95i8vtpeyfqmv99fx0i4?alt=json&prettyPrint=false&projection=full": oauth2: cannot fetch token: Post "https://oauth2.googleapis.com/token": dial tcp: lookup oauth2.googleapis.com on 10.63.0.18:53: read udp 100.137.192.153:57882->10.66.0.10:53: i/o timeout`,
   909  			},
   910  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
   911  				func() *sqlmock.ExpectedQuery {
   912  					return mock.ExpectQuery(sqlquery.GetClusterStatuses).
   913  						WithArgs(clusterEdgeID, false).
   914  						WillReturnRows(sqlmock.NewRows([]string{"kind", "jsonpath", "value"}).
   915  							AddRow("Shipment", `$.status.conditions[?(@.type == "Ready")].status`, "False").
   916  							AddRow("Kustomization", `$.status.conditions[?(@.type == "Ready")].status`, "False").
   917  							AddRow("Bucket", `$.status.conditions[?(@.type == "Ready")].status`, "False"),
   918  						)
   919  				},
   920  				func() *sqlmock.ExpectedQuery {
   921  					return mock.ExpectQuery(sqlquery.GetClusterErrorStatusMessage).
   922  						WithArgs("Shipment", clusterEdgeID, false).
   923  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
   924  							AddRow(`timeout waiting for: [UnpackedPallet/vncserver-76d26410 status: 'InProgress', UnpackedPallet/display-76d26410 status: 'InProgress']`),
   925  						)
   926  				},
   927  				func() *sqlmock.ExpectedQuery {
   928  					return mock.ExpectQuery(sqlquery.GetClusterErrorStatusMessage).
   929  						WithArgs("Kustomization", clusterEdgeID, false).
   930  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
   931  							AddRow(`kustomization path not found: stat /tmp/kustomization-2906021254/e0da4d18-0786-440e-acc7-b37ea6198c09/shipments: no such file or directory`),
   932  						)
   933  				},
   934  				func() *sqlmock.ExpectedQuery {
   935  					return mock.ExpectQuery(sqlquery.GetClusterErrorStatusMessage).
   936  						WithArgs("Bucket", clusterEdgeID, false).
   937  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
   938  							AddRow(`failed to confirm existence of 'ret-edge-y95i8vtpeyfqmv99fx0i4' bucket: Get "https://storage.googleapis.com/storage/v1/b/ret-edge-y95i8vtpeyfqmv99fx0i4?alt=json&prettyPrint=false&projection=full": oauth2: cannot fetch token: Post "https://oauth2.googleapis.com/token": dial tcp: lookup oauth2.googleapis.com on 10.63.0.18:53: read udp 100.137.192.153:57882->10.66.0.10:53: i/o timeout`),
   939  						)
   940  				},
   941  			},
   942  		},
   943  	}
   944  
   945  	for _, tc := range testCases {
   946  		for _, mockSQLFn := range tc.mockSQLQueries {
   947  			mockSQLFn()
   948  		}
   949  
   950  		t.Run(tc.testName, func(t *testing.T) {
   951  			clusterStatus, err := service.GetCombinedClusterStatus(context.Background(), tc.cluster)
   952  			if tc.err != nil {
   953  				assert.True(t, errors.Is(err, tc.err))
   954  			} else {
   955  				assert.NoError(t, err)
   956  				assert.Equal(t, tc.expected.Status, clusterStatus.Status)
   957  				assert.Equal(t, tc.expected.Message, clusterStatus.Message)
   958  			}
   959  		})
   960  	}
   961  }
   962  
   963  func TestGetComponentStatus(t *testing.T) {
   964  	clusterEdgeID := "11fd4df6-db4c-422b-ac9d-2b43dae86d7e"
   965  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   966  	if err != nil {
   967  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   968  	}
   969  	defer db.Close()
   970  
   971  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
   972  
   973  	testCases := []struct {
   974  		title          string
   975  		clusterEdgeID  string
   976  		kind           string
   977  		active         bool
   978  		expected       *model.ClusterStatus
   979  		mockSQLQueries []func() *sqlmock.ExpectedQuery
   980  		err            error
   981  	}{
   982  		{
   983  			title:         "Test Case 1 - InActive Cluster",
   984  			clusterEdgeID: clusterEdgeID,
   985  			kind:          whv1.ShipmentGVK.Kind,
   986  			active:        false,
   987  			expected: &model.ClusterStatus{
   988  				Status:  status.NotAvailable,
   989  				Message: status.NotAvailableStatusMessage,
   990  			},
   991  			err: nil,
   992  		},
   993  		{
   994  			title:         "Test Case 2 - Shipment Status, Active Cluster",
   995  			clusterEdgeID: clusterEdgeID,
   996  			kind:          whv1.ShipmentGVK.Kind,
   997  			active:        true,
   998  			expected: &model.ClusterStatus{
   999  				Status:  status.Ready,
  1000  				Message: fmt.Sprintf(status.KindReadyMessage, whv1.ShipmentGVK.Kind),
  1001  			},
  1002  			err: nil,
  1003  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
  1004  				func() *sqlmock.ExpectedQuery {
  1005  					return mock.ExpectQuery(sqlquery.GetClusterStatus).
  1006  						WithArgs(whv1.ShipmentGVK.Kind, clusterEdgeID, false).
  1007  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
  1008  							AddRow("True"),
  1009  						)
  1010  				},
  1011  			},
  1012  		},
  1013  		{
  1014  			title:         "Test Case 3 - Shipment Status, Active Cluster, Missing Cluster Status",
  1015  			clusterEdgeID: clusterEdgeID,
  1016  			kind:          whv1.ShipmentGVK.Kind,
  1017  			active:        true,
  1018  			expected: &model.ClusterStatus{
  1019  				Status:  status.NotAvailable,
  1020  				Message: status.NotAvailableStatusMessage,
  1021  			},
  1022  			err: nil,
  1023  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
  1024  				func() *sqlmock.ExpectedQuery {
  1025  					return mock.ExpectQuery(sqlquery.GetClusterStatus).
  1026  						WithArgs(whv1.ShipmentGVK.Kind, clusterEdgeID, false).
  1027  						WillReturnError(sql.ErrNoRows)
  1028  				},
  1029  			},
  1030  		},
  1031  		{
  1032  			title:         "Test Case 4 - Shipment Status, Active Cluster, Not Reported",
  1033  			clusterEdgeID: clusterEdgeID,
  1034  			kind:          whv1.ShipmentGVK.Kind,
  1035  			active:        true,
  1036  			expected: &model.ClusterStatus{
  1037  				Status:  status.Installing,
  1038  				Message: fmt.Sprintf("%s %s status", status.NotReportedFormat, whv1.ShipmentGVK.Kind),
  1039  			},
  1040  			err: nil,
  1041  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
  1042  				func() *sqlmock.ExpectedQuery {
  1043  					return mock.ExpectQuery(sqlquery.GetClusterStatus).
  1044  						WithArgs(whv1.ShipmentGVK.Kind, clusterEdgeID, false).
  1045  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
  1046  							AddRow("False"),
  1047  						)
  1048  				},
  1049  				func() *sqlmock.ExpectedQuery {
  1050  					return mock.ExpectQuery(sqlquery.GetClusterErrorStatusMessage).
  1051  						WithArgs(whv1.ShipmentGVK.Kind, clusterEdgeID, false).
  1052  						WillReturnError(sql.ErrNoRows)
  1053  				},
  1054  			},
  1055  		},
  1056  		{
  1057  			title:         "Test Case 5 - Shipment Status, Active Cluster, Error",
  1058  			clusterEdgeID: clusterEdgeID,
  1059  			kind:          whv1.ShipmentGVK.Kind,
  1060  			active:        true,
  1061  			expected: &model.ClusterStatus{
  1062  				Status:  status.Error,
  1063  				Message: "timeout waiting for: [UnpackedPallet/display-823f6029 status: 'InProgress', UnpackedPallet/vncserver-823f6029 status: 'InProgress']",
  1064  			},
  1065  			err: nil,
  1066  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
  1067  				func() *sqlmock.ExpectedQuery {
  1068  					return mock.ExpectQuery(sqlquery.GetClusterStatus).
  1069  						WithArgs(whv1.ShipmentGVK.Kind, clusterEdgeID, false).
  1070  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
  1071  							AddRow("False"),
  1072  						)
  1073  				},
  1074  				func() *sqlmock.ExpectedQuery {
  1075  					return mock.ExpectQuery(sqlquery.GetClusterErrorStatusMessage).
  1076  						WithArgs(whv1.ShipmentGVK.Kind, clusterEdgeID, false).
  1077  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
  1078  							AddRow("timeout waiting for: [UnpackedPallet/display-823f6029 status: 'InProgress', UnpackedPallet/vncserver-823f6029 status: 'InProgress']"),
  1079  						)
  1080  				},
  1081  			},
  1082  		},
  1083  		{
  1084  			title:         "Test Case 6 - Kustomization Status, Active Cluster, Ready",
  1085  			clusterEdgeID: clusterEdgeID,
  1086  			kind:          kustomizeApi.KustomizationKind,
  1087  			active:        true,
  1088  			expected: &model.ClusterStatus{
  1089  				Status:  status.Ready,
  1090  				Message: fmt.Sprintf(status.KindReadyMessage, kustomizeApi.KustomizationKind),
  1091  			},
  1092  			err: nil,
  1093  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
  1094  				func() *sqlmock.ExpectedQuery {
  1095  					return mock.ExpectQuery(sqlquery.GetClusterStatus).
  1096  						WithArgs(kustomizeApi.KustomizationKind, clusterEdgeID, false).
  1097  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
  1098  							AddRow("True"),
  1099  						)
  1100  				},
  1101  			},
  1102  		},
  1103  		{
  1104  			title:         "Test Case 7 - Kustomization Status, Active Cluster, Missing Cluster Status",
  1105  			clusterEdgeID: clusterEdgeID,
  1106  			kind:          kustomizeApi.KustomizationKind,
  1107  			active:        true,
  1108  			expected: &model.ClusterStatus{
  1109  				Status:  status.NotAvailable,
  1110  				Message: status.NotAvailableStatusMessage,
  1111  			},
  1112  			err: nil,
  1113  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
  1114  				func() *sqlmock.ExpectedQuery {
  1115  					return mock.ExpectQuery(sqlquery.GetClusterStatus).
  1116  						WithArgs(kustomizeApi.KustomizationKind, clusterEdgeID, false).
  1117  						WillReturnError(sql.ErrNoRows)
  1118  				},
  1119  			},
  1120  		},
  1121  		{
  1122  			title:         "Test Case 8 - Kustomization Status, Active Cluster, Not Reported",
  1123  			clusterEdgeID: clusterEdgeID,
  1124  			kind:          kustomizeApi.KustomizationKind,
  1125  			active:        true,
  1126  			expected: &model.ClusterStatus{
  1127  				Status:  status.Installing,
  1128  				Message: fmt.Sprintf("%s %s status", status.NotReportedFormat, kustomizeApi.KustomizationKind),
  1129  			},
  1130  			err: nil,
  1131  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
  1132  				func() *sqlmock.ExpectedQuery {
  1133  					return mock.ExpectQuery(sqlquery.GetClusterStatus).
  1134  						WithArgs(kustomizeApi.KustomizationKind, clusterEdgeID, false).
  1135  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
  1136  							AddRow("False"),
  1137  						)
  1138  				},
  1139  				func() *sqlmock.ExpectedQuery {
  1140  					return mock.ExpectQuery(sqlquery.GetClusterErrorStatusMessage).
  1141  						WithArgs(kustomizeApi.KustomizationKind, clusterEdgeID, false).
  1142  						WillReturnError(sql.ErrNoRows)
  1143  				},
  1144  			},
  1145  		},
  1146  		{
  1147  			title:         "Test Case 9 - Kustomization Status, Active Cluster, Error",
  1148  			clusterEdgeID: clusterEdgeID,
  1149  			kind:          kustomizeApi.KustomizationKind,
  1150  			active:        true,
  1151  			expected: &model.ClusterStatus{
  1152  				Status:  status.Error,
  1153  				Message: "path /tmp/abc123 not found",
  1154  			},
  1155  			err: nil,
  1156  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
  1157  				func() *sqlmock.ExpectedQuery {
  1158  					return mock.ExpectQuery(sqlquery.GetClusterStatus).
  1159  						WithArgs(kustomizeApi.KustomizationKind, clusterEdgeID, false).
  1160  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
  1161  							AddRow("False"),
  1162  						)
  1163  				},
  1164  				func() *sqlmock.ExpectedQuery {
  1165  					return mock.ExpectQuery(sqlquery.GetClusterErrorStatusMessage).
  1166  						WithArgs(kustomizeApi.KustomizationKind, clusterEdgeID, false).
  1167  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
  1168  							AddRow("path /tmp/abc123 not found"),
  1169  						)
  1170  				},
  1171  			},
  1172  		},
  1173  		{
  1174  			title:         "Test Case 10 - Bucket Status, Active Cluster, Ready",
  1175  			clusterEdgeID: clusterEdgeID,
  1176  			kind:          sourceApi.BucketKind,
  1177  			active:        true,
  1178  			expected: &model.ClusterStatus{
  1179  				Status:  status.Ready,
  1180  				Message: fmt.Sprintf(status.KindReadyMessage, sourceApi.BucketKind),
  1181  			},
  1182  			err: nil,
  1183  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
  1184  				func() *sqlmock.ExpectedQuery {
  1185  					return mock.ExpectQuery(sqlquery.GetClusterStatus).
  1186  						WithArgs(sourceApi.BucketKind, clusterEdgeID, false).
  1187  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
  1188  							AddRow("True"),
  1189  						)
  1190  				},
  1191  			},
  1192  		},
  1193  		{
  1194  			title:         "Test Case 11 - Bucket Status, Active Cluster, Missing Cluster Status",
  1195  			clusterEdgeID: clusterEdgeID,
  1196  			kind:          sourceApi.BucketKind,
  1197  			active:        true,
  1198  			expected: &model.ClusterStatus{
  1199  				Status:  status.NotAvailable,
  1200  				Message: status.NotAvailableStatusMessage,
  1201  			},
  1202  			err: nil,
  1203  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
  1204  				func() *sqlmock.ExpectedQuery {
  1205  					return mock.ExpectQuery(sqlquery.GetClusterStatus).
  1206  						WithArgs(sourceApi.BucketKind, clusterEdgeID, false).
  1207  						WillReturnError(sql.ErrNoRows)
  1208  				},
  1209  			},
  1210  		},
  1211  		{
  1212  			title:         "Test Case 12 - Bucket Status, Active Cluster, Not Reported",
  1213  			clusterEdgeID: clusterEdgeID,
  1214  			kind:          sourceApi.BucketKind,
  1215  			active:        true,
  1216  			expected: &model.ClusterStatus{
  1217  				Status:  status.Installing,
  1218  				Message: fmt.Sprintf("%s %s status", status.NotReportedFormat, sourceApi.BucketKind),
  1219  			},
  1220  			err: nil,
  1221  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
  1222  				func() *sqlmock.ExpectedQuery {
  1223  					return mock.ExpectQuery(sqlquery.GetClusterStatus).
  1224  						WithArgs(sourceApi.BucketKind, clusterEdgeID, false).
  1225  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
  1226  							AddRow("False"),
  1227  						)
  1228  				},
  1229  				func() *sqlmock.ExpectedQuery {
  1230  					return mock.ExpectQuery(sqlquery.GetClusterErrorStatusMessage).
  1231  						WithArgs(sourceApi.BucketKind, clusterEdgeID, false).
  1232  						WillReturnError(sql.ErrNoRows)
  1233  				},
  1234  			},
  1235  		},
  1236  		{
  1237  			title:         "Test Case 13 - Bucket Status, Active Cluster, Error",
  1238  			clusterEdgeID: clusterEdgeID,
  1239  			kind:          sourceApi.BucketKind,
  1240  			active:        true,
  1241  			expected: &model.ClusterStatus{
  1242  				Status:  status.Error,
  1243  				Message: "some cool source bucket error here",
  1244  			},
  1245  			err: nil,
  1246  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
  1247  				func() *sqlmock.ExpectedQuery {
  1248  					return mock.ExpectQuery(sqlquery.GetClusterStatus).
  1249  						WithArgs(sourceApi.BucketKind, clusterEdgeID, false).
  1250  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
  1251  							AddRow("False"),
  1252  						)
  1253  				},
  1254  				func() *sqlmock.ExpectedQuery {
  1255  					return mock.ExpectQuery(sqlquery.GetClusterErrorStatusMessage).
  1256  						WithArgs(sourceApi.BucketKind, clusterEdgeID, false).
  1257  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
  1258  							AddRow("some cool source bucket error here"),
  1259  						)
  1260  				},
  1261  			},
  1262  		},
  1263  		{
  1264  			title:         "Test Case 14 - No Cluster Edge ID Error",
  1265  			clusterEdgeID: "",
  1266  			kind:          sourceApi.BucketKind,
  1267  			active:        true,
  1268  			expected:      nil,
  1269  			err:           ErrClusterMissing,
  1270  		},
  1271  		{
  1272  			title:         "Test Case 15 - No Kind Error",
  1273  			clusterEdgeID: clusterEdgeID,
  1274  			kind:          "",
  1275  			active:        true,
  1276  			expected:      nil,
  1277  			err:           ErrKindMissing,
  1278  		},
  1279  	}
  1280  
  1281  	for _, tc := range testCases {
  1282  		for _, mockSQLFn := range tc.mockSQLQueries {
  1283  			mockSQLFn()
  1284  		}
  1285  
  1286  		t.Run(tc.title, func(t *testing.T) {
  1287  			res, err := service.GetComponentStatus(context.Background(), tc.clusterEdgeID, tc.kind, tc.active)
  1288  			if tc.err != nil {
  1289  				assert.True(t, errors.Is(tc.err, err))
  1290  			}
  1291  			if tc.expected != nil {
  1292  				assert.Equal(t, tc.expected.Status, res.Status)
  1293  				assert.Equal(t, tc.expected.Message, res.Message)
  1294  			} else {
  1295  				assert.Equal(t, tc.expected, res)
  1296  			}
  1297  		})
  1298  	}
  1299  }
  1300  
  1301  func TestGetActiveVersion(t *testing.T) {
  1302  	clusterEdgeID := "test-active-version-cluster"
  1303  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  1304  	if err != nil {
  1305  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  1306  	}
  1307  	defer db.Close()
  1308  
  1309  	service := NewStoreClusterService(nil, nil, db, nil, nil, nil)
  1310  
  1311  	activeVersion := "0.18.0-rc.1715271464+commit.a8854d8"
  1312  
  1313  	type test struct {
  1314  		testName      string
  1315  		clusterEdgeID string
  1316  		expected      string
  1317  		mockSQLQuery  func() *sqlmock.ExpectedQuery
  1318  	}
  1319  
  1320  	tests := []test{
  1321  		{
  1322  			testName:      "GetActiveEdgeVersion",
  1323  			clusterEdgeID: clusterEdgeID,
  1324  			expected:      activeVersion,
  1325  			mockSQLQuery: func() *sqlmock.ExpectedQuery {
  1326  				return mock.ExpectQuery(sqlquery.GetActiveEdgeVersionFromWatchedField).
  1327  					WithArgs(clusterEdgeID).
  1328  					WillReturnRows(sqlmock.NewRows([]string{"value"}).
  1329  						AddRow("\"0.18.0-rc.1715271464+commit.a8854d8\"").
  1330  						AddRow("\"0.18.0-rc.1715271464+commit.a8854d8\"").
  1331  						AddRow("True"))
  1332  			},
  1333  		},
  1334  		{
  1335  			testName:      "GetActiveEdgeVersionEmpty",
  1336  			clusterEdgeID: clusterEdgeID,
  1337  			expected:      "",
  1338  			mockSQLQuery: func() *sqlmock.ExpectedQuery {
  1339  				return mock.ExpectQuery(sqlquery.GetActiveEdgeVersionFromWatchedField).
  1340  					WithArgs(clusterEdgeID).
  1341  					WillReturnRows(sqlmock.NewRows([]string{"value"}).
  1342  						AddRow("\"\"").AddRow("\"\"").AddRow("True"))
  1343  			},
  1344  		},
  1345  	}
  1346  
  1347  	for _, tc := range tests {
  1348  		tc.mockSQLQuery()
  1349  
  1350  		t.Run(tc.testName, func(t *testing.T) {
  1351  			clusterInfraStatus, err := service.GetActiveEdgeVersion(context.Background(), clusterEdgeID)
  1352  			assert.NoError(t, err)
  1353  			assert.Equal(t, tc.expected, clusterInfraStatus)
  1354  		})
  1355  	}
  1356  }
  1357  
  1358  // nolint: dupl
  1359  func TestGetSupportStatus(t *testing.T) {
  1360  	supportedClusterEdgeID := "test-support-status-cluster"
  1361  	unsupportedClusterEdgeID := "test-unsupported-status-cluster"
  1362  	noTerminalVersionClusterEdgeID := "test-no-terminal-version-status-cluster"
  1363  	latestVersion := version.New().SemVer
  1364  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  1365  	if err != nil {
  1366  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  1367  	}
  1368  	defer db.Close()
  1369  
  1370  	getKubeResource := func() GetKubeResourceFunc {
  1371  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  1372  			assert.Equal(t, projectID, _projectID)
  1373  			assert.Nil(t, cluster)
  1374  			return []string{supportVersionResource, unsupportedVersionResource, noVersionResource}, nil
  1375  		}
  1376  	}
  1377  	bqClientMock := createMockBQClient(t, getKubeResource())
  1378  	artifactService := artifacts.NewArtifactsService(db, nil)
  1379  	labelService := NewLabelService(artifactService, db)
  1380  	terminalService := NewTerminalServiceBQ(db, bqClientMock, labelService)
  1381  	compatibilityService := NewCompatibilityService(db)
  1382  	service := NewStoreClusterService(nil, bqClientMock, db, nil, terminalService, compatibilityService)
  1383  
  1384  	testCases := []struct {
  1385  		testName       string
  1386  		cluster        *model.CombinedStatus
  1387  		expected       *model.SupportStatus
  1388  		mockSQLQueries []func() *sqlmock.ExpectedQuery
  1389  		err            error
  1390  	}{
  1391  		{
  1392  			testName: "supported-gke-cluster",
  1393  			cluster: &model.CombinedStatus{
  1394  				ClusterEdgeID: supportedClusterEdgeID,
  1395  			},
  1396  			expected: &model.SupportStatus{
  1397  				InfraSupportStatus: &model.InfraSupportStatus{
  1398  					Status:  status.Supported,
  1399  					Message: fmt.Sprintf("Edge Infra version %s supported", latestVersion),
  1400  				},
  1401  				EdgeOsSupportStatus: &model.EdgeOsSupportStatus{},
  1402  			},
  1403  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
  1404  				func() *sqlmock.ExpectedQuery {
  1405  					return mock.ExpectQuery(sqlquery.SelectEdgeLabelsForCluster).WithArgs(supportedClusterEdgeID).
  1406  						WillReturnRows(mock.NewRows([]string{"label_edge_id", "label_key", "color", "visible", "editable", "banner_edge_id", "label_unique", "description", "label_type"}).
  1407  							AddRow("label_edge_id", "test-label-key-1", "color", true, true, "banner_edge_id", true, "description", "label_type"))
  1408  				},
  1409  				func() *sqlmock.ExpectedQuery {
  1410  					return mock.ExpectQuery(sqlquery.GetArtifactVersionsAndCompatibilityForArtifactName).WithArgs(fleet.Store, latestVersion, constants.EdgeOSArtifact).
  1411  						WillReturnRows(mock.NewRows([]string{"artifact_name", "artifact_version", "nth_index", "compatible_artifact_name", "compatible_artifact_version"}).
  1412  							AddRow(fleet.Store, latestVersion, 2, constants.EdgeOSArtifact, "1.15").
  1413  							AddRow(fleet.Store, latestVersion, 2, constants.EdgeOSArtifact, "1.14").
  1414  							AddRow(fleet.Store, latestVersion, 2, constants.EdgeOSArtifact, "1.13"))
  1415  				},
  1416  				func() *sqlmock.ExpectedQuery {
  1417  					return mock.ExpectQuery(sqlquery.GetActiveEdgeVersionFromWatchedField).
  1418  						WithArgs(supportedClusterEdgeID).
  1419  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
  1420  							AddRow(fmt.Sprintf("\"%s-rc.1715271464+commit.a8854d8\"", latestVersion)).
  1421  							AddRow(fmt.Sprintf("\"%s-rc.1715271464+commit.a8854d8\"", latestVersion)).
  1422  							AddRow("True"))
  1423  				},
  1424  			},
  1425  			err: nil,
  1426  		},
  1427  		{
  1428  			testName: "unsupported-gke-cluster",
  1429  			cluster: &model.CombinedStatus{
  1430  				ClusterEdgeID: unsupportedClusterEdgeID,
  1431  			},
  1432  			expected: &model.SupportStatus{
  1433  				InfraSupportStatus: &model.InfraSupportStatus{
  1434  					Status:  status.ClusterOutOfSupport,
  1435  					Message: fmt.Sprintf("Edge Infra version %s is out of support with current version %s", "0.17.0", latestVersion),
  1436  				},
  1437  				EdgeOsSupportStatus: &model.EdgeOsSupportStatus{},
  1438  			},
  1439  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
  1440  				func() *sqlmock.ExpectedQuery {
  1441  					return mock.ExpectQuery(sqlquery.SelectEdgeLabelsForCluster).WithArgs(unsupportedClusterEdgeID).
  1442  						WillReturnRows(mock.NewRows([]string{"label_edge_id", "label_key", "color", "visible", "editable", "banner_edge_id", "label_unique", "description", "label_type"}).
  1443  							AddRow("label_edge_id", "test-label-key-1", "color", true, true, "banner_edge_id", true, "description", "label_type"))
  1444  				},
  1445  				func() *sqlmock.ExpectedQuery {
  1446  					return mock.ExpectQuery(sqlquery.GetArtifactVersionsAndCompatibilityForArtifactName).WithArgs(fleet.Store, latestVersion, constants.EdgeOSArtifact).
  1447  						WillReturnRows(mock.NewRows([]string{"artifact_name", "artifact_version", "nth_index", "compatible_artifact_name", "compatible_artifact_version"}).
  1448  							AddRow(fleet.Store, latestVersion, 2, constants.EdgeOSArtifact, "1.15").
  1449  							AddRow(fleet.Store, latestVersion, 2, constants.EdgeOSArtifact, "1.14").
  1450  							AddRow(fleet.Store, latestVersion, 2, constants.EdgeOSArtifact, "1.13"))
  1451  				},
  1452  				func() *sqlmock.ExpectedQuery {
  1453  					return mock.ExpectQuery(sqlquery.GetActiveEdgeVersionFromWatchedField).
  1454  						WithArgs(unsupportedClusterEdgeID).
  1455  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
  1456  							AddRow("\"0.17.0-rc.1715271464+commit.a8854d8\"").
  1457  							AddRow("\"0.17.0-rc.1715271464+commit.a8854d8\"").
  1458  							AddRow("True"))
  1459  				},
  1460  			},
  1461  			err: nil,
  1462  		},
  1463  		{
  1464  			testName: "supported-dsds-cluster",
  1465  			cluster: &model.CombinedStatus{
  1466  				ClusterEdgeID: supportedClusterEdgeID,
  1467  			},
  1468  			expected: &model.SupportStatus{
  1469  				InfraSupportStatus: &model.InfraSupportStatus{
  1470  					Status:  status.Supported,
  1471  					Message: fmt.Sprintf("Edge Infra version %s supported", latestVersion),
  1472  				},
  1473  				EdgeOsSupportStatus: &model.EdgeOsSupportStatus{
  1474  					Status:  status.Supported,
  1475  					Message: fmt.Sprintf("EdgeOS version %s supported", "1.15.0"),
  1476  				},
  1477  			},
  1478  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
  1479  				func() *sqlmock.ExpectedQuery {
  1480  					return mock.ExpectQuery(sqlquery.SelectEdgeLabelsForCluster).WithArgs(supportedClusterEdgeID).
  1481  						WillReturnRows(mock.NewRows([]string{"label_edge_id", "label_key", "color", "visible", "editable", "banner_edge_id", "label_unique", "description", "label_type"}).
  1482  							AddRow("label_edge_id", "dsds", "color", true, true, "banner_edge_id", true, "description", "label_type"))
  1483  				},
  1484  				func() *sqlmock.ExpectedQuery {
  1485  					return mock.ExpectQuery(sqlquery.GetArtifactVersionsAndCompatibilityForArtifactName).WithArgs(fleet.Store, latestVersion, constants.EdgeOSArtifact).
  1486  						WillReturnRows(mock.NewRows([]string{"artifact_name", "artifact_version", "nth_index", "compatible_artifact_name", "compatible_artifact_version"}).
  1487  							AddRow(fleet.Store, latestVersion, 2, constants.EdgeOSArtifact, "1.15").
  1488  							AddRow(fleet.Store, latestVersion, 2, constants.EdgeOSArtifact, "1.14").
  1489  							AddRow(fleet.Store, latestVersion, 2, constants.EdgeOSArtifact, "1.13"))
  1490  				},
  1491  				func() *sqlmock.ExpectedQuery {
  1492  					return mock.ExpectQuery(sqlquery.GetActiveEdgeVersionFromWatchedField).
  1493  						WithArgs(supportedClusterEdgeID).
  1494  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
  1495  							AddRow(fmt.Sprintf("\"%s-rc.1715271464+commit.a8854d8\"", latestVersion)).
  1496  							AddRow(fmt.Sprintf("\"%s-rc.1715271464+commit.a8854d8\"", latestVersion)).
  1497  							AddRow("True"))
  1498  				},
  1499  				func() *sqlmock.ExpectedQuery {
  1500  					return mock.ExpectQuery(sqlquery.GetTerminalByClusterEdgeIDQuery).WithArgs(supportedClusterEdgeID).
  1501  						WillReturnRows(mock.NewRows(terminalColumns).
  1502  							AddRow("t001", "lane1", "controlplane", supportedClusterEdgeID, "test-cluster", "server", "none", "", "", "", false, "test"))
  1503  				},
  1504  				func() *sqlmock.ExpectedQuery {
  1505  					return mock.ExpectQuery(sqlquery.GetTerminalDiskByTerminalIDQuery).WithArgs(sqlmock.AnyArg()).
  1506  						WillReturnRows(mock.NewRows(terminalDiskColumns).
  1507  							AddRow("", "", false, false, "", false))
  1508  				},
  1509  				func() *sqlmock.ExpectedQuery {
  1510  					return mock.ExpectQuery(sqlquery.GetTerminalInterfaceByTerminalIDQuery).WithArgs(sqlmock.AnyArg()).
  1511  						WillReturnRows(mock.NewRows(terminalIfaceColumns).
  1512  							AddRow("", "", false, false, "", "", ""))
  1513  				},
  1514  				func() *sqlmock.ExpectedQuery {
  1515  					return mock.ExpectQuery(sqlquery.GetTerminalAddressByInterfaceIDQuery).WithArgs(sqlmock.AnyArg()).
  1516  						WillReturnRows(mock.NewRows(terminalAddrColumns).
  1517  							AddRow("", "", 1, "", ""))
  1518  				},
  1519  				func() *sqlmock.ExpectedQuery {
  1520  					return mock.ExpectQuery(sqlquery.GetTerminalLabels).
  1521  						WithArgs(sqlmock.AnyArg(), sql.NullString{}).
  1522  						WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  1523  							AddRow("t001", "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  1524  				},
  1525  				func() *sqlmock.ExpectedQuery {
  1526  					return mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  1527  						WithArgs(supportedClusterEdgeID).
  1528  						WillReturnRows(mock.NewRows([]string{"project_id"}).
  1529  							AddRow("test-org"))
  1530  				},
  1531  			},
  1532  			err: nil,
  1533  		},
  1534  		{
  1535  			testName: "unsupported-dsds-cluster",
  1536  			cluster: &model.CombinedStatus{
  1537  				ClusterEdgeID: unsupportedClusterEdgeID,
  1538  			},
  1539  			expected: &model.SupportStatus{
  1540  				InfraSupportStatus: &model.InfraSupportStatus{
  1541  					Status:  status.Supported,
  1542  					Message: fmt.Sprintf("Edge Infra version %s supported", latestVersion),
  1543  				},
  1544  				EdgeOsSupportStatus: &model.EdgeOsSupportStatus{
  1545  					Status:  status.ClusterOutOfSupport,
  1546  					Message: fmt.Sprintf("One or more terminals on EdgeOS version %s is out of support", "1.2.0"),
  1547  				},
  1548  			},
  1549  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
  1550  				func() *sqlmock.ExpectedQuery {
  1551  					return mock.ExpectQuery(sqlquery.SelectEdgeLabelsForCluster).WithArgs(unsupportedClusterEdgeID).
  1552  						WillReturnRows(mock.NewRows([]string{"label_edge_id", "label_key", "color", "visible", "editable", "banner_edge_id", "label_unique", "description", "label_type"}).
  1553  							AddRow("label_edge_id", "dsds", "color", true, true, "banner_edge_id", true, "description", "label_type"))
  1554  				},
  1555  				func() *sqlmock.ExpectedQuery {
  1556  					return mock.ExpectQuery(sqlquery.GetArtifactVersionsAndCompatibilityForArtifactName).WithArgs(fleet.Store, latestVersion, constants.EdgeOSArtifact).
  1557  						WillReturnRows(mock.NewRows([]string{"artifact_name", "artifact_version", "nth_index", "compatible_artifact_name", "compatible_artifact_version"}).
  1558  							AddRow(fleet.Store, latestVersion, 2, constants.EdgeOSArtifact, "1.15").
  1559  							AddRow(fleet.Store, latestVersion, 2, constants.EdgeOSArtifact, "1.14").
  1560  							AddRow(fleet.Store, latestVersion, 2, constants.EdgeOSArtifact, "1.13"))
  1561  				},
  1562  				func() *sqlmock.ExpectedQuery {
  1563  					return mock.ExpectQuery(sqlquery.GetActiveEdgeVersionFromWatchedField).
  1564  						WithArgs(unsupportedClusterEdgeID).
  1565  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
  1566  							AddRow(fmt.Sprintf("\"%s-rc.1715271464+commit.a8854d8\"", latestVersion)).
  1567  							AddRow(fmt.Sprintf("\"%s-rc.1715271464+commit.a8854d8\"", latestVersion)).
  1568  							AddRow("True"))
  1569  				},
  1570  				func() *sqlmock.ExpectedQuery {
  1571  					return mock.ExpectQuery(sqlquery.GetTerminalByClusterEdgeIDQuery).WithArgs(unsupportedClusterEdgeID).
  1572  						WillReturnRows(mock.NewRows(terminalColumns).
  1573  							AddRow("t001", "lane1", "controlplane", unsupportedClusterEdgeID, "test-cluster", "server", "none", "", "", "", false, "test"))
  1574  				},
  1575  				func() *sqlmock.ExpectedQuery {
  1576  					return mock.ExpectQuery(sqlquery.GetTerminalDiskByTerminalIDQuery).WithArgs(sqlmock.AnyArg()).
  1577  						WillReturnRows(mock.NewRows(terminalDiskColumns).
  1578  							AddRow("", "", false, false, "", false))
  1579  				},
  1580  				func() *sqlmock.ExpectedQuery {
  1581  					return mock.ExpectQuery(sqlquery.GetTerminalInterfaceByTerminalIDQuery).WithArgs(sqlmock.AnyArg()).
  1582  						WillReturnRows(mock.NewRows(terminalIfaceColumns).
  1583  							AddRow("", "", false, false, "", "", ""))
  1584  				},
  1585  				func() *sqlmock.ExpectedQuery {
  1586  					return mock.ExpectQuery(sqlquery.GetTerminalAddressByInterfaceIDQuery).WithArgs(sqlmock.AnyArg()).
  1587  						WillReturnRows(mock.NewRows(terminalAddrColumns).
  1588  							AddRow("", "", 1, "", ""))
  1589  				},
  1590  				func() *sqlmock.ExpectedQuery {
  1591  					return mock.ExpectQuery(sqlquery.GetTerminalLabels).
  1592  						WithArgs(sqlmock.AnyArg(), sql.NullString{}).
  1593  						WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  1594  							AddRow("t001", "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  1595  				},
  1596  				func() *sqlmock.ExpectedQuery {
  1597  					return mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  1598  						WithArgs(unsupportedClusterEdgeID).
  1599  						WillReturnRows(mock.NewRows([]string{"project_id"}).
  1600  							AddRow("test-org"))
  1601  				},
  1602  			},
  1603  			err: nil,
  1604  		},
  1605  		{
  1606  			testName: "no-active-version-cluster",
  1607  			cluster: &model.CombinedStatus{
  1608  				ClusterEdgeID: unsupportedClusterEdgeID,
  1609  			},
  1610  			expected: &model.SupportStatus{
  1611  				InfraSupportStatus: &model.InfraSupportStatus{
  1612  					Status:  status.ErrGettingVersion,
  1613  					Message: status.NoActiveVersion,
  1614  				},
  1615  				EdgeOsSupportStatus: &model.EdgeOsSupportStatus{},
  1616  			},
  1617  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
  1618  				func() *sqlmock.ExpectedQuery {
  1619  					return mock.ExpectQuery(sqlquery.SelectEdgeLabelsForCluster).WithArgs(unsupportedClusterEdgeID).
  1620  						WillReturnRows(mock.NewRows([]string{"label_edge_id", "label_key", "color", "visible", "editable", "banner_edge_id", "label_unique", "description", "label_type"}).
  1621  							AddRow("label_edge_id", "dsds", "color", true, true, "banner_edge_id", true, "description", "label_type"))
  1622  				},
  1623  				func() *sqlmock.ExpectedQuery {
  1624  					return mock.ExpectQuery(sqlquery.GetArtifactVersionsAndCompatibilityForArtifactName).WithArgs(fleet.Store, latestVersion, constants.EdgeOSArtifact).
  1625  						WillReturnRows(mock.NewRows([]string{"artifact_name", "artifact_version", "nth_index", "compatible_artifact_name", "compatible_artifact_version"}).
  1626  							AddRow(fleet.Store, latestVersion, 2, constants.EdgeOSArtifact, "1.15").
  1627  							AddRow(fleet.Store, latestVersion, 2, constants.EdgeOSArtifact, "1.14").
  1628  							AddRow(fleet.Store, latestVersion, 2, constants.EdgeOSArtifact, "1.13"))
  1629  				},
  1630  				func() *sqlmock.ExpectedQuery {
  1631  					return mock.ExpectQuery(sqlquery.GetActiveEdgeVersionFromWatchedField).
  1632  						WithArgs(unsupportedClusterEdgeID).
  1633  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
  1634  							AddRow("").
  1635  							AddRow("").
  1636  							AddRow("True"))
  1637  				},
  1638  			},
  1639  			err: nil,
  1640  		},
  1641  		{
  1642  			testName: "no-terminal-version-cluster",
  1643  			cluster: &model.CombinedStatus{
  1644  				ClusterEdgeID: noTerminalVersionClusterEdgeID,
  1645  			},
  1646  			expected: &model.SupportStatus{
  1647  				InfraSupportStatus: &model.InfraSupportStatus{
  1648  					Status:  status.Supported,
  1649  					Message: fmt.Sprintf("Edge Infra version %s supported", latestVersion),
  1650  				},
  1651  				EdgeOsSupportStatus: &model.EdgeOsSupportStatus{
  1652  					Status:  status.ErrGettingVersion,
  1653  					Message: status.NoTerminalVersion,
  1654  				},
  1655  			},
  1656  			mockSQLQueries: []func() *sqlmock.ExpectedQuery{
  1657  				func() *sqlmock.ExpectedQuery {
  1658  					return mock.ExpectQuery(sqlquery.SelectEdgeLabelsForCluster).WithArgs(noTerminalVersionClusterEdgeID).
  1659  						WillReturnRows(mock.NewRows([]string{"label_edge_id", "label_key", "color", "visible", "editable", "banner_edge_id", "label_unique", "description", "label_type"}).
  1660  							AddRow("label_edge_id", "dsds", "color", true, true, "banner_edge_id", true, "description", "label_type"))
  1661  				},
  1662  				func() *sqlmock.ExpectedQuery {
  1663  					return mock.ExpectQuery(sqlquery.GetArtifactVersionsAndCompatibilityForArtifactName).WithArgs(fleet.Store, latestVersion, constants.EdgeOSArtifact).
  1664  						WillReturnRows(mock.NewRows([]string{"artifact_name", "artifact_version", "nth_index", "compatible_artifact_name", "compatible_artifact_version"}).
  1665  							AddRow(fleet.Store, latestVersion, 2, constants.EdgeOSArtifact, "1.15").
  1666  							AddRow(fleet.Store, latestVersion, 2, constants.EdgeOSArtifact, "1.14").
  1667  							AddRow(fleet.Store, latestVersion, 2, constants.EdgeOSArtifact, "1.13"))
  1668  				},
  1669  				func() *sqlmock.ExpectedQuery {
  1670  					return mock.ExpectQuery(sqlquery.GetActiveEdgeVersionFromWatchedField).
  1671  						WithArgs(noTerminalVersionClusterEdgeID).
  1672  						WillReturnRows(sqlmock.NewRows([]string{"value"}).
  1673  							AddRow(fmt.Sprintf("\"%s-rc.1715271464+commit.a8854d8\"", latestVersion)).
  1674  							AddRow(fmt.Sprintf("\"%s-rc.1715271464+commit.a8854d8\"", latestVersion)).
  1675  							AddRow("True"))
  1676  				},
  1677  				func() *sqlmock.ExpectedQuery {
  1678  					return mock.ExpectQuery(sqlquery.GetTerminalByClusterEdgeIDQuery).WithArgs(noTerminalVersionClusterEdgeID).
  1679  						WillReturnRows(mock.NewRows(terminalColumns).
  1680  							AddRow("t001", "lane1", "controlplane", noTerminalVersionClusterEdgeID, "test-cluster", "server", "none", "", "", "", false, "test"))
  1681  				},
  1682  				func() *sqlmock.ExpectedQuery {
  1683  					return mock.ExpectQuery(sqlquery.GetTerminalDiskByTerminalIDQuery).WithArgs(sqlmock.AnyArg()).
  1684  						WillReturnRows(mock.NewRows(terminalDiskColumns).
  1685  							AddRow("", "", false, false, "", false))
  1686  				},
  1687  				func() *sqlmock.ExpectedQuery {
  1688  					return mock.ExpectQuery(sqlquery.GetTerminalInterfaceByTerminalIDQuery).WithArgs(sqlmock.AnyArg()).
  1689  						WillReturnRows(mock.NewRows(terminalIfaceColumns).
  1690  							AddRow("", "", false, false, "", "", ""))
  1691  				},
  1692  				func() *sqlmock.ExpectedQuery {
  1693  					return mock.ExpectQuery(sqlquery.GetTerminalAddressByInterfaceIDQuery).WithArgs(sqlmock.AnyArg()).
  1694  						WillReturnRows(mock.NewRows(terminalAddrColumns).
  1695  							AddRow("", "", 1, "", ""))
  1696  				},
  1697  				func() *sqlmock.ExpectedQuery {
  1698  					return mock.ExpectQuery(sqlquery.GetTerminalLabels).
  1699  						WithArgs(sqlmock.AnyArg(), sql.NullString{}).
  1700  						WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  1701  							AddRow("t001", "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  1702  				},
  1703  				func() *sqlmock.ExpectedQuery {
  1704  					return mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  1705  						WithArgs(noTerminalVersionClusterEdgeID).
  1706  						WillReturnRows(mock.NewRows([]string{"project_id"}).
  1707  							AddRow("test-org"))
  1708  				},
  1709  			},
  1710  			err: nil,
  1711  		},
  1712  	}
  1713  
  1714  	for _, tc := range testCases {
  1715  		for _, mockSQLFn := range tc.mockSQLQueries {
  1716  			mockSQLFn()
  1717  		}
  1718  		t.Run(tc.testName, func(t *testing.T) {
  1719  			supportStatus, err := service.GetSupportStatus(context.Background(), tc.cluster)
  1720  			if tc.err != nil {
  1721  				assert.True(t, errors.Is(err, tc.err))
  1722  			} else {
  1723  				assert.NoError(t, err)
  1724  				assert.Equal(t, tc.expected.InfraSupportStatus, supportStatus.InfraSupportStatus)
  1725  				assert.Equal(t, tc.expected.EdgeOsSupportStatus, supportStatus.EdgeOsSupportStatus)
  1726  			}
  1727  		})
  1728  	}
  1729  }
  1730  

View as plain text