...

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

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

     1  package services
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"database/sql/driver"
     7  	"encoding/hex"
     8  	"fmt"
     9  	"net"
    10  	"strings"
    11  	"testing"
    12  
    13  	"github.com/DATA-DOG/go-sqlmock"
    14  	"github.com/golang/mock/gomock"
    15  	"github.com/google/uuid"
    16  	"github.com/stretchr/testify/assert"
    17  
    18  	"edge-infra.dev/pkg/edge/api/graph/model"
    19  	"edge-infra.dev/pkg/edge/api/mocks"
    20  	"edge-infra.dev/pkg/edge/api/services/artifacts"
    21  	edgenode "edge-infra.dev/pkg/edge/api/services/edgenode/common"
    22  	sqlquery "edge-infra.dev/pkg/edge/api/sql"
    23  	"edge-infra.dev/pkg/edge/api/status"
    24  	"edge-infra.dev/pkg/edge/api/utils"
    25  	"edge-infra.dev/pkg/lib/crypto"
    26  	"edge-infra.dev/pkg/sds/clustersecrets/breakglass"
    27  	"edge-infra.dev/pkg/sds/clustersecrets/grub"
    28  	"edge-infra.dev/pkg/sds/k8s/bootstrap/tokens"
    29  )
    30  
    31  var (
    32  	terminalID            = "t001"
    33  	terminalID2           = "t002"
    34  	terminalClusterEdgeID = "cluster-0001"
    35  	// terminalClusterEdgeID2     = "cluster-0002"
    36  	terminalClusterName = "cluster-name-1"
    37  	// terminalClusterName2       = "cluster-name-2"
    38  	terminalBannerEdgeID = "banner-0001"
    39  	lane1                = "lane01"
    40  	lane7                = "lane07"
    41  	// lane20                     = "lane20"
    42  	lane21                   = "lane21"
    43  	terminalRoleWorker       = model.TerminalRoleTypeWorker
    44  	terminalRoleControlplane = model.TerminalRoleTypeControlplane
    45  	terminalHostname         = "ien-00005e0053af"
    46  	terminalHostname2        = "ien-1a74bbfed056"
    47  	// terminalHostname3          = "ien-dede376c3ce0"
    48  	terminalClassTouchpoint    = model.TerminalClassTypeTouchpoint
    49  	terminalClassServer        = model.TerminalClassTypeServer
    50  	terminalDiscoverDisksAll   = model.TerminalDiscoverDisksTypeAll
    51  	terminalDiscoverDisksEmpty = model.TerminalDiscoverDisksTypeEmpty
    52  	terminalPrimaryInterface   = "i001"
    53  	terminalInterfaceID        = "i001"
    54  	terminalInterfaceID2       = "i002"
    55  	terminalInterfaceID3       = "i003"
    56  	terminalInterfaceID4       = "i004"
    57  	terminalExistingEfiPart    = "/dev/sda1"
    58  	macAddress                 = "00:00:5e:00:53:af"
    59  	macAddressDashCapital      = "00-00-5E-00-53-AF"
    60  	macAddress2                = "1a:74:bb:fe:d0:56"
    61  	macAddress3                = "de:de:37:6c:3c:e0"
    62  	dhcp4False                 = false
    63  	dhcp4True                  = true
    64  	dhcp6False                 = false
    65  	// dhcp6True                  = true
    66  	gateway4           = "1.1.1.1"
    67  	gateway6           = "2.2.2.2"
    68  	terminalAddressID  = "a001"
    69  	terminalAddressID2 = "a002"
    70  	terminalAddressID3 = "a003"
    71  	// terminalAddressID4         = "a004"
    72  	ipv4        = "192.168.1.1"
    73  	ip2v4       = "209.142.228.41"
    74  	ipv6        = "6009:6076:90bf:7ce0:5a59:df56:3261:d70e"
    75  	prefixLen   = 24
    76  	prefixLen16 = 16
    77  	familyInet  = model.InetTypeInet
    78  	familyInet6 = model.InetTypeInet6
    79  	dnsService  = &model.ClusterNetworkServiceInfo{
    80  		ServiceType: "dns",
    81  		Family:      "inet",
    82  		IP:          "8.8.8.8",
    83  	}
    84  	ntpService = &model.ClusterNetworkServiceInfo{
    85  		ServiceType: "ntp",
    86  		Family:      "inet",
    87  		IP:          "time.google.com",
    88  	}
    89  	clusterNetworkServices = []*model.ClusterNetworkServiceInfo{dnsService, ntpService} // nolint // technically, unused when the test unconditionally skips
    90  	clusterCaHash          = uuid.NewString()
    91  	terminalDiskID         = "disk-001"
    92  	terminalDiskID2        = "disk-002"
    93  	devicePath             = "/dev/sdc"
    94  	devicePath2            = "/dev/sdf"
    95  	efiPath                = "/dev/sda1"
    96  	swapEnabled            = false
    97  	diskDiscoveryNone      = model.TerminalDiscoverDisksTypeNone
    98  	diskDiscoveryAll       = model.TerminalDiscoverDisksTypeAll
    99  )
   100  
   101  var (
   102  	terminalDiskColumns  = []string{"disk_id", "terminal_id", "include_disk", "expect_empty", "device_path", "use_part"}
   103  	terminalColumns      = []string{"terminal_id", "lane", "role", "cluster_edge_id", "cluster_name", "class", "discover_disks", "boot_disk", "primary_interface", "existing_efi_part", "swap_enabled", "hostname"}
   104  	terminalIfaceColumns = []string{"interface_id", "mac_address", "dhcp4", "dhcp6", "gateway4", "gateway6", "terminal_id"}
   105  	terminalAddrColumns  = []string{"address_id", "ip", "prefix_len", "family", "interface_id"}
   106  	terminals            = []model.Terminal{
   107  		{
   108  			TerminalID:       terminalID,
   109  			Lane:             &lane1,
   110  			Role:             terminalRoleControlplane,
   111  			Class:            &terminalClassServer,
   112  			ClusterEdgeID:    terminalClusterEdgeID,
   113  			ClusterName:      terminalClusterName,
   114  			Hostname:         terminalHostname,
   115  			DiscoverDisks:    &diskDiscoveryNone,
   116  			BootDisk:         &devicePath,
   117  			PrimaryInterface: &terminalInterfaceID,
   118  			ExistingEfiPart:  &efiPath,
   119  			SwapEnabled:      swapEnabled,
   120  			Disks: []*model.TerminalDisk{
   121  				{
   122  					TerminalID:     terminalID,
   123  					TerminalDiskID: terminalDiskID,
   124  					ExpectEmpty:    true,
   125  					IncludeDisk:    true,
   126  					DevicePath:     devicePath,
   127  					UsePart:        false,
   128  				},
   129  			},
   130  			Interfaces: []*model.TerminalInterface{
   131  				{
   132  					TerminalInterfaceID: terminalInterfaceID,
   133  					MacAddress:          macAddress,
   134  					Dhcp4:               dhcp4False,
   135  					Dhcp6:               dhcp6False,
   136  					Gateway4:            &gateway4,
   137  					Gateway6:            &gateway6,
   138  					TerminalID:          terminalID,
   139  					Addresses: []*model.TerminalAddress{
   140  						{
   141  							TerminalAddressID:   terminalAddressID,
   142  							IP:                  &ipv4,
   143  							PrefixLen:           prefixLen,
   144  							Family:              familyInet,
   145  							TerminalInterfaceID: terminalInterfaceID,
   146  						},
   147  					},
   148  				},
   149  				{
   150  					TerminalInterfaceID: terminalInterfaceID2,
   151  					MacAddress:          macAddress2,
   152  					Dhcp4:               dhcp4False,
   153  					Dhcp6:               dhcp6False,
   154  					Gateway4:            &gateway4,
   155  					Gateway6:            &gateway6,
   156  					TerminalID:          terminalID,
   157  					Addresses: []*model.TerminalAddress{
   158  						{
   159  							TerminalAddressID:   terminalAddressID2,
   160  							IP:                  &ip2v4,
   161  							PrefixLen:           prefixLen16,
   162  							Family:              familyInet,
   163  							TerminalInterfaceID: terminalInterfaceID2,
   164  						},
   165  						{
   166  							TerminalAddressID:   terminalAddressID3,
   167  							IP:                  &ipv4,
   168  							PrefixLen:           prefixLen16,
   169  							Family:              familyInet,
   170  							TerminalInterfaceID: terminalInterfaceID2,
   171  						},
   172  					},
   173  				},
   174  				{
   175  					TerminalInterfaceID: terminalInterfaceID3,
   176  					MacAddress:          macAddress3,
   177  					Dhcp4:               dhcp4True,
   178  					Dhcp6:               dhcp6False,
   179  					Gateway4:            &gateway4,
   180  					Gateway6:            &gateway6,
   181  					TerminalID:          terminalID,
   182  					Addresses:           []*model.TerminalAddress{},
   183  				},
   184  			},
   185  		},
   186  		{
   187  			TerminalID:       terminalID2,
   188  			Lane:             &lane7,
   189  			Role:             terminalRoleControlplane,
   190  			Class:            &terminalClassServer,
   191  			ClusterEdgeID:    terminalClusterEdgeID,
   192  			ClusterName:      terminalClusterName,
   193  			Hostname:         terminalHostname2,
   194  			DiscoverDisks:    &diskDiscoveryAll,
   195  			BootDisk:         &devicePath2,
   196  			PrimaryInterface: &terminalInterfaceID4,
   197  			ExistingEfiPart:  &efiPath,
   198  			SwapEnabled:      swapEnabled,
   199  			Disks: []*model.TerminalDisk{
   200  				{
   201  					TerminalID:     terminalID2,
   202  					TerminalDiskID: terminalDiskID2,
   203  					ExpectEmpty:    true,
   204  					IncludeDisk:    true,
   205  					DevicePath:     devicePath2,
   206  					UsePart:        false,
   207  				},
   208  			},
   209  			Interfaces: []*model.TerminalInterface{
   210  				{
   211  					TerminalInterfaceID: terminalInterfaceID4,
   212  					MacAddress:          macAddress,
   213  					Dhcp4:               dhcp4True,
   214  					Dhcp6:               dhcp6False,
   215  					Gateway4:            &gateway4,
   216  					Gateway6:            &gateway6,
   217  					TerminalID:          terminalID2,
   218  					Addresses: []*model.TerminalAddress{
   219  						{
   220  							TerminalAddressID:   terminalAddressID,
   221  							IP:                  &ipv4,
   222  							PrefixLen:           prefixLen,
   223  							Family:              familyInet,
   224  							TerminalInterfaceID: terminalInterfaceID4,
   225  						},
   226  					},
   227  				},
   228  			},
   229  		},
   230  	}
   231  )
   232  
   233  type terminalLaneAndHostname struct {
   234  	lane     *string
   235  	hostname string
   236  }
   237  
   238  const (
   239  	versionResource = `["{\"metadata\":{\"name\":\"test\",\"labels\":{\"feature.node.kubernetes.io/ien-version\":\"v1.0.0\"}}}","test-uuid"]`
   240  )
   241  
   242  func TestCreateTerminal(t *testing.T) {
   243  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   244  	if err != nil {
   245  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   246  	}
   247  	defer db.Close()
   248  
   249  	activationCode, err := crypto.GenerateRandomActivationCode()
   250  	assert.NoError(t, err)
   251  
   252  	hashDecoded := activationCode.Hashed()
   253  	hash := hex.EncodeToString(hashDecoded)
   254  
   255  	mock.ExpectBegin()
   256  	mock.ExpectQuery(sqlquery.GetClusterNameByClusterEdgeIDQuery).
   257  		WithArgs(terminalClusterEdgeID).
   258  		WillReturnRows(sqlmock.NewRows([]string{"cluster_name"}).
   259  			AddRow(terminalClusterName))
   260  	mockDBGetAllHostnamesForACluster(mock, terminalClusterEdgeID, []string{terminalHostname2})
   261  	mockDBGetAllLanesForACluster(mock, terminalClusterEdgeID, []terminalLaneAndHostname{
   262  		{lane: &lane1, hostname: terminalHostname2},
   263  	})
   264  
   265  	mockTerminal := terminals[0]
   266  	mockTerminal.Hostname, mockTerminal.ActivationCode, mockTerminal.Lane = terminalHostname, &hash, &lane21
   267  	mockIface := mockTerminal.Interfaces[1]
   268  	mockIface.MacAddress = macAddress
   269  	mockAddr1 := mockIface.Addresses[0]
   270  	mockAddr2 := mockIface.Addresses[1]
   271  
   272  	mockDBTerminalCreate(mock, mockTerminal, sqlmock.NewResult(1, 1))
   273  	mockDBTerminalInterfaceCreateQuery(mock, *mockIface, sqlmock.NewResult(1, 1))
   274  	mockDBTerminalAddressCreateQuery(mock, *mockAddr1, sqlmock.NewResult(1, 1))
   275  	mockDBTerminalAddressCreateQuery(mock, *mockAddr2, sqlmock.NewResult(1, 1))
   276  	mock.ExpectCommit()
   277  
   278  	artifactsService := artifacts.NewArtifactsService(db, nil)
   279  	labelSvc := NewLabelService(artifactsService, db)
   280  	service := NewTerminalService(db, labelSvc)
   281  
   282  	terminalAddress := []*model.TerminalAddressCreateInput{getAddrCreateInput(*mockAddr1), getAddrCreateInput(*mockAddr2)}
   283  
   284  	iface := getIfaceCreateInput(*mockIface)
   285  	iface.Addresses = terminalAddress
   286  	iface.MacAddress = macAddressDashCapital
   287  	ifaces := []*model.TerminalInterfaceCreateInput{iface}
   288  
   289  	terminal := getTerminalCreateInput(mockTerminal)
   290  	terminal.Interfaces = ifaces
   291  	terminal.Hostname = nil
   292  
   293  	newTerminal, err := service.CreateTerminalEntry(context.Background(), terminal, activationCode)
   294  	assert.NoError(t, err)
   295  	assert.Equal(t, macAddress, newTerminal.Interfaces[0].MacAddress)
   296  	expectedHostname := utils.CreateIENodeHostname(macAddress)
   297  	assert.Equal(t, expectedHostname, newTerminal.Hostname)
   298  
   299  	err = mock.ExpectationsWereMet()
   300  	assert.NoError(t, err)
   301  }
   302  
   303  func TestCreateTerminalDuplicateLaneNumber(t *testing.T) {
   304  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   305  	if err != nil {
   306  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   307  	}
   308  	defer db.Close()
   309  
   310  	activationCode, err := crypto.GenerateRandomActivationCode()
   311  	assert.NoError(t, err)
   312  
   313  	mock.ExpectBegin()
   314  	mock.ExpectQuery(sqlquery.GetClusterNameByClusterEdgeIDQuery).
   315  		WithArgs(terminalClusterEdgeID).
   316  		WillReturnRows(sqlmock.NewRows([]string{"cluster_name"}).
   317  			AddRow(terminalClusterName))
   318  	mockDBGetAllHostnamesForACluster(mock, terminalClusterEdgeID, []string{terminalHostname2})
   319  	mockDBGetAllLanesForACluster(mock, terminalClusterEdgeID, []terminalLaneAndHostname{
   320  		{lane: &lane1, hostname: terminalHostname2},
   321  	})
   322  
   323  	artifactsService := artifacts.NewArtifactsService(db, nil)
   324  	labelSvc := NewLabelService(artifactsService, db)
   325  	service := NewTerminalService(db, labelSvc)
   326  
   327  	terminalAddress := []*model.TerminalAddressCreateInput{
   328  		{
   329  			IP:        &ipv4,
   330  			PrefixLen: prefixLen,
   331  			Family:    familyInet,
   332  		},
   333  		{
   334  			IP:        &ipv6,
   335  			PrefixLen: prefixLen,
   336  			Family:    familyInet,
   337  		},
   338  	}
   339  	terminalInterface := []*model.TerminalInterfaceCreateInput{
   340  		{
   341  			MacAddress: macAddress,
   342  			Dhcp4:      dhcp4False,
   343  			Dhcp6:      dhcp6False,
   344  			Gateway4:   &gateway4,
   345  			Gateway6:   &gateway6,
   346  			Addresses:  terminalAddress,
   347  		},
   348  	}
   349  	terminal := model.TerminalCreateInput{
   350  		Lane:          &lane1,
   351  		Role:          terminalRoleWorker,
   352  		Class:         &terminalClassTouchpoint,
   353  		DiscoverDisks: &terminalDiscoverDisksEmpty,
   354  		BootDisk:      &devicePath2,
   355  		ClusterEdgeID: terminalClusterEdgeID,
   356  		Interfaces:    terminalInterface,
   357  	}
   358  
   359  	_, err = service.CreateTerminalEntry(context.Background(), &terminal, activationCode)
   360  	assert.Error(t, err)
   361  
   362  	err = mock.ExpectationsWereMet()
   363  	assert.NoError(t, err)
   364  }
   365  
   366  func TestCreateTerminalWithDHCPEmptyAddress(t *testing.T) {
   367  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   368  	if err != nil {
   369  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   370  	}
   371  	defer db.Close()
   372  
   373  	activationCode, err := crypto.GenerateRandomActivationCode()
   374  	assert.NoError(t, err)
   375  
   376  	hashDecoded := activationCode.Hashed()
   377  	hash := hex.EncodeToString(hashDecoded)
   378  
   379  	mock.ExpectBegin()
   380  	mock.ExpectQuery(sqlquery.GetClusterNameByClusterEdgeIDQuery).
   381  		WithArgs(terminalClusterEdgeID).
   382  		WillReturnRows(sqlmock.NewRows([]string{"cluster_name"}).
   383  			AddRow(terminalClusterName))
   384  	mockDBGetAllHostnamesForACluster(mock, terminalClusterEdgeID, []string{terminalHostname2})
   385  	mockDBGetAllLanesForACluster(mock, terminalClusterEdgeID, []terminalLaneAndHostname{
   386  		{lane: &lane1, hostname: terminalHostname2},
   387  	})
   388  
   389  	mockTerminal := terminals[1]
   390  	mockTerminal.Hostname, mockTerminal.ActivationCode = terminalHostname, &hash
   391  	mockIface := mockTerminal.Interfaces[0]
   392  
   393  	mockDBTerminalCreate(mock, mockTerminal, sqlmock.NewResult(1, 1))
   394  	mockDBTerminalInterfaceCreateQuery(mock, *mockIface, sqlmock.NewResult(1, 1))
   395  	mock.ExpectCommit()
   396  
   397  	artifactsService := artifacts.NewArtifactsService(db, nil)
   398  	labelSvc := NewLabelService(artifactsService, db)
   399  	service := NewTerminalService(db, labelSvc)
   400  
   401  	ifaces := []*model.TerminalInterfaceCreateInput{getIfaceCreateInput(*mockIface)}
   402  	terminal := getTerminalCreateInput(mockTerminal)
   403  	terminal.Interfaces = ifaces
   404  
   405  	_, err = service.CreateTerminalEntry(context.Background(), terminal, activationCode)
   406  	if err != nil {
   407  		t.Errorf("error was not expected while creating terminal: %s", err)
   408  	}
   409  
   410  	if err := mock.ExpectationsWereMet(); err != nil {
   411  		t.Errorf("there were unfulfilled expectations: %s", err)
   412  	}
   413  }
   414  
   415  func TestCreateTerminalWithDHCP(t *testing.T) {
   416  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   417  	if err != nil {
   418  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   419  	}
   420  	defer db.Close()
   421  
   422  	// dhcp4 = true and dhcp6 = false
   423  	activationCode, err := crypto.GenerateRandomActivationCode()
   424  	assert.NoError(t, err)
   425  
   426  	hashDecoded := activationCode.Hashed()
   427  	hash := hex.EncodeToString(hashDecoded)
   428  
   429  	mock.ExpectBegin()
   430  	mock.ExpectQuery(sqlquery.GetClusterNameByClusterEdgeIDQuery).
   431  		WithArgs(terminalClusterEdgeID).
   432  		WillReturnRows(sqlmock.NewRows([]string{"cluster_name"}).
   433  			AddRow(terminalClusterName))
   434  	mockDBGetAllHostnamesForACluster(mock, terminalClusterEdgeID, []string{terminalHostname2})
   435  	mockDBGetAllLanesForACluster(mock, terminalClusterEdgeID, []terminalLaneAndHostname{
   436  		{lane: &lane1, hostname: terminalHostname2},
   437  	})
   438  
   439  	mockTerminal := terminals[0]
   440  	mockTerminal.Hostname, mockTerminal.ActivationCode, mockTerminal.Lane = terminalHostname, &hash, &lane21
   441  	mockIface := mockTerminal.Interfaces[1]
   442  	mockIface.MacAddress, mockIface.Dhcp4, mockIface.Dhcp6, mockIface.Gateway4 = macAddress, true, false, nil
   443  	mockAddrs := mockIface.Addresses
   444  	mockAddrs[0].IP = nil
   445  
   446  	mockDBTerminalCreate(mock, mockTerminal, sqlmock.NewResult(1, 1))
   447  	mockDBTerminalInterfaceCreateQuery(mock, *mockIface, sqlmock.NewResult(1, 1))
   448  	mockDBTerminalAddressCreateQuery(mock, *mockAddrs[0], sqlmock.NewResult(1, 1))
   449  	mockDBTerminalAddressCreateQuery(mock, *mockAddrs[1], sqlmock.NewResult(1, 1))
   450  	mock.ExpectCommit()
   451  
   452  	artifactsService := artifacts.NewArtifactsService(db, nil)
   453  	labelSvc := NewLabelService(artifactsService, db)
   454  	service := NewTerminalService(db, labelSvc)
   455  	terminalAddress := []*model.TerminalAddressCreateInput{getAddrCreateInput(*mockAddrs[0]), getAddrCreateInput(*mockAddrs[1])}
   456  
   457  	iface := getIfaceCreateInput(*mockIface)
   458  	iface.MacAddress = macAddressDashCapital
   459  	iface.Addresses = terminalAddress
   460  	ifaces := []*model.TerminalInterfaceCreateInput{iface}
   461  	terminal := getTerminalCreateInput(mockTerminal)
   462  	terminal.Interfaces = ifaces
   463  
   464  	newTerminal, err := service.CreateTerminalEntry(context.Background(), terminal, activationCode)
   465  	assert.NoError(t, err)
   466  
   467  	assert.NotEmpty(t, newTerminal.Interfaces)
   468  	assert.Equal(t, macAddress, newTerminal.Interfaces[0].MacAddress)
   469  	assert.True(t, newTerminal.Interfaces[0].Dhcp4)
   470  	assert.False(t, newTerminal.Interfaces[0].Dhcp6)
   471  	assert.Nil(t, newTerminal.Interfaces[0].Gateway4)
   472  	assert.Nil(t, newTerminal.Interfaces[0].Addresses[0].IP)
   473  
   474  	if err := mock.ExpectationsWereMet(); err != nil {
   475  		t.Errorf("there were unfulfilled expectations: %s", err)
   476  	}
   477  
   478  	// dhcp4 = false and dhcp6 = true
   479  	mockIface.Dhcp4, mockIface.Dhcp6, mockIface.Gateway4, mockIface.Gateway6 = false, true, &gateway4, nil
   480  	mockAddrs[0].IP, mockAddrs[1].IP = &ipv4, nil
   481  	terminal.Interfaces = []*model.TerminalInterfaceCreateInput{getIfaceCreateInput(*mockIface)}
   482  
   483  	mock.ExpectBegin()
   484  	mock.ExpectQuery(sqlquery.GetClusterNameByClusterEdgeIDQuery).
   485  		WithArgs(terminalClusterEdgeID).
   486  		WillReturnRows(sqlmock.NewRows([]string{"cluster_name"}).
   487  			AddRow(terminalClusterName))
   488  	mockDBGetAllHostnamesForACluster(mock, terminalClusterEdgeID, []string{terminalHostname2})
   489  	mockDBGetAllLanesForACluster(mock, terminalClusterEdgeID, []terminalLaneAndHostname{
   490  		{lane: &lane1, hostname: terminalHostname2},
   491  	})
   492  	mockDBTerminalCreate(mock, mockTerminal, sqlmock.NewResult(1, 1))
   493  	mockDBTerminalInterfaceCreateQuery(mock, *mockIface, sqlmock.NewResult(1, 1))
   494  	mockDBTerminalAddressCreateQuery(mock, *mockAddrs[0], sqlmock.NewResult(1, 1))
   495  	mockDBTerminalAddressCreateQuery(mock, *mockAddrs[1], sqlmock.NewResult(1, 1))
   496  	mock.ExpectCommit()
   497  
   498  	labelSvc = NewLabelService(artifactsService, db)
   499  	service = NewTerminalService(db, labelSvc)
   500  
   501  	terminalAddress = []*model.TerminalAddressCreateInput{getAddrCreateInput(*mockAddrs[0]), getAddrCreateInput(*mockAddrs[1])}
   502  	terminal.Interfaces[0].Addresses = terminalAddress
   503  
   504  	newTerminal, err = service.CreateTerminalEntry(context.Background(), terminal, activationCode)
   505  	assert.NoError(t, err)
   506  
   507  	assert.NotEmpty(t, newTerminal.Interfaces)
   508  	assert.False(t, newTerminal.Interfaces[0].Dhcp4)
   509  	assert.True(t, newTerminal.Interfaces[0].Dhcp6)
   510  	assert.Nil(t, newTerminal.Interfaces[0].Gateway6)
   511  	assert.Nil(t, newTerminal.Interfaces[0].Addresses[1].IP)
   512  
   513  	if err := mock.ExpectationsWereMet(); err != nil {
   514  		t.Errorf("there were unfulfilled expectations: %s", err)
   515  	}
   516  
   517  	// dhcp4 = true and dhcp6 = true
   518  	mockIface.Dhcp4, mockIface.Dhcp6, mockIface.Gateway4, mockIface.Gateway6 = true, true, nil, nil
   519  	terminal.Interfaces = []*model.TerminalInterfaceCreateInput{getIfaceCreateInput(*mockIface)}
   520  	mockAddrs[0].IP, mockAddrs[1].IP = nil, nil
   521  
   522  	mock.ExpectBegin()
   523  	mock.ExpectQuery(sqlquery.GetClusterNameByClusterEdgeIDQuery).
   524  		WithArgs(terminalClusterEdgeID).
   525  		WillReturnRows(sqlmock.NewRows([]string{"cluster_name"}).
   526  			AddRow(terminalClusterName))
   527  	mockDBGetAllHostnamesForACluster(mock, terminalClusterEdgeID, []string{terminalHostname2})
   528  	mockDBGetAllLanesForACluster(mock, terminalClusterEdgeID, []terminalLaneAndHostname{
   529  		{lane: &lane1, hostname: terminalHostname2},
   530  	})
   531  	mockDBTerminalCreate(mock, mockTerminal, sqlmock.NewResult(1, 1))
   532  	mockDBTerminalInterfaceCreateQuery(mock, *mockIface, sqlmock.NewResult(1, 1))
   533  	mockDBTerminalAddressCreateQuery(mock, *mockAddrs[0], sqlmock.NewResult(1, 1))
   534  	mockDBTerminalAddressCreateQuery(mock, *mockAddrs[1], sqlmock.NewResult(1, 1))
   535  	mock.ExpectCommit()
   536  
   537  	labelSvc = NewLabelService(artifactsService, db)
   538  	service = NewTerminalService(db, labelSvc)
   539  
   540  	terminalAddress = []*model.TerminalAddressCreateInput{getAddrCreateInput(*mockAddrs[0]), getAddrCreateInput(*mockAddrs[1])}
   541  	terminal.Interfaces[0].Addresses = terminalAddress
   542  
   543  	newTerminal, err = service.CreateTerminalEntry(context.Background(), terminal, activationCode)
   544  	assert.NoError(t, err)
   545  
   546  	assert.NotEmpty(t, newTerminal.Interfaces)
   547  	assert.True(t, newTerminal.Interfaces[0].Dhcp4)
   548  	assert.Nil(t, newTerminal.Interfaces[0].Gateway4)
   549  	assert.Nil(t, newTerminal.Interfaces[0].Addresses[0].IP)
   550  	assert.True(t, newTerminal.Interfaces[0].Dhcp6)
   551  	assert.Nil(t, newTerminal.Interfaces[0].Gateway6)
   552  	assert.Nil(t, newTerminal.Interfaces[0].Addresses[1].IP)
   553  
   554  	if err := mock.ExpectationsWereMet(); err != nil {
   555  		t.Errorf("there were unfulfilled expectations: %s", err)
   556  	}
   557  }
   558  
   559  func TestCreateTerminalWithDHCPError(t *testing.T) {
   560  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   561  	if err != nil {
   562  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   563  	}
   564  	defer db.Close()
   565  
   566  	activationCode, err := crypto.GenerateRandomActivationCode()
   567  	assert.NoError(t, err)
   568  
   569  	hashDecoded := activationCode.Hashed()
   570  	hash := hex.EncodeToString(hashDecoded)
   571  
   572  	mock.ExpectBegin()
   573  	mock.ExpectQuery(sqlquery.GetClusterNameByClusterEdgeIDQuery).
   574  		WithArgs(terminalClusterEdgeID).
   575  		WillReturnRows(sqlmock.NewRows([]string{"cluster_name"}).
   576  			AddRow(terminalClusterName))
   577  	mockDBGetAllHostnamesForACluster(mock, terminalClusterEdgeID, []string{terminalHostname2})
   578  	mockDBGetAllLanesForACluster(mock, terminalClusterEdgeID, []terminalLaneAndHostname{
   579  		{lane: &lane1, hostname: terminalHostname2},
   580  	})
   581  	mockTerminal := terminals[1]
   582  	mockTerminal.Hostname, mockTerminal.ActivationCode = terminalHostname, &hash
   583  	mockIface := mockTerminal.Interfaces[0]
   584  
   585  	mockDBTerminalCreate(mock, mockTerminal, sqlmock.NewResult(1, 1))
   586  	mockDBTerminalInterfaceCreateQuery(mock, *mockIface, sqlmock.NewResult(1, 1))
   587  	mock.ExpectRollback()
   588  
   589  	artifactsService := artifacts.NewArtifactsService(db, nil)
   590  	labelSvc := NewLabelService(artifactsService, db)
   591  	service := NewTerminalService(db, labelSvc)
   592  
   593  	ifaces := []*model.TerminalInterfaceCreateInput{getIfaceCreateInput(*mockIface)}
   594  	terminal := getTerminalCreateInput(mockTerminal)
   595  	terminal.Interfaces = ifaces
   596  
   597  	_, err = service.CreateTerminalEntry(context.Background(), terminal, activationCode)
   598  	assert.Error(t, err)
   599  }
   600  
   601  func TestCreateTerminalInvalidIP(t *testing.T) {
   602  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   603  	if err != nil {
   604  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   605  	}
   606  	defer db.Close()
   607  
   608  	activationCode, err := crypto.GenerateRandomActivationCode()
   609  	assert.NoError(t, err)
   610  
   611  	hashDecoded := activationCode.Hashed()
   612  	hash := hex.EncodeToString(hashDecoded)
   613  
   614  	mock.ExpectBegin()
   615  	mock.ExpectQuery(sqlquery.GetClusterNameByClusterEdgeIDQuery).
   616  		WithArgs(terminalClusterEdgeID).
   617  		WillReturnRows(sqlmock.NewRows([]string{"cluster_name"}).
   618  			AddRow(terminalClusterName))
   619  	mockDBGetAllHostnamesForACluster(mock, terminalClusterEdgeID, []string{terminalHostname2})
   620  	mockDBGetAllLanesForACluster(mock, terminalClusterEdgeID, []terminalLaneAndHostname{
   621  		{lane: &lane21, hostname: terminalHostname2},
   622  	})
   623  
   624  	mockTerminal := terminals[1]
   625  	mockTerminal.Hostname, mockTerminal.ActivationCode = terminalHostname, &hash
   626  	mockIface := mockTerminal.Interfaces[0]
   627  
   628  	mockDBTerminalCreate(mock, mockTerminal, sqlmock.NewResult(1, 1))
   629  	mockDBTerminalInterfaceCreateQuery(mock, *mockIface, sqlmock.NewResult(1, 1))
   630  	mock.ExpectRollback()
   631  
   632  	artifactsService := artifacts.NewArtifactsService(db, nil)
   633  	labelSvc := NewLabelService(artifactsService, db)
   634  	service := NewTerminalService(db, labelSvc)
   635  
   636  	incorrectIP := "x.x.x.x"
   637  	terminalAddress := []*model.TerminalAddressCreateInput{
   638  		{
   639  			IP:        &incorrectIP,
   640  			PrefixLen: prefixLen,
   641  			Family:    familyInet,
   642  		},
   643  	}
   644  
   645  	iface := getIfaceCreateInput(*mockIface)
   646  	iface.Addresses = terminalAddress
   647  	terminal := getTerminalCreateInput(mockTerminal)
   648  	terminal.Interfaces = []*model.TerminalInterfaceCreateInput{iface}
   649  
   650  	_, err = service.CreateTerminalEntry(context.Background(), terminal, activationCode)
   651  	assert.ErrorContains(t, err, "invalid address ip: x.x.x.x")
   652  }
   653  
   654  func TestCreateTerminalInvalidMac(t *testing.T) {
   655  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   656  	if err != nil {
   657  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   658  	}
   659  	defer db.Close()
   660  
   661  	incorrectMac, hostname := "123321", "ien-123321"
   662  	activationCode, err := crypto.GenerateRandomActivationCode()
   663  	assert.NoError(t, err)
   664  
   665  	hashDecoded := activationCode.Hashed()
   666  	hash := hex.EncodeToString(hashDecoded)
   667  
   668  	mock.ExpectBegin()
   669  	mock.ExpectQuery(sqlquery.GetClusterNameByClusterEdgeIDQuery).
   670  		WithArgs(terminalClusterEdgeID).
   671  		WillReturnRows(sqlmock.NewRows([]string{"cluster_name"}).
   672  			AddRow(terminalClusterName))
   673  	mockDBGetAllHostnamesForACluster(mock, terminalClusterEdgeID, []string{terminalHostname2})
   674  	mockDBGetAllLanesForACluster(mock, terminalClusterEdgeID, []terminalLaneAndHostname{
   675  		{lane: &lane21, hostname: terminalHostname2},
   676  	})
   677  	mockTerminal := terminals[1]
   678  	mockTerminal.Hostname, mockTerminal.ActivationCode = hostname, &hash
   679  	mockDBTerminalCreate(mock, mockTerminal, sqlmock.NewResult(1, 1))
   680  	mock.ExpectRollback()
   681  
   682  	artifactsService := artifacts.NewArtifactsService(db, nil)
   683  	labelSvc := NewLabelService(artifactsService, db)
   684  	service := NewTerminalService(db, labelSvc)
   685  
   686  	terminalAddress := []*model.TerminalAddressCreateInput{
   687  		{
   688  			IP:        &ipv4,
   689  			PrefixLen: prefixLen,
   690  			Family:    familyInet,
   691  		},
   692  	}
   693  	terminalInterface := []*model.TerminalInterfaceCreateInput{
   694  		{
   695  			MacAddress: incorrectMac,
   696  			Dhcp4:      dhcp4False,
   697  			Dhcp6:      dhcp6False,
   698  			Gateway4:   &gateway4,
   699  			Gateway6:   &gateway6,
   700  			Addresses:  terminalAddress,
   701  		},
   702  	}
   703  	terminal := model.TerminalCreateInput{
   704  		Lane:          mockTerminal.Lane,
   705  		Role:          mockTerminal.Role,
   706  		Class:         mockTerminal.Class,
   707  		ClusterEdgeID: mockTerminal.ClusterEdgeID,
   708  		Hostname:      &mockTerminal.Hostname,
   709  		DiscoverDisks: mockTerminal.DiscoverDisks,
   710  		BootDisk:      mockTerminal.BootDisk,
   711  		Interfaces:    terminalInterface,
   712  	}
   713  
   714  	_, err = service.CreateTerminalEntry(context.Background(), &terminal, activationCode)
   715  	assert.Error(t, err)
   716  	assert.ErrorContains(t, err, incorrectMac)
   717  }
   718  
   719  func TestCreateTerminalValidButUppercaseMac(t *testing.T) {
   720  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   721  	if err != nil {
   722  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   723  	}
   724  	defer db.Close()
   725  
   726  	uppercaseMac, hostname := "A1:B2:C3:D4:E5:F6", "ien-a1b2c3d4e5f6"
   727  	activationCode, err := crypto.GenerateRandomActivationCode()
   728  	assert.NoError(t, err)
   729  
   730  	hashDecoded := activationCode.Hashed()
   731  	hash := hex.EncodeToString(hashDecoded)
   732  
   733  	mock.ExpectBegin()
   734  	mock.ExpectQuery(sqlquery.GetClusterNameByClusterEdgeIDQuery).
   735  		WithArgs(terminalClusterEdgeID).
   736  		WillReturnRows(sqlmock.NewRows([]string{"cluster_name"}).
   737  			AddRow(terminalClusterName))
   738  	mockDBGetAllHostnamesForACluster(mock, terminalClusterEdgeID, []string{terminalHostname2})
   739  	mockDBGetAllLanesForACluster(mock, terminalClusterEdgeID, []terminalLaneAndHostname{
   740  		{lane: &lane1, hostname: terminalHostname2},
   741  	})
   742  
   743  	mockTerminal := terminals[0]
   744  	mockTerminal.Hostname, mockTerminal.ActivationCode, mockTerminal.Lane = hostname, &hash, &lane21
   745  	mockIface := mockTerminal.Interfaces[1]
   746  	mockIface.MacAddress = strings.ToLower(uppercaseMac)
   747  	mockAddrs := mockIface.Addresses
   748  
   749  	mockDBTerminalCreate(mock, mockTerminal, sqlmock.NewResult(1, 1))
   750  	mockDBTerminalInterfaceCreateQuery(mock, *mockIface, sqlmock.NewResult(1, 1))
   751  	mockDBTerminalAddressCreateQuery(mock, *mockAddrs[0], sqlmock.NewResult(1, 1))
   752  	mockDBTerminalAddressCreateQuery(mock, *mockAddrs[1], sqlmock.NewResult(1, 1))
   753  	mock.ExpectCommit()
   754  
   755  	artifactsService := artifacts.NewArtifactsService(db, nil)
   756  	labelSvc := NewLabelService(artifactsService, db)
   757  	service := NewTerminalService(db, labelSvc)
   758  
   759  	terminalAddress := []*model.TerminalAddressCreateInput{getAddrCreateInput(*mockAddrs[0]), getAddrCreateInput(*mockAddrs[1])}
   760  	iface := getIfaceCreateInput(*mockIface)
   761  	iface.MacAddress = uppercaseMac
   762  	iface.Addresses = terminalAddress
   763  	terminal := getTerminalCreateInput(mockTerminal)
   764  	terminal.Interfaces = []*model.TerminalInterfaceCreateInput{iface}
   765  
   766  	createdTerminal, err := service.CreateTerminalEntry(context.Background(), terminal, activationCode)
   767  	assert.NoError(t, err)
   768  	assert.Equal(t, hostname, createdTerminal.Hostname)
   769  }
   770  
   771  func TestCreateTerminalEmptyClass(t *testing.T) {
   772  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   773  	if err != nil {
   774  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   775  	}
   776  	defer db.Close()
   777  
   778  	activationCode, err := crypto.GenerateRandomActivationCode()
   779  	assert.NoError(t, err)
   780  
   781  	hashDecoded := activationCode.Hashed()
   782  	hash := hex.EncodeToString(hashDecoded)
   783  
   784  	mock.ExpectBegin()
   785  	mock.ExpectQuery(sqlquery.GetClusterNameByClusterEdgeIDQuery).
   786  		WithArgs(terminalClusterEdgeID).
   787  		WillReturnRows(sqlmock.NewRows([]string{"cluster_name"}).
   788  			AddRow(terminalClusterName))
   789  	mockDBGetAllHostnamesForACluster(mock, terminalClusterEdgeID, []string{terminalHostname2})
   790  	mockDBGetAllLanesForACluster(mock, terminalClusterEdgeID, []terminalLaneAndHostname{
   791  		{lane: &lane1, hostname: terminalHostname2},
   792  	})
   793  
   794  	mockTerminal := terminals[0]
   795  	mockTerminal.Hostname, mockTerminal.ActivationCode, mockTerminal.Lane = terminalHostname, &hash, &lane21
   796  	mockIface := mockTerminal.Interfaces[0]
   797  	mockAddr := mockIface.Addresses[0]
   798  
   799  	mockDBTerminalCreate(mock, mockTerminal, sqlmock.NewResult(1, 1))
   800  	mockDBTerminalInterfaceCreateQuery(mock, *mockIface, sqlmock.NewResult(1, 1))
   801  	mockDBTerminalAddressCreateQuery(mock, *mockAddr, sqlmock.NewResult(1, 1))
   802  	mock.ExpectCommit()
   803  
   804  	artifactsService := artifacts.NewArtifactsService(db, nil)
   805  	labelSvc := NewLabelService(artifactsService, db)
   806  	service := NewTerminalService(db, labelSvc)
   807  
   808  	terminalAddress := []*model.TerminalAddressCreateInput{getAddrCreateInput(*mockAddr)}
   809  
   810  	iface := getIfaceCreateInput(*mockIface)
   811  	iface.Addresses = terminalAddress
   812  	terminal := getTerminalCreateInput(mockTerminal)
   813  	terminal.Interfaces = []*model.TerminalInterfaceCreateInput{iface}
   814  
   815  	_, err = service.CreateTerminalEntry(context.Background(), terminal, activationCode)
   816  	assert.NoError(t, err)
   817  
   818  	err = mock.ExpectationsWereMet()
   819  	assert.NoError(t, err)
   820  }
   821  
   822  func TestCreateTerminalRollback(t *testing.T) { //nolint
   823  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   824  	if err != nil {
   825  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   826  	}
   827  	defer db.Close()
   828  
   829  	activationCode, err := crypto.GenerateRandomActivationCode()
   830  	assert.NoError(t, err)
   831  
   832  	hashDecoded := activationCode.Hashed()
   833  	hash := hex.EncodeToString(hashDecoded)
   834  
   835  	mock.ExpectBegin()
   836  	mock.ExpectQuery(sqlquery.GetClusterNameByClusterEdgeIDQuery).
   837  		WithArgs(terminalClusterEdgeID).
   838  		WillReturnRows(sqlmock.NewRows([]string{"cluster_name"}).
   839  			AddRow(terminalClusterName))
   840  	mockDBGetAllHostnamesForACluster(mock, terminalClusterEdgeID, []string{terminalHostname2})
   841  	mockDBGetAllLanesForACluster(mock, terminalClusterEdgeID, []terminalLaneAndHostname{
   842  		{lane: &lane21, hostname: terminalHostname2},
   843  	})
   844  
   845  	mockTerminal := terminals[1]
   846  	mockTerminal.Hostname, mockTerminal.ActivationCode = terminalHostname, &hash
   847  	mockIface := mockTerminal.Interfaces[0]
   848  	mockAddr := mockIface.Addresses[0]
   849  
   850  	mockDBTerminalCreate(mock, mockTerminal, sqlmock.NewResult(1, 1))
   851  	mockDBTerminalInterfaceCreateQuery(mock, *mockIface, sqlmock.NewResult(1, 1))
   852  	mockDBTerminalAddressCreateQuery(mock, *mockAddr, sqlmock.NewResult(1, 1))
   853  	mock.ExpectRollback()
   854  
   855  	artifactsService := artifacts.NewArtifactsService(db, nil)
   856  	labelSvc := NewLabelService(artifactsService, db)
   857  	service := NewTerminalService(db, labelSvc)
   858  
   859  	terminalAddress := []*model.TerminalAddressCreateInput{getAddrCreateInput(*mockAddr)}
   860  	iface := getIfaceCreateInput(*mockIface)
   861  	iface.Addresses = terminalAddress
   862  	terminal := getTerminalCreateInput(mockTerminal)
   863  	terminal.Interfaces = []*model.TerminalInterfaceCreateInput{iface}
   864  
   865  	_, err = service.CreateTerminalEntry(context.Background(), terminal, activationCode)
   866  	assert.Error(t, err)
   867  }
   868  
   869  func TestMissingIpv4AddressRollback(t *testing.T) {
   870  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   871  	if err != nil {
   872  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   873  	}
   874  	defer db.Close()
   875  
   876  	activationCode, err := crypto.GenerateRandomActivationCode()
   877  	assert.NoError(t, err)
   878  
   879  	hashDecoded := activationCode.Hashed()
   880  	hash := hex.EncodeToString(hashDecoded)
   881  
   882  	mock.ExpectBegin()
   883  	mock.ExpectQuery(sqlquery.GetClusterNameByClusterEdgeIDQuery).
   884  		WithArgs(terminalClusterEdgeID).
   885  		WillReturnRows(sqlmock.NewRows([]string{"cluster_name"}).
   886  			AddRow(terminalClusterName))
   887  	mockDBGetAllHostnamesForACluster(mock, terminalClusterEdgeID, []string{terminalHostname2})
   888  	mockDBGetAllLanesForACluster(mock, terminalClusterEdgeID, []terminalLaneAndHostname{
   889  		{lane: &lane1, hostname: terminalHostname2},
   890  	})
   891  
   892  	mockTerminal := terminals[1]
   893  	mockTerminal.Hostname, mockTerminal.ActivationCode = terminalHostname, &hash
   894  	mockIface := mockTerminal.Interfaces[0]
   895  	mockIface.Dhcp4, mockIface.Dhcp6, mockIface.Gateway4, mockIface.Gateway6 = false, false, &gateway4, &gateway6
   896  	mockAddr := mockIface.Addresses[0]
   897  	mockAddr.IP, mockAddr.Family = &ipv6, familyInet6
   898  
   899  	mockDBTerminalCreate(mock, mockTerminal, sqlmock.NewResult(1, 1))
   900  	mockDBTerminalInterfaceCreateQuery(mock, *mockIface, sqlmock.NewResult(1, 1))
   901  	mockDBTerminalAddressCreateQuery(mock, *mockAddr, sqlmock.NewResult(1, 1))
   902  	mock.ExpectRollback()
   903  
   904  	artifactsService := artifacts.NewArtifactsService(db, nil)
   905  	labelSvc := NewLabelService(artifactsService, db)
   906  	service := NewTerminalService(db, labelSvc)
   907  
   908  	terminalAddress := []*model.TerminalAddressCreateInput{getAddrCreateInput(*mockAddr)}
   909  	iface := getIfaceCreateInput(*mockIface)
   910  	iface.Addresses = terminalAddress
   911  	terminal := getTerminalCreateInput(mockTerminal)
   912  	terminal.Interfaces = []*model.TerminalInterfaceCreateInput{iface}
   913  
   914  	_, err = service.CreateTerminalEntry(context.Background(), terminal, activationCode)
   915  	assert.Error(t, err)
   916  	assert.Equal(t, "terminal address validation failed - missing ipv4 address", err.Error())
   917  }
   918  
   919  func TestCreateTerminalHostnameExists(t *testing.T) { //nolint
   920  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   921  	if err != nil {
   922  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   923  	}
   924  	defer db.Close()
   925  
   926  	activationCode, err := crypto.GenerateRandomActivationCode()
   927  	assert.NoError(t, err)
   928  
   929  	hashDecoded := activationCode.Hashed()
   930  	hash := hex.EncodeToString(hashDecoded)
   931  
   932  	mock.ExpectBegin()
   933  	mock.ExpectQuery(sqlquery.GetClusterNameByClusterEdgeIDQuery).
   934  		WithArgs(terminalClusterEdgeID).
   935  		WillReturnRows(sqlmock.NewRows([]string{"cluster_name"}).
   936  			AddRow(terminalClusterName))
   937  	mockDBGetAllHostnamesForACluster(mock, terminalClusterEdgeID, []string{terminalHostname})
   938  	mockDBGetAllLanesForACluster(mock, terminalClusterEdgeID, []terminalLaneAndHostname{
   939  		{lane: &lane1, hostname: terminalHostname2},
   940  	})
   941  
   942  	mockTerminal := terminals[1]
   943  	mockTerminal.Hostname, mockTerminal.ActivationCode = terminalHostname, &hash
   944  	mockIface := mockTerminal.Interfaces[0]
   945  	mockAddr := mockIface.Addresses[0]
   946  
   947  	mockDBTerminalCreate(mock, mockTerminal, sqlmock.NewResult(1, 1))
   948  	mockDBTerminalInterfaceCreateQuery(mock, *mockIface, sqlmock.NewResult(1, 1))
   949  	mockDBTerminalAddressCreateQuery(mock, *mockAddr, sqlmock.NewResult(1, 1))
   950  	mock.ExpectCommit()
   951  
   952  	artifactsService := artifacts.NewArtifactsService(db, nil)
   953  	labelSvc := NewLabelService(artifactsService, db)
   954  	service := NewTerminalService(db, labelSvc)
   955  
   956  	terminalAddress := []*model.TerminalAddressCreateInput{getAddrCreateInput(*mockAddr)}
   957  	iface := getIfaceCreateInput(*mockIface)
   958  	iface.Addresses = terminalAddress
   959  	terminal := getTerminalCreateInput(mockTerminal)
   960  	terminal.Interfaces = []*model.TerminalInterfaceCreateInput{iface}
   961  
   962  	_, err = service.CreateTerminalEntry(context.Background(), terminal, activationCode)
   963  	assert.Error(t, err)
   964  }
   965  
   966  func TestDeleteTerminal(t *testing.T) {
   967  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   968  	if err != nil {
   969  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   970  	}
   971  	defer db.Close()
   972  
   973  	mockDBTerminalDelete(mock, terminalID, sqlmock.NewResult(1, 1))
   974  	artifactsService := artifacts.NewArtifactsService(db, nil)
   975  
   976  	labelSvc := NewLabelService(artifactsService, db)
   977  	service := NewTerminalService(db, labelSvc)
   978  
   979  	if err := service.DeleteTerminalEntry(context.Background(), terminalID); err != nil {
   980  		t.Errorf("error was not expected while deleting terminal: %s", err)
   981  	}
   982  
   983  	if err := mock.ExpectationsWereMet(); err != nil {
   984  		t.Errorf("there were unfulfilled expectations: %s", err)
   985  	}
   986  }
   987  
   988  func TestUpdateTerminal(t *testing.T) {
   989  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   990  	if err != nil {
   991  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   992  	}
   993  	defer db.Close()
   994  
   995  	mockAcReal, err := crypto.GenerateRandomActivationCode()
   996  	assert.NoError(t, err)
   997  	mockAc := mockAcReal.Plain()
   998  
   999  	mockTerminal := terminals[0]
  1000  	mockIface := mockTerminal.Interfaces[0]
  1001  	mockIfaces := []*model.TerminalInterface{mockIface}
  1002  	mockAddr := mockIface.Addresses[0]
  1003  	mockAddrs := []*model.TerminalAddress{mockAddr}
  1004  	result := sqlmock.NewResult(1, 1)
  1005  
  1006  	mock.ExpectBegin()
  1007  	mockDBGetTerminalByID(mock, mockTerminal.TerminalID, &mockTerminal)
  1008  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, mockTerminal.TerminalID, mockIfaces)
  1009  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, mockIface.TerminalInterfaceID, mockAddrs)
  1010  	mockDBGetTerminalDiskByTerminalID(mock, terminalID, nil)
  1011  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  1012  		WithArgs(mockTerminal.TerminalID, sql.NullString{}).
  1013  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  1014  			AddRow(mockTerminal.TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  1015  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  1016  		WithArgs(mockTerminal.ClusterEdgeID).
  1017  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  1018  			AddRow("test-org"))
  1019  	mockDBGetAllLanesForACluster(mock, mockTerminal.ClusterEdgeID, []terminalLaneAndHostname{
  1020  		{lane: &lane7, hostname: terminalHostname2},
  1021  	})
  1022  
  1023  	newIP := "144.26.1.2"
  1024  	mockTerminal.Role, mockIface.MacAddress, mockIface.Addresses[0].IP, mockTerminal.DiscoverDisks = terminalRoleControlplane,
  1025  		"16:54:fc:29:a7:7a", &newIP, &terminalDiscoverDisksEmpty
  1026  	mockDBGetActivationCode(mock, terminalID, mockAc)
  1027  	mockDBTerminalUpdate(mock, terminalID, model.TerminalUpdateInput{
  1028  		Lane: mockTerminal.Lane, Role: &mockTerminal.Role, Class: mockTerminal.Class, DiscoverDisks: mockTerminal.DiscoverDisks, BootDisk: mockTerminal.BootDisk, PrimaryInterface: mockTerminal.PrimaryInterface, ExistingEfiPart: mockTerminal.ExistingEfiPart, SwapEnabled: &mockTerminal.SwapEnabled,
  1029  	}, sqlmock.NewResult(1, 1))
  1030  	mockDBTerminalInterfaceUpdateQuery(mock, terminalInterfaceID, model.TerminalInterfaceUpdateInput{
  1031  		MacAddress: &mockIface.MacAddress, Dhcp4: &mockIface.Dhcp4, Dhcp6: &mockIface.Dhcp6, Gateway4: mockIface.Gateway4, Gateway6: mockIface.Gateway6,
  1032  	}, result)
  1033  	mockDBTerminalAddressUpdateQuery(mock, mockIface.Addresses[0].TerminalAddressID, model.TerminalAddressUpdateInput{
  1034  		IP: mockIface.Addresses[0].IP, PrefixLen: &mockIface.Addresses[0].PrefixLen, Family: &mockIface.Addresses[0].Family,
  1035  	}, sqlmock.NewResult(1, 1))
  1036  	mock.ExpectCommit()
  1037  
  1038  	mockDBGetTerminalByID(mock, mockTerminal.TerminalID, &mockTerminal)
  1039  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, mockIface.TerminalID, mockIfaces)
  1040  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, mockIface.TerminalInterfaceID, mockAddrs)
  1041  	mockDBGetTerminalDiskByTerminalID(mock, terminalID, nil)
  1042  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  1043  		WithArgs(mockTerminal.TerminalID, sql.NullString{}).
  1044  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  1045  			AddRow(mockTerminal.TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  1046  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  1047  		WithArgs(mockTerminal.ClusterEdgeID).
  1048  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  1049  			AddRow("test-org"))
  1050  
  1051  	getKubeResource := func() GetKubeResourceFunc {
  1052  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  1053  			assert.Equal(t, projectID, _projectID)
  1054  			assert.Nil(t, cluster)
  1055  			res := versionResource
  1056  			return []string{res}, nil
  1057  		}
  1058  	}
  1059  	bqClientMock := createMockBQClient(t, getKubeResource())
  1060  	artifactsService := artifacts.NewArtifactsService(db, nil)
  1061  	labelSvc := NewLabelService(artifactsService, db)
  1062  	activationSvc := mocks.NewMockActivationCode(gomock.NewController(t))
  1063  	activationSvc.EXPECT().Fetch(gomock.Any(), terminalID).Return(&mockAc, nil).AnyTimes()
  1064  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  1065  
  1066  	terminalAddress := []*model.TerminalAddressIDInput{
  1067  		{
  1068  			TerminalAddressID: terminalAddressID,
  1069  			TerminalAddressValues: &model.TerminalAddressUpdateInput{
  1070  				IP: &newIP,
  1071  			},
  1072  		},
  1073  	}
  1074  	terminalInterface := []*model.TerminalInterfaceIDInput{
  1075  		{
  1076  			TerminalInterfaceID: terminalInterfaceID,
  1077  			TerminalInterfaceValues: &model.TerminalInterfaceUpdateInput{
  1078  				MacAddress: &mockTerminal.Interfaces[0].MacAddress,
  1079  				Addresses:  terminalAddress,
  1080  			},
  1081  		},
  1082  	}
  1083  	terminal := model.TerminalUpdateInput{
  1084  		Lane:             mockTerminal.Lane,
  1085  		Role:             &mockTerminal.Role,
  1086  		Class:            &terminalClassServer,
  1087  		DiscoverDisks:    mockTerminal.DiscoverDisks,
  1088  		BootDisk:         mockTerminal.BootDisk,
  1089  		PrimaryInterface: mockTerminal.PrimaryInterface,
  1090  		ExistingEfiPart:  mockTerminal.ExistingEfiPart,
  1091  		Interfaces:       terminalInterface,
  1092  		SwapEnabled:      &mockTerminal.SwapEnabled,
  1093  	}
  1094  	terminalUpdate := model.TerminalIDInput{
  1095  		TerminalID:     terminalID,
  1096  		TerminalValues: &terminal,
  1097  	}
  1098  
  1099  	updatedTerminal, err := service.UpdateTerminalEntry(context.Background(), &terminalUpdate)
  1100  	assert.NoError(t, err)
  1101  
  1102  	assert.Equal(t, mockTerminal.Lane, updatedTerminal.Lane)
  1103  	assert.Equal(t, mockTerminal.Role, updatedTerminal.Role)
  1104  	assert.Equal(t, *mockTerminal.DiscoverDisks, *updatedTerminal.DiscoverDisks)
  1105  	assert.Equal(t, mockTerminal.BootDisk, updatedTerminal.BootDisk)
  1106  	assert.Equal(t, mockTerminal.ExistingEfiPart, updatedTerminal.ExistingEfiPart)
  1107  	assert.Equal(t, mockTerminal.SwapEnabled, updatedTerminal.SwapEnabled)
  1108  	assert.Equal(t, mockTerminal.PrimaryInterface, updatedTerminal.PrimaryInterface)
  1109  	assert.Equal(t, mockIface.MacAddress, updatedTerminal.Interfaces[0].MacAddress)
  1110  	assert.Equal(t, mockIface.Addresses[0].PrefixLen, updatedTerminal.Interfaces[0].Addresses[0].PrefixLen)
  1111  	assert.Equal(t, newIP, *updatedTerminal.Interfaces[0].Addresses[0].IP)
  1112  
  1113  	if err := mock.ExpectationsWereMet(); err != nil {
  1114  		t.Errorf("there were unfulfilled expectations: %s", err)
  1115  	}
  1116  }
  1117  
  1118  func mockDBGetActivationCode(mock sqlmock.Sqlmock, terminalID string, ac string) {
  1119  	rows := mock.NewRows([]string{"activation_code"})
  1120  
  1121  	rows.AddRow(ac)
  1122  
  1123  	mock.ExpectQuery(edgenode.GetActivationCode).
  1124  		WithArgs(terminalID).
  1125  		WillReturnRows(rows)
  1126  }
  1127  
  1128  func TestUpdateTerminalPrimaryInterfaceWithoutActivationCode(t *testing.T) {
  1129  	db, _, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  1130  	if err != nil {
  1131  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  1132  	}
  1133  	defer db.Close()
  1134  
  1135  	mockTerminal := terminals[0]
  1136  	mockAc := ""
  1137  	mockTerminal.ActivationCode = &mockAc
  1138  
  1139  	getKubeResource := func() GetKubeResourceFunc {
  1140  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  1141  			assert.Equal(t, projectID, _projectID)
  1142  			assert.Nil(t, cluster)
  1143  			res := versionResource
  1144  			return []string{res}, nil
  1145  		}
  1146  	}
  1147  	bqClientMock := createMockBQClient(t, getKubeResource())
  1148  	artifactsService := artifacts.NewArtifactsService(db, nil)
  1149  	labelSvc := NewLabelService(artifactsService, db)
  1150  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  1151  
  1152  	terminal := model.TerminalUpdateInput{
  1153  		PrimaryInterface: mockTerminal.PrimaryInterface,
  1154  	}
  1155  	terminalUpdate := model.TerminalIDInput{
  1156  		TerminalID:     terminalID,
  1157  		TerminalValues: &terminal,
  1158  	}
  1159  
  1160  	_, err = service.UpdateTerminalEntry(context.Background(), &terminalUpdate)
  1161  	assert.Error(t, err)
  1162  }
  1163  
  1164  func TestUpdateTerminalInvalidPrimaryInterface(t *testing.T) {
  1165  	db, _, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  1166  	if err != nil {
  1167  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  1168  	}
  1169  	defer db.Close()
  1170  
  1171  	mockAcReal, err := crypto.GenerateRandomActivationCode()
  1172  	assert.NoError(t, err)
  1173  	mockAc := mockAcReal.Plain()
  1174  
  1175  	mockTerminal := terminals[0]
  1176  
  1177  	invalidInterfaceUUID := "invalid"
  1178  	mockTerminal.ActivationCode, mockTerminal.PrimaryInterface = &mockAc, &invalidInterfaceUUID
  1179  
  1180  	getKubeResource := func() GetKubeResourceFunc {
  1181  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  1182  			assert.Equal(t, projectID, _projectID)
  1183  			assert.Nil(t, cluster)
  1184  			res := versionResource
  1185  			return []string{res}, nil
  1186  		}
  1187  	}
  1188  	bqClientMock := createMockBQClient(t, getKubeResource())
  1189  	artifactsService := artifacts.NewArtifactsService(db, nil)
  1190  	labelSvc := NewLabelService(artifactsService, db)
  1191  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  1192  
  1193  	terminal := model.TerminalUpdateInput{
  1194  		PrimaryInterface: mockTerminal.PrimaryInterface,
  1195  	}
  1196  	terminalUpdate := model.TerminalIDInput{
  1197  		TerminalID:     terminalID,
  1198  		TerminalValues: &terminal,
  1199  	}
  1200  
  1201  	_, err = service.UpdateTerminalEntry(context.Background(), &terminalUpdate)
  1202  	assert.Error(t, err)
  1203  }
  1204  
  1205  func TestUpdateTerminalInterface(t *testing.T) {
  1206  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  1207  	if err != nil {
  1208  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  1209  	}
  1210  	defer db.Close()
  1211  
  1212  	mockIface := terminals[0].Interfaces[0]
  1213  	mockIface.Dhcp4 = true
  1214  
  1215  	mockDBGetTerminalInterfaceQuery(mock, mockIface.TerminalInterfaceID, []*model.TerminalInterface{mockIface})
  1216  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, mockIface.TerminalInterfaceID, []*model.TerminalAddress{})
  1217  	newMacAddr, newGateway4 := "42-8A-D6-06-AF-17", "172.10.208.136"
  1218  	hardwareAddr, _ := net.ParseMAC(newMacAddr)
  1219  	newFormattedMac := hardwareAddr.String()
  1220  	result := sqlmock.NewResult(1, 1)
  1221  	mock.ExpectBegin()
  1222  	mockDBTerminalInterfaceUpdateQuery(mock, mockIface.TerminalInterfaceID, model.TerminalInterfaceUpdateInput{
  1223  		MacAddress: &newFormattedMac,
  1224  		Dhcp4:      &mockIface.Dhcp4,
  1225  		Dhcp6:      &mockIface.Dhcp6,
  1226  		Gateway4:   &newGateway4,
  1227  		Gateway6:   mockIface.Gateway6,
  1228  	}, result)
  1229  	mock.ExpectCommit()
  1230  	mockIface.MacAddress, mockIface.Gateway4 = newFormattedMac, &newGateway4
  1231  	mockDBGetTerminalInterfaceQuery(mock, mockIface.TerminalInterfaceID, []*model.TerminalInterface{mockIface})
  1232  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, mockIface.TerminalInterfaceID, []*model.TerminalAddress{})
  1233  
  1234  	getKubeResource := func() GetKubeResourceFunc {
  1235  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  1236  			assert.Equal(t, projectID, _projectID)
  1237  			assert.Nil(t, cluster)
  1238  			res := versionResource
  1239  			return []string{res}, nil
  1240  		}
  1241  	}
  1242  	bqClientMock := createMockBQClient(t, getKubeResource())
  1243  	artifactsService := artifacts.NewArtifactsService(db, nil)
  1244  	labelSvc := NewLabelService(artifactsService, db)
  1245  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  1246  
  1247  	ifaceUpdate := model.TerminalInterfaceIDInput{
  1248  		TerminalInterfaceID: mockIface.TerminalInterfaceID,
  1249  		TerminalInterfaceValues: &model.TerminalInterfaceUpdateInput{
  1250  			MacAddress: &newFormattedMac,
  1251  			Gateway4:   &newGateway4,
  1252  			Addresses:  []*model.TerminalAddressIDInput{},
  1253  		},
  1254  	}
  1255  
  1256  	updatedIface, err := service.UpdateTerminalInterfaceEntry(context.Background(), &ifaceUpdate)
  1257  	assert.NoError(t, err)
  1258  	assert.Equal(t, mockIface.Gateway4, updatedIface.Gateway4)
  1259  	assert.Equal(t, newFormattedMac, updatedIface.MacAddress)
  1260  }
  1261  
  1262  func TestUpdateTerminalAddress(t *testing.T) {
  1263  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  1264  	if err != nil {
  1265  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  1266  	}
  1267  	defer db.Close()
  1268  
  1269  	mockAddr := terminals[0].Interfaces[0].Addresses[0]
  1270  	result := sqlmock.NewResult(1, 1)
  1271  	newPrefixLen := 32
  1272  
  1273  	mockDBGetTerminalAddressQuery(mock, mockAddr.TerminalAddressID, []*model.TerminalAddress{mockAddr})
  1274  	mock.ExpectBegin()
  1275  	mockDBTerminalAddressUpdateQuery(mock, mockAddr.TerminalAddressID, model.TerminalAddressUpdateInput{
  1276  		IP:        mockAddr.IP,
  1277  		PrefixLen: &newPrefixLen,
  1278  		Family:    &mockAddr.Family,
  1279  	}, result)
  1280  	mock.ExpectCommit()
  1281  	mockDBGetTerminalAddressQuery(mock, mockAddr.TerminalAddressID, []*model.TerminalAddress{mockAddr})
  1282  
  1283  	getKubeResource := func() GetKubeResourceFunc {
  1284  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  1285  			assert.Equal(t, projectID, _projectID)
  1286  			assert.Nil(t, cluster)
  1287  			res := versionResource
  1288  			return []string{res}, nil
  1289  		}
  1290  	}
  1291  	bqClientMock := createMockBQClient(t, getKubeResource())
  1292  	artifactsService := artifacts.NewArtifactsService(db, nil)
  1293  	labelSvc := NewLabelService(artifactsService, db)
  1294  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  1295  
  1296  	addrUpdate := model.TerminalAddressIDInput{
  1297  		TerminalAddressID: mockAddr.TerminalAddressID,
  1298  		TerminalAddressValues: &model.TerminalAddressUpdateInput{
  1299  			PrefixLen: &newPrefixLen,
  1300  		},
  1301  	}
  1302  
  1303  	updatedAddr, err := service.UpdateTerminalAddressEntry(context.Background(), &addrUpdate)
  1304  	assert.NoError(t, err)
  1305  	assert.Equal(t, mockAddr.PrefixLen, updatedAddr.PrefixLen)
  1306  }
  1307  
  1308  func TestUpdateTerminalWithEmptyIface(t *testing.T) {
  1309  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  1310  	if err != nil {
  1311  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  1312  	}
  1313  	defer db.Close()
  1314  
  1315  	mockTerminal := terminals[0]
  1316  	mockIface := mockTerminal.Interfaces[0]
  1317  	mockIfaces := []*model.TerminalInterface{mockIface}
  1318  	mockAddr := mockIface.Addresses[0]
  1319  	mockAddrs := []*model.TerminalAddress{mockAddr}
  1320  
  1321  	mock.ExpectBegin()
  1322  	mockDBGetTerminalByID(mock, mockTerminal.TerminalID, &mockTerminal)
  1323  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, mockTerminal.TerminalID, mockIfaces)
  1324  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, mockIface.TerminalInterfaceID, mockAddrs)
  1325  	mockDBGetTerminalDiskByTerminalID(mock, terminalID, nil)
  1326  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  1327  		WithArgs(mockTerminal.TerminalID, sql.NullString{}).
  1328  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  1329  			AddRow(mockTerminal.TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  1330  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  1331  		WithArgs(terminalClusterEdgeID).
  1332  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  1333  			AddRow("test-org"))
  1334  	mockDBGetAllLanesForACluster(mock, terminalClusterEdgeID, []terminalLaneAndHostname{
  1335  		{lane: &lane1, hostname: terminalHostname2},
  1336  	})
  1337  
  1338  	newLane := "lane11"
  1339  	mockTerminal.Lane = &newLane
  1340  	mockDBTerminalUpdate(mock, terminalID, model.TerminalUpdateInput{
  1341  		Lane: &newLane, Role: &mockTerminal.Role, Class: mockTerminal.Class, DiscoverDisks: mockTerminal.DiscoverDisks, BootDisk: mockTerminal.BootDisk, PrimaryInterface: mockTerminal.PrimaryInterface, ExistingEfiPart: mockTerminal.ExistingEfiPart, SwapEnabled: &mockTerminal.SwapEnabled,
  1342  	}, sqlmock.NewResult(1, 1))
  1343  	mock.ExpectCommit()
  1344  
  1345  	mockDBGetTerminalByID(mock, mockTerminal.TerminalID, &mockTerminal)
  1346  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, mockIface.TerminalID, mockIfaces)
  1347  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, mockIface.TerminalInterfaceID, mockAddrs)
  1348  	mockDBGetTerminalDiskByTerminalID(mock, terminalID, nil)
  1349  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  1350  		WithArgs(mockTerminal.TerminalID, sql.NullString{}).
  1351  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  1352  			AddRow(mockTerminal.TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  1353  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  1354  		WithArgs(terminalClusterEdgeID).
  1355  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  1356  			AddRow("test-org"))
  1357  
  1358  	getKubeResource := func() GetKubeResourceFunc {
  1359  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  1360  			assert.Equal(t, projectID, _projectID)
  1361  			assert.Nil(t, cluster)
  1362  			res := versionResource
  1363  			return []string{res}, nil
  1364  		}
  1365  	}
  1366  	bqClientMock := createMockBQClient(t, getKubeResource())
  1367  	artifactsService := artifacts.NewArtifactsService(db, nil)
  1368  	labelSvc := NewLabelService(artifactsService, db)
  1369  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  1370  	terminalInput := model.TerminalUpdateInput{
  1371  		Lane:       &newLane,
  1372  		Interfaces: []*model.TerminalInterfaceIDInput{},
  1373  	}
  1374  	terminalUpdate := model.TerminalIDInput{
  1375  		TerminalID:     terminalID,
  1376  		TerminalValues: &terminalInput,
  1377  	}
  1378  
  1379  	updatedTerminal, err := service.UpdateTerminalEntry(context.Background(), &terminalUpdate)
  1380  	if err != nil {
  1381  		t.Errorf("error was not expected while updating terminal: %s", err)
  1382  	}
  1383  
  1384  	assert.Equal(t, newLane, *updatedTerminal.Lane)
  1385  	assert.NotEmpty(t, updatedTerminal.Interfaces)
  1386  
  1387  	if err := mock.ExpectationsWereMet(); err != nil {
  1388  		t.Errorf("there were unfulfilled expectations: %s", err)
  1389  	}
  1390  }
  1391  
  1392  func TestUpdateTerminalInvalidGateway(t *testing.T) {
  1393  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  1394  	if err != nil {
  1395  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  1396  	}
  1397  	defer db.Close()
  1398  
  1399  	mockTerminal := terminals[0]
  1400  	mockIface := mockTerminal.Interfaces[0]
  1401  	mockIface.Dhcp4 = false
  1402  	mockIfaces := []*model.TerminalInterface{mockIface}
  1403  	mockAddr := mockIface.Addresses[0]
  1404  	mockAddrs := []*model.TerminalAddress{mockAddr}
  1405  
  1406  	mock.ExpectBegin()
  1407  	mockDBGetTerminalByID(mock, mockTerminal.TerminalID, &mockTerminal)
  1408  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, mockTerminal.TerminalID, mockIfaces)
  1409  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, mockIface.TerminalInterfaceID, mockAddrs)
  1410  	mockDBGetTerminalDiskByTerminalID(mock, terminalID, nil)
  1411  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  1412  		WithArgs(mockTerminal.TerminalID, sql.NullString{}).
  1413  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  1414  			AddRow(mockTerminal.TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  1415  
  1416  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  1417  		WithArgs(terminalClusterEdgeID).
  1418  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  1419  			AddRow("test-org"))
  1420  
  1421  	mockDBTerminalUpdate(mock, mockTerminal.TerminalID, model.TerminalUpdateInput{
  1422  		Lane: mockTerminal.Lane, Role: &mockTerminal.Role, Class: mockTerminal.Class, DiscoverDisks: mockTerminal.DiscoverDisks, BootDisk: mockTerminal.BootDisk, PrimaryInterface: mockTerminal.PrimaryInterface, ExistingEfiPart: mockTerminal.ExistingEfiPart, SwapEnabled: &mockTerminal.SwapEnabled,
  1423  	}, sqlmock.NewResult(1, 1))
  1424  	mock.ExpectRollback()
  1425  
  1426  	getKubeResource := func() GetKubeResourceFunc {
  1427  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  1428  			assert.Equal(t, projectID, _projectID)
  1429  			assert.Nil(t, cluster)
  1430  			res := versionResource
  1431  			return []string{res}, nil
  1432  		}
  1433  	}
  1434  	bqClientMock := createMockBQClient(t, getKubeResource())
  1435  	artifactsService := artifacts.NewArtifactsService(db, nil)
  1436  	labelSvc := NewLabelService(artifactsService, db)
  1437  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  1438  	newGateway4 := "1111"
  1439  	terminalUpdate := model.TerminalIDInput{
  1440  		TerminalID: terminalID,
  1441  		TerminalValues: &model.TerminalUpdateInput{
  1442  			Interfaces: []*model.TerminalInterfaceIDInput{
  1443  				{
  1444  					TerminalInterfaceID: terminalInterfaceID,
  1445  					TerminalInterfaceValues: &model.TerminalInterfaceUpdateInput{
  1446  						Gateway4: &newGateway4,
  1447  					},
  1448  				},
  1449  			},
  1450  		},
  1451  	}
  1452  
  1453  	_, err = service.UpdateTerminalEntry(context.Background(), &terminalUpdate)
  1454  	assert.Error(t, err)
  1455  	expectedErrorMsg := fmt.Sprintf("invalid gateway4 address: %s", newGateway4)
  1456  	assert.Equal(t, expectedErrorMsg, err.Error())
  1457  }
  1458  
  1459  func TestUpdateTerminalInvalidCIDR(t *testing.T) {
  1460  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  1461  	if err != nil {
  1462  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  1463  	}
  1464  	defer db.Close()
  1465  
  1466  	terminal := terminals[0]
  1467  	iface := terminal.Interfaces[0]
  1468  	ifaces := []*model.TerminalInterface{iface}
  1469  	addr := iface.Addresses[0]
  1470  	addrs := []*model.TerminalAddress{addr}
  1471  	result := sqlmock.NewResult(1, 1)
  1472  
  1473  	mock.ExpectBegin()
  1474  	mockDBGetTerminalByID(mock, terminal.TerminalID, &terminal)
  1475  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, terminal.TerminalID, ifaces)
  1476  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, iface.TerminalInterfaceID, addrs)
  1477  	mockDBGetTerminalDiskByTerminalID(mock, terminalID, nil)
  1478  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  1479  		WithArgs(terminal.TerminalID, sql.NullString{}).
  1480  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  1481  			AddRow(terminal.TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  1482  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  1483  		WithArgs(terminalClusterEdgeID).
  1484  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  1485  			AddRow("test-org"))
  1486  	mockDBTerminalUpdate(mock, terminal.TerminalID, model.TerminalUpdateInput{
  1487  		Lane: terminal.Lane, Role: &terminal.Role, Class: terminal.Class, DiscoverDisks: terminal.DiscoverDisks, BootDisk: terminal.BootDisk, PrimaryInterface: terminal.PrimaryInterface, ExistingEfiPart: terminal.ExistingEfiPart, SwapEnabled: &terminal.SwapEnabled,
  1488  	}, sqlmock.NewResult(1, 1))
  1489  	mockDBTerminalInterfaceUpdateQuery(mock, terminalInterfaceID, model.TerminalInterfaceUpdateInput{
  1490  		MacAddress: &iface.MacAddress, Dhcp4: &iface.Dhcp4, Dhcp6: &iface.Dhcp6, Gateway4: iface.Gateway4, Gateway6: iface.Gateway6,
  1491  	}, result)
  1492  	mock.ExpectRollback()
  1493  
  1494  	getKubeResource := func() GetKubeResourceFunc {
  1495  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  1496  			assert.Equal(t, projectID, _projectID)
  1497  			assert.Nil(t, cluster)
  1498  			res := versionResource
  1499  			return []string{res}, nil
  1500  		}
  1501  	}
  1502  	bqClientMock := createMockBQClient(t, getKubeResource())
  1503  	artifactsService := artifacts.NewArtifactsService(db, nil)
  1504  	labelSvc := NewLabelService(artifactsService, db)
  1505  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  1506  	newPrefixLen := -13
  1507  	terminalUpdate := model.TerminalIDInput{
  1508  		TerminalID: terminalID,
  1509  		TerminalValues: &model.TerminalUpdateInput{
  1510  			Interfaces: []*model.TerminalInterfaceIDInput{
  1511  				{
  1512  					TerminalInterfaceID: terminalInterfaceID,
  1513  					TerminalInterfaceValues: &model.TerminalInterfaceUpdateInput{
  1514  						Addresses: []*model.TerminalAddressIDInput{
  1515  							{
  1516  								TerminalAddressID: terminalAddressID,
  1517  								TerminalAddressValues: &model.TerminalAddressUpdateInput{
  1518  									PrefixLen: &newPrefixLen,
  1519  								},
  1520  							},
  1521  						},
  1522  					},
  1523  				},
  1524  			},
  1525  		},
  1526  	}
  1527  
  1528  	_, err = service.UpdateTerminalEntry(context.Background(), &terminalUpdate)
  1529  	assert.Error(t, err)
  1530  	expectedErrorMsg := fmt.Sprintf("invalid prefix: %d", newPrefixLen)
  1531  	assert.Equal(t, err.Error(), expectedErrorMsg)
  1532  }
  1533  
  1534  func TestUpdateTerminalDHCP(t *testing.T) {
  1535  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  1536  	if err != nil {
  1537  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  1538  	}
  1539  	defer db.Close()
  1540  
  1541  	terminal := terminals[0]
  1542  	iface := terminal.Interfaces[0]
  1543  	ifaces := []*model.TerminalInterface{iface}
  1544  	addr := iface.Addresses[0]
  1545  	addrs := []*model.TerminalAddress{addr}
  1546  	result := sqlmock.NewResult(1, 1)
  1547  
  1548  	mock.ExpectBegin()
  1549  	mockDBGetTerminalByID(mock, terminal.TerminalID, &terminal)
  1550  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, terminal.TerminalID, ifaces)
  1551  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, iface.TerminalInterfaceID, addrs)
  1552  	mockDBGetTerminalDiskByTerminalID(mock, terminalID, nil)
  1553  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  1554  		WithArgs(terminal.TerminalID, sql.NullString{}).
  1555  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  1556  			AddRow(terminal.TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  1557  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  1558  		WithArgs(terminalClusterEdgeID).
  1559  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  1560  			AddRow("test-org"))
  1561  
  1562  	mockDBTerminalUpdate(mock, terminal.TerminalID, model.TerminalUpdateInput{
  1563  		Lane: terminal.Lane, Role: &terminal.Role, Class: terminal.Class, DiscoverDisks: terminal.DiscoverDisks, BootDisk: terminal.BootDisk, PrimaryInterface: terminal.PrimaryInterface, ExistingEfiPart: terminal.ExistingEfiPart, SwapEnabled: &terminal.SwapEnabled,
  1564  	}, sqlmock.NewResult(1, 1))
  1565  	iface.Dhcp4 = true
  1566  	mockDBTerminalInterfaceUpdateQuery(mock, iface.TerminalInterfaceID, model.TerminalInterfaceUpdateInput{
  1567  		MacAddress: &iface.MacAddress, Dhcp4: &iface.Dhcp4, Dhcp6: &iface.Dhcp6, Gateway4: iface.Gateway4, Gateway6: iface.Gateway6,
  1568  	}, result)
  1569  	mock.ExpectCommit()
  1570  
  1571  	mockDBGetTerminalByID(mock, terminal.TerminalID, &terminal)
  1572  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, terminal.TerminalID, ifaces)
  1573  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, iface.TerminalInterfaceID, addrs)
  1574  	mockDBGetTerminalDiskByTerminalID(mock, terminalID, nil)
  1575  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  1576  		WithArgs(terminal.TerminalID, sql.NullString{}).
  1577  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  1578  			AddRow(terminal.TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  1579  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  1580  		WithArgs(terminalClusterEdgeID).
  1581  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  1582  			AddRow("test-org"))
  1583  
  1584  	getKubeResource := func() GetKubeResourceFunc {
  1585  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  1586  			assert.Equal(t, projectID, _projectID)
  1587  			assert.Nil(t, cluster)
  1588  			res := versionResource
  1589  			return []string{res}, nil
  1590  		}
  1591  	}
  1592  	bqClientMock := createMockBQClient(t, getKubeResource())
  1593  	artifactsService := artifacts.NewArtifactsService(db, nil)
  1594  	labelSvc := NewLabelService(artifactsService, db)
  1595  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  1596  	terminalInterface := []*model.TerminalInterfaceIDInput{
  1597  		{
  1598  			TerminalInterfaceID: terminalInterfaceID,
  1599  			TerminalInterfaceValues: &model.TerminalInterfaceUpdateInput{
  1600  				Dhcp4:     &dhcp4True,
  1601  				Addresses: []*model.TerminalAddressIDInput{},
  1602  			},
  1603  		},
  1604  	}
  1605  	terminalInput := model.TerminalUpdateInput{
  1606  		Interfaces: terminalInterface,
  1607  	}
  1608  	terminalUpdate := model.TerminalIDInput{
  1609  		TerminalID:     terminalID,
  1610  		TerminalValues: &terminalInput,
  1611  	}
  1612  
  1613  	_, err = service.UpdateTerminalEntry(context.Background(), &terminalUpdate)
  1614  	assert.NoError(t, err)
  1615  }
  1616  
  1617  func TestUpdateTerminalIfaceWithUppercaseMac(t *testing.T) {
  1618  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  1619  	if err != nil {
  1620  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  1621  	}
  1622  	defer db.Close()
  1623  
  1624  	newMacAddress := "A1:B2:C3:D4:E5:F6"
  1625  	lowercaseMac := strings.ToLower(newMacAddress)
  1626  
  1627  	terminal := terminals[0]
  1628  	iface := terminal.Interfaces[0]
  1629  	ifaces := []*model.TerminalInterface{iface}
  1630  	addr := iface.Addresses[0]
  1631  	addrs := []*model.TerminalAddress{addr}
  1632  	result := sqlmock.NewResult(1, 1)
  1633  
  1634  	mock.ExpectBegin()
  1635  	mockDBGetTerminalByID(mock, terminal.TerminalID, &terminal)
  1636  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, terminal.TerminalID, ifaces)
  1637  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, iface.TerminalInterfaceID, addrs)
  1638  	mockDBGetTerminalDiskByTerminalID(mock, terminalID, nil)
  1639  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  1640  		WithArgs(terminal.TerminalID, sql.NullString{}).
  1641  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  1642  			AddRow(terminal.TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  1643  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  1644  		WithArgs(terminalClusterEdgeID).
  1645  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  1646  			AddRow("test-org"))
  1647  
  1648  	mockDBTerminalUpdate(mock, terminal.TerminalID, model.TerminalUpdateInput{
  1649  		Lane: terminal.Lane, Role: &terminal.Role, Class: terminal.Class, DiscoverDisks: terminal.DiscoverDisks, BootDisk: terminal.BootDisk, PrimaryInterface: terminal.PrimaryInterface, ExistingEfiPart: terminal.ExistingEfiPart, SwapEnabled: &terminal.SwapEnabled,
  1650  	}, sqlmock.NewResult(1, 1))
  1651  	iface.MacAddress = lowercaseMac
  1652  	mockDBTerminalInterfaceUpdateQuery(mock, iface.TerminalInterfaceID, model.TerminalInterfaceUpdateInput{
  1653  		MacAddress: &iface.MacAddress, Dhcp4: &iface.Dhcp4, Dhcp6: &iface.Dhcp6, Gateway4: iface.Gateway4, Gateway6: iface.Gateway6,
  1654  	}, result)
  1655  	mock.ExpectCommit()
  1656  
  1657  	mockDBGetTerminalByID(mock, terminal.TerminalID, &terminal)
  1658  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, terminal.TerminalID, ifaces)
  1659  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, iface.TerminalInterfaceID, addrs)
  1660  	mockDBGetTerminalDiskByTerminalID(mock, terminalID, nil)
  1661  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  1662  		WithArgs(terminal.TerminalID, sql.NullString{}).
  1663  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  1664  			AddRow(terminal.TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  1665  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  1666  		WithArgs(terminalClusterEdgeID).
  1667  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  1668  			AddRow("test-org"))
  1669  
  1670  	getKubeResource := func() GetKubeResourceFunc {
  1671  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  1672  			assert.Equal(t, projectID, _projectID)
  1673  			assert.Nil(t, cluster)
  1674  			res := versionResource
  1675  			return []string{res}, nil
  1676  		}
  1677  	}
  1678  	bqClientMock := createMockBQClient(t, getKubeResource())
  1679  	artifactsService := artifacts.NewArtifactsService(db, nil)
  1680  	labelSvc := NewLabelService(artifactsService, db)
  1681  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  1682  	terminalUpdate := model.TerminalIDInput{
  1683  		TerminalID: terminalID,
  1684  		TerminalValues: &model.TerminalUpdateInput{
  1685  			Interfaces: []*model.TerminalInterfaceIDInput{
  1686  				{
  1687  					TerminalInterfaceID: terminalInterfaceID,
  1688  					TerminalInterfaceValues: &model.TerminalInterfaceUpdateInput{
  1689  						MacAddress: &newMacAddress,
  1690  					},
  1691  				},
  1692  			},
  1693  		},
  1694  	}
  1695  
  1696  	_, err = service.UpdateTerminalEntry(context.Background(), &terminalUpdate)
  1697  	assert.NoError(t, err)
  1698  }
  1699  
  1700  func TestCreateTerminalInterface(t *testing.T) {
  1701  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  1702  	if err != nil {
  1703  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  1704  	}
  1705  	defer db.Close()
  1706  
  1707  	mockIface := terminals[0].Interfaces[1]
  1708  	mockIface.Dhcp4, mockIface.Dhcp6, mockIface.Gateway4, mockIface.Gateway6 = false, false, &gateway4, &gateway6
  1709  	mockAddrs := mockIface.Addresses
  1710  	mockAddrs[0].IP, mockAddrs[1].IP = &ipv4, &ip2v4
  1711  
  1712  	mock.ExpectBegin()
  1713  	mockDBTerminalInterfaceCreateQuery(mock, *mockIface, sqlmock.NewResult(1, 1))
  1714  	mockDBTerminalAddressCreateQuery(mock, *mockAddrs[0], sqlmock.NewResult(1, 1))
  1715  	mockDBTerminalAddressCreateQuery(mock, *mockAddrs[1], sqlmock.NewResult(1, 1))
  1716  	mock.ExpectCommit()
  1717  
  1718  	newAddresses := []*model.TerminalAddressCreateInput{getAddrCreateInput(*mockAddrs[0]), getAddrCreateInput(*mockAddrs[1])}
  1719  	newIface := getIfaceCreateInput(*mockIface)
  1720  	newIface.Addresses = newAddresses
  1721  
  1722  	artifactsService := artifacts.NewArtifactsService(db, nil)
  1723  	labelSvc := NewLabelService(artifactsService, db)
  1724  	service := NewTerminalService(db, labelSvc)
  1725  	iface, err := service.CreateTerminalInterfaceEntry(context.Background(), mockIface.TerminalID, newIface)
  1726  	assert.NoError(t, err)
  1727  
  1728  	assert.Equal(t, mockIface.TerminalID, iface.TerminalID)
  1729  	assert.NotEmpty(t, iface.Addresses)
  1730  	assert.Equal(t, 2, len(iface.Addresses))
  1731  	assert.Equal(t, mockAddrs[0].IP, iface.Addresses[0].IP)
  1732  	assert.Equal(t, mockAddrs[1].IP, iface.Addresses[1].IP)
  1733  }
  1734  
  1735  func TestDeleteTerminalInterface(t *testing.T) {
  1736  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  1737  	if err != nil {
  1738  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  1739  	}
  1740  	defer db.Close()
  1741  
  1742  	result := sqlmock.NewResult(1, 1)
  1743  	mockTerminal := terminals[0]
  1744  	mockIface1, mockIface2 := mockTerminal.Interfaces[0], mockTerminal.Interfaces[1]
  1745  	mockIfaces := []*model.TerminalInterface{mockIface1, mockIface2}
  1746  	mockAddr1, mockAddr2 := mockIface1.Addresses[0], mockIface2.Addresses[0]
  1747  	mockAddrs1, mockAddrs2 := []*model.TerminalAddress{mockAddr1}, []*model.TerminalAddress{mockAddr2}
  1748  
  1749  	mockDBGetTerminalIDFromInterfaceQuery(mock, mockIface1.TerminalInterfaceID, []string{mockTerminal.TerminalID})
  1750  	mockDBGetTerminalByID(mock, mockTerminal.TerminalID, &mockTerminal)
  1751  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, mockTerminal.TerminalID, mockIfaces)
  1752  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, mockAddr1.TerminalInterfaceID, mockAddrs1)
  1753  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, mockAddr2.TerminalInterfaceID, mockAddrs2)
  1754  	mockDBGetTerminalDiskByTerminalID(mock, mockTerminal.TerminalID, nil)
  1755  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  1756  		WithArgs(mockTerminal.TerminalID, sql.NullString{}).
  1757  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  1758  			AddRow(mockTerminal.TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  1759  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  1760  		WithArgs(terminals[0].ClusterEdgeID).
  1761  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  1762  			AddRow("test-org"))
  1763  	mockDBTerminalInterfaceDeleteQuery(mock, mockIface1.TerminalInterfaceID, result)
  1764  
  1765  	getKubeResource := func() GetKubeResourceFunc {
  1766  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  1767  			assert.Equal(t, projectID, _projectID)
  1768  			assert.Nil(t, cluster)
  1769  			res := versionResource
  1770  			return []string{res}, nil
  1771  		}
  1772  	}
  1773  	bqClientMock := createMockBQClient(t, getKubeResource())
  1774  	artifactsService := artifacts.NewArtifactsService(db, nil)
  1775  	labelSvc := NewLabelService(artifactsService, db)
  1776  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  1777  	newTerminal, err := service.DeleteTerminalInterfaceEntry(context.Background(), terminalInterfaceID)
  1778  	assert.NoError(t, err)
  1779  	assert.Equal(t, terminalID, newTerminal.TerminalID)
  1780  	assert.NotEmpty(t, newTerminal.Interfaces)
  1781  	assert.Equal(t, 1, len(newTerminal.Interfaces))
  1782  }
  1783  
  1784  func TestCreateTerminalAddress(t *testing.T) {
  1785  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  1786  	if err != nil {
  1787  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  1788  	}
  1789  	defer db.Close()
  1790  
  1791  	mockAddr := *terminals[0].Interfaces[0].Addresses[0]
  1792  	mockDBTerminalAddressCreateQuery(mock, mockAddr, sqlmock.NewResult(1, 1))
  1793  
  1794  	artifactsService := artifacts.NewArtifactsService(db, nil)
  1795  	labelSvc := NewLabelService(artifactsService, db)
  1796  	service := NewTerminalService(db, labelSvc)
  1797  
  1798  	newAddress := getAddrCreateInput(mockAddr)
  1799  	address, err := service.CreateTerminalAddressEntry(context.Background(), terminalInterfaceID, newAddress)
  1800  	assert.NoError(t, err)
  1801  	assert.Equal(t, mockAddr.IP, address.IP)
  1802  	assert.Equal(t, mockAddr.PrefixLen, address.PrefixLen)
  1803  	assert.Equal(t, mockAddr.Family, address.Family)
  1804  }
  1805  
  1806  func TestDeleteTerminalAddress(t *testing.T) {
  1807  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  1808  	if err != nil {
  1809  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  1810  	}
  1811  	defer db.Close()
  1812  
  1813  	mockTerminal := terminals[0]
  1814  	iface := mockTerminal.Interfaces[1]
  1815  	mockIfaces := []*model.TerminalInterface{iface}
  1816  	mockAddrs := iface.Addresses
  1817  
  1818  	mockDBGetInterfaceIDFromAddressQuery(mock, mockAddrs[1].TerminalAddressID, []string{iface.TerminalInterfaceID})
  1819  	mockDBGetTerminalIDFromInterfaceQuery(mock, iface.TerminalInterfaceID, []string{mockTerminal.TerminalID})
  1820  	mockDBGetTerminalByID(mock, mockTerminal.TerminalID, &terminals[0])
  1821  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, terminals[0].TerminalID, mockIfaces)
  1822  
  1823  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, iface.TerminalInterfaceID, mockAddrs)
  1824  	mockDBGetTerminalDiskByTerminalID(mock, mockTerminal.TerminalID, nil)
  1825  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  1826  		WithArgs(mockTerminal.TerminalID, sql.NullString{}).
  1827  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  1828  			AddRow(mockTerminal.TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  1829  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  1830  		WithArgs(mockTerminal.ClusterEdgeID).
  1831  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  1832  			AddRow("test-org"))
  1833  	mockDBTerminalAddressDeleteQuery(mock, mockAddrs[1].TerminalAddressID, sqlmock.NewResult(1, 1))
  1834  
  1835  	getKubeResource := func() GetKubeResourceFunc {
  1836  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  1837  			assert.Equal(t, projectID, _projectID)
  1838  			assert.Nil(t, cluster)
  1839  			res := versionResource
  1840  			return []string{res}, nil
  1841  		}
  1842  	}
  1843  	bqClientMock := createMockBQClient(t, getKubeResource())
  1844  	artifactsService := artifacts.NewArtifactsService(db, nil)
  1845  	labelSvc := NewLabelService(artifactsService, db)
  1846  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  1847  	newTerminal, err := service.DeleteTerminalAddressEntry(context.Background(), mockAddrs[1].TerminalAddressID)
  1848  	assert.NoError(t, err)
  1849  	assert.Equal(t, mockTerminal.TerminalID, newTerminal.TerminalID)
  1850  	assert.NotEmpty(t, newTerminal.Interfaces)
  1851  	assert.Equal(t, iface.TerminalInterfaceID, newTerminal.Interfaces[0].TerminalInterfaceID)
  1852  	assert.Equal(t, 1, len(newTerminal.Interfaces[0].Addresses))
  1853  }
  1854  
  1855  func TestDeleteTerminalAddressError(t *testing.T) {
  1856  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  1857  	if err != nil {
  1858  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  1859  	}
  1860  	defer db.Close()
  1861  
  1862  	mockTerminal := terminals[0]
  1863  	iface := mockTerminal.Interfaces[0]
  1864  	iface.Dhcp4 = false
  1865  	mockIfaces := []*model.TerminalInterface{iface}
  1866  	mockAddrs := iface.Addresses
  1867  
  1868  	mockDBGetInterfaceIDFromAddressQuery(mock, mockAddrs[0].TerminalAddressID, []string{iface.TerminalInterfaceID})
  1869  	mockDBGetTerminalIDFromInterfaceQuery(mock, iface.TerminalInterfaceID, []string{mockTerminal.TerminalID})
  1870  	mockDBGetTerminalByID(mock, mockTerminal.TerminalID, &mockTerminal)
  1871  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, mockTerminal.TerminalID, mockIfaces)
  1872  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, iface.TerminalInterfaceID, mockAddrs)
  1873  	mockDBGetTerminalDiskByTerminalID(mock, terminalID, nil)
  1874  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  1875  		WithArgs(mockTerminal.TerminalID, sql.NullString{}).
  1876  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  1877  			AddRow(mockTerminal.TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  1878  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  1879  		WithArgs(terminals[0].ClusterEdgeID).
  1880  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  1881  			AddRow("test-org"))
  1882  	mock.ExpectRollback()
  1883  
  1884  	getKubeResource := func() GetKubeResourceFunc {
  1885  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  1886  			assert.Equal(t, projectID, _projectID)
  1887  			assert.Nil(t, cluster)
  1888  			res := versionResource
  1889  			return []string{res}, nil
  1890  		}
  1891  	}
  1892  	bqClientMock := createMockBQClient(t, getKubeResource())
  1893  	artifactsService := artifacts.NewArtifactsService(db, nil)
  1894  	labelSvc := NewLabelService(artifactsService, db)
  1895  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  1896  	_, err = service.DeleteTerminalAddressEntry(context.Background(), terminalAddressID)
  1897  	assert.Error(t, err)
  1898  	assert.Equal(t, "terminal address validation failed - missing ipv4 address", err.Error())
  1899  }
  1900  
  1901  func TestGetTerminalByID(t *testing.T) {
  1902  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  1903  	if err != nil {
  1904  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  1905  	}
  1906  	defer db.Close()
  1907  
  1908  	mockTerminal := terminals[0]
  1909  	iface := mockTerminal.Interfaces[0]
  1910  	mockIfaces := []*model.TerminalInterface{iface}
  1911  	mockAddrs := iface.Addresses
  1912  
  1913  	mockDBGetTerminalByID(mock, mockTerminal.TerminalID, &mockTerminal)
  1914  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, mockTerminal.TerminalID, mockIfaces)
  1915  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, iface.TerminalInterfaceID, mockAddrs)
  1916  	mockDBGetTerminalDiskByTerminalID(mock, terminalID, nil)
  1917  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  1918  		WithArgs(mockTerminal.TerminalID, sql.NullString{}).
  1919  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  1920  			AddRow(mockTerminal.TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  1921  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  1922  		WithArgs(terminalClusterEdgeID).
  1923  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  1924  			AddRow("test-org"))
  1925  
  1926  	getKubeResource := func() GetKubeResourceFunc {
  1927  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  1928  			assert.Equal(t, projectID, _projectID)
  1929  			assert.Nil(t, cluster)
  1930  			res := versionResource
  1931  			return []string{res}, nil
  1932  		}
  1933  	}
  1934  	bqClientMock := createMockBQClient(t, getKubeResource())
  1935  	artifactsService := artifacts.NewArtifactsService(db, nil)
  1936  	labelSvc := NewLabelService(artifactsService, db)
  1937  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  1938  	getLabel := true
  1939  	terminal, err := service.GetTerminal(context.Background(), terminalID, &getLabel)
  1940  
  1941  	assert.NoError(t, err)
  1942  	assert.Equal(t, mockTerminal.TerminalID, terminal.TerminalID)
  1943  	assert.Equal(t, mockTerminal.ClusterName, terminal.ClusterName)
  1944  	assert.Equal(t, mockTerminal.Hostname, terminal.Hostname)
  1945  	assert.Equal(t, mockTerminal.ClusterEdgeID, terminal.ClusterEdgeID)
  1946  	assert.Equal(t, mockTerminal.Lane, terminal.Lane)
  1947  	assert.Equal(t, mockTerminal.Role, terminal.Role)
  1948  	assert.Equal(t, mockTerminal.Class, terminal.Class)
  1949  	assert.Equal(t, mockTerminal.DiscoverDisks, terminal.DiscoverDisks)
  1950  	assert.Equal(t, mockTerminal.BootDisk, terminal.BootDisk)
  1951  	assert.Equal(t, mockTerminal.PrimaryInterface, terminal.PrimaryInterface)
  1952  	assert.Equal(t, mockTerminal.ExistingEfiPart, terminal.ExistingEfiPart)
  1953  	assert.Equal(t, mockTerminal.SwapEnabled, terminal.SwapEnabled)
  1954  	assert.NotEmpty(t, terminal.Interfaces)
  1955  
  1956  	terminalInterface := terminal.Interfaces[0]
  1957  	mockIface := mockTerminal.Interfaces[0]
  1958  	assert.Equal(t, mockIface.TerminalInterfaceID, terminalInterface.TerminalInterfaceID)
  1959  	assert.Equal(t, mockIface.MacAddress, terminalInterface.MacAddress)
  1960  	assert.Equal(t, mockIface.Dhcp4, terminalInterface.Dhcp4)
  1961  	assert.Equal(t, mockIface.Dhcp6, terminalInterface.Dhcp6)
  1962  	assert.Equal(t, mockIface.Gateway4, terminalInterface.Gateway4)
  1963  	assert.Equal(t, mockIface.Gateway6, terminalInterface.Gateway6)
  1964  	assert.NotEmpty(t, terminalInterface.Addresses)
  1965  
  1966  	terminalAddress := terminalInterface.Addresses[0]
  1967  	mockAddr := mockIface.Addresses[0]
  1968  	assert.Equal(t, mockAddr.TerminalAddressID, terminalAddress.TerminalAddressID)
  1969  	assert.Equal(t, *mockAddr.IP, *terminalAddress.IP)
  1970  	assert.Equal(t, mockAddr.PrefixLen, terminalAddress.PrefixLen)
  1971  	assert.Equal(t, mockAddr.Family, terminalAddress.Family)
  1972  }
  1973  
  1974  func TestGetTerminalByIDWithoutAddress(t *testing.T) {
  1975  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  1976  	if err != nil {
  1977  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  1978  	}
  1979  	defer db.Close()
  1980  
  1981  	mockTerminal := terminals[1]
  1982  	iface := mockTerminal.Interfaces[0]
  1983  	mockIfaces := []*model.TerminalInterface{iface}
  1984  	mockAddrs := []*model.TerminalAddress{}
  1985  
  1986  	mockDBGetTerminalByID(mock, mockTerminal.TerminalID, &mockTerminal)
  1987  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, mockTerminal.TerminalID, mockIfaces)
  1988  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, iface.TerminalInterfaceID, mockAddrs)
  1989  	mockDBGetTerminalDiskByTerminalID(mock, mockTerminal.TerminalID, nil)
  1990  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  1991  		WithArgs(mockTerminal.TerminalID, sql.NullString{}).
  1992  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  1993  			AddRow(mockTerminal.TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  1994  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  1995  		WithArgs(mockTerminal.ClusterEdgeID).
  1996  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  1997  			AddRow("test-org"))
  1998  
  1999  	getKubeResource := func() GetKubeResourceFunc {
  2000  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  2001  			assert.Equal(t, projectID, _projectID)
  2002  			assert.Nil(t, cluster)
  2003  			res := versionResource
  2004  			return []string{res}, nil
  2005  		}
  2006  	}
  2007  	bqClientMock := createMockBQClient(t, getKubeResource())
  2008  	artifactsService := artifacts.NewArtifactsService(db, nil)
  2009  	labelSvc := NewLabelService(artifactsService, db)
  2010  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  2011  	getLabel := true
  2012  	terminal, err := service.GetTerminal(context.Background(), terminalID2, &getLabel)
  2013  	assert.NoError(t, err)
  2014  
  2015  	assert.Equal(t, mockTerminal.TerminalID, terminal.TerminalID)
  2016  	assert.NotEmpty(t, terminal.Interfaces)
  2017  	assert.Equal(t, len(mockTerminal.Interfaces), len(terminal.Interfaces))
  2018  	assert.Equal(t, mockTerminal.Interfaces[0].TerminalInterfaceID, terminal.Interfaces[0].TerminalInterfaceID)
  2019  	assert.Empty(t, terminal.Interfaces[0].Addresses)
  2020  }
  2021  
  2022  func TestGetTerminalsWithClusterEdgeID(t *testing.T) {
  2023  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  2024  	if err != nil {
  2025  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  2026  	}
  2027  	defer db.Close()
  2028  
  2029  	// mock query with cluster edge id
  2030  	testClusterEdgeID := "cluster-0001a"
  2031  	mockTerminals := terminals[0:2]
  2032  	mockTerminals[0].ClusterEdgeID, mockTerminals[1].ClusterEdgeID = testClusterEdgeID, testClusterEdgeID
  2033  	iface := mockTerminals[0].Interfaces[0]
  2034  	mockIfaces1 := []*model.TerminalInterface{iface}
  2035  	mockAddrs := iface.Addresses
  2036  
  2037  	mockDBGetTerminalByClusterEdgeID(mock, testClusterEdgeID, mockTerminals)
  2038  	mockDBGetTerminalDiskByTerminalID(mock, terminalID, []model.TerminalDisk{
  2039  		{
  2040  			TerminalDiskID: terminalDiskID,
  2041  			TerminalID:     mockTerminals[0].TerminalID,
  2042  			IncludeDisk:    true,
  2043  			ExpectEmpty:    false,
  2044  			DevicePath:     devicePath,
  2045  			UsePart:        false,
  2046  		},
  2047  	})
  2048  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, mockTerminals[0].TerminalID, mockIfaces1)
  2049  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, iface.TerminalInterfaceID, mockAddrs)
  2050  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  2051  		WithArgs(mockTerminals[0].TerminalID, sql.NullString{}).
  2052  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  2053  			AddRow(mockTerminals[0].TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  2054  	mockDBGetTerminalDiskByTerminalID(mock, mockTerminals[1].TerminalID, []model.TerminalDisk{
  2055  		{
  2056  			TerminalDiskID: terminalDiskID2,
  2057  			TerminalID:     mockTerminals[1].TerminalID,
  2058  			IncludeDisk:    true,
  2059  			ExpectEmpty:    false,
  2060  			DevicePath:     devicePath2,
  2061  			UsePart:        false,
  2062  		},
  2063  	})
  2064  
  2065  	iface = mockTerminals[1].Interfaces[0]
  2066  	mockIfaces2 := []*model.TerminalInterface{iface}
  2067  	mockAddrs = iface.Addresses
  2068  
  2069  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, mockTerminals[1].TerminalID, mockIfaces2)
  2070  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, iface.TerminalInterfaceID, mockAddrs)
  2071  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  2072  		WithArgs(mockTerminals[1].TerminalID, sql.NullString{}).
  2073  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  2074  			AddRow(mockTerminals[1].TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  2075  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  2076  		WithArgs(testClusterEdgeID).
  2077  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  2078  			AddRow("test-org"))
  2079  
  2080  	getKubeResource := func() GetKubeResourceFunc {
  2081  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  2082  			assert.Equal(t, projectID, _projectID)
  2083  			assert.Nil(t, cluster)
  2084  			res := versionResource
  2085  			return []string{res}, nil
  2086  		}
  2087  	}
  2088  	bqClientMock := createMockBQClient(t, getKubeResource())
  2089  	artifactsService := artifacts.NewArtifactsService(db, nil)
  2090  	labelSvc := NewLabelService(artifactsService, db)
  2091  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  2092  	terminals, err := service.GetTerminals(context.Background(), &testClusterEdgeID, nil)
  2093  	assert.NoError(t, err)
  2094  	assert.Equal(t, len(mockTerminals), len(terminals))
  2095  	assert.Equal(t, mockTerminals[0].TerminalID, terminals[0].TerminalID)
  2096  	assert.Equal(t, mockTerminals[0].ClusterName, terminals[0].ClusterName)
  2097  	assert.Equal(t, mockTerminals[0].Hostname, terminals[0].Hostname)
  2098  	assert.Equal(t, devicePath, terminals[0].Disks[0].DevicePath)
  2099  	assert.Equal(t, testClusterEdgeID, terminals[0].ClusterEdgeID)
  2100  	assert.Equal(t, mockTerminals[0].Role, terminals[0].Role)
  2101  	assert.Equal(t, mockTerminals[0].Class, terminals[0].Class)
  2102  }
  2103  
  2104  func TestGetTerminalsWithHostname(t *testing.T) {
  2105  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  2106  	if err != nil {
  2107  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  2108  	}
  2109  	defer db.Close()
  2110  
  2111  	mockTerminal := terminals[0]
  2112  	iface := mockTerminal.Interfaces[0]
  2113  	mockIfaces := []*model.TerminalInterface{iface}
  2114  	mockAddrs := iface.Addresses
  2115  
  2116  	mockDBGetTerminalByHostname(mock, mockTerminal.Hostname, []model.Terminal{mockTerminal})
  2117  
  2118  	mockDBGetTerminalDiskByTerminalID(mock, terminalID, []model.TerminalDisk{
  2119  		{
  2120  			TerminalDiskID: terminalDiskID,
  2121  			TerminalID:     terminalID,
  2122  			IncludeDisk:    false,
  2123  			ExpectEmpty:    true,
  2124  			DevicePath:     devicePath,
  2125  			UsePart:        false,
  2126  		},
  2127  	})
  2128  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, mockTerminal.TerminalID, mockIfaces)
  2129  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, iface.TerminalInterfaceID, mockAddrs)
  2130  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  2131  		WithArgs(mockTerminal.TerminalID, sql.NullString{}).
  2132  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  2133  			AddRow(mockTerminal.TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  2134  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  2135  		WithArgs(mockTerminal.ClusterEdgeID).
  2136  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  2137  			AddRow("test-org"))
  2138  
  2139  	getKubeResource := func() GetKubeResourceFunc {
  2140  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  2141  			assert.Equal(t, projectID, _projectID)
  2142  			assert.Nil(t, cluster)
  2143  			res := versionResource
  2144  			return []string{res}, nil
  2145  		}
  2146  	}
  2147  	bqClientMock := createMockBQClient(t, getKubeResource())
  2148  	artifactsService := artifacts.NewArtifactsService(db, nil)
  2149  	labelSvc := NewLabelService(artifactsService, db)
  2150  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  2151  	terminals, err := service.GetTerminals(context.Background(), nil, &terminalHostname)
  2152  	assert.NoError(t, err)
  2153  	assert.Equal(t, 1, len(terminals))
  2154  	assert.Equal(t, mockTerminal.TerminalID, terminals[0].TerminalID)
  2155  	assert.Equal(t, mockTerminal.ClusterName, terminals[0].ClusterName)
  2156  	assert.Equal(t, mockTerminal.Hostname, terminals[0].Hostname)
  2157  	assert.Equal(t, mockTerminal.ClusterEdgeID, terminals[0].ClusterEdgeID)
  2158  	assert.Equal(t, mockTerminal.Role, terminals[0].Role)
  2159  	assert.True(t, terminals[0].Disks[0].ExpectEmpty)
  2160  	assert.Equal(t, devicePath, terminals[0].Disks[0].DevicePath)
  2161  }
  2162  
  2163  func TestGetTerminalsWithClusterEdgeIDAndHostname(t *testing.T) {
  2164  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  2165  	if err != nil {
  2166  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  2167  	}
  2168  	defer db.Close()
  2169  
  2170  	mockTerminal := terminals[0]
  2171  	iface := mockTerminal.Interfaces[0]
  2172  	mockIfaces := []*model.TerminalInterface{iface}
  2173  	mockAddrs := iface.Addresses
  2174  
  2175  	mockDBGetTerminalByClusterEdgeIDAndHostname(mock, mockTerminal.ClusterEdgeID, mockTerminal.Hostname, []model.Terminal{mockTerminal})
  2176  	mockDBGetTerminalDiskByTerminalID(mock, mockTerminal.TerminalID, []model.TerminalDisk{
  2177  		{
  2178  			TerminalDiskID: terminalDiskID,
  2179  			TerminalID:     terminalID,
  2180  			IncludeDisk:    false,
  2181  			ExpectEmpty:    false,
  2182  			DevicePath:     devicePath,
  2183  			UsePart:        false,
  2184  		},
  2185  	})
  2186  
  2187  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, mockTerminal.TerminalID, mockIfaces)
  2188  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, iface.TerminalInterfaceID, mockAddrs)
  2189  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  2190  		WithArgs(mockTerminal.TerminalID, sql.NullString{}).
  2191  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  2192  			AddRow(mockTerminal.TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  2193  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  2194  		WithArgs(mockTerminal.ClusterEdgeID).
  2195  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  2196  			AddRow("test-org"))
  2197  
  2198  	getKubeResource := func() GetKubeResourceFunc {
  2199  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  2200  			assert.Equal(t, projectID, _projectID)
  2201  			assert.Nil(t, cluster)
  2202  			res := versionResource
  2203  			return []string{res}, nil
  2204  		}
  2205  	}
  2206  	bqClientMock := createMockBQClient(t, getKubeResource())
  2207  	artifactsService := artifacts.NewArtifactsService(db, nil)
  2208  	labelSvc := NewLabelService(artifactsService, db)
  2209  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  2210  	terminals, err := service.GetTerminals(context.Background(), &mockTerminal.ClusterEdgeID, &mockTerminal.Hostname)
  2211  	assert.NoError(t, err)
  2212  	assert.Equal(t, 1, len(terminals))
  2213  
  2214  	terminal := terminals[0]
  2215  	assert.Equal(t, mockTerminal.TerminalID, terminal.TerminalID)
  2216  	assert.Equal(t, mockTerminal.ClusterName, terminal.ClusterName)
  2217  	assert.Equal(t, mockTerminal.Hostname, terminal.Hostname)
  2218  	assert.Equal(t, mockTerminal.ClusterEdgeID, terminal.ClusterEdgeID)
  2219  	assert.Equal(t, mockTerminal.Role, terminal.Role)
  2220  	assert.False(t, terminal.Disks[0].IncludeDisk)
  2221  	assert.False(t, terminal.Disks[0].UsePart)
  2222  	assert.Equal(t, devicePath, terminal.Disks[0].DevicePath)
  2223  	assert.NotEmpty(t, terminal.Interfaces)
  2224  	iface = terminal.Interfaces[0]
  2225  	assert.Equal(t, mockTerminal.Interfaces[0].TerminalInterfaceID, iface.TerminalInterfaceID)
  2226  	assert.NotEmpty(t, iface.Addresses)
  2227  	address := iface.Addresses[0]
  2228  	assert.Equal(t, terminalAddressID, address.TerminalAddressID)
  2229  }
  2230  
  2231  func TestGetTerminalsWithoutClusterEdgeIDAndHostname(t *testing.T) {
  2232  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  2233  	if err != nil {
  2234  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  2235  	}
  2236  	defer db.Close()
  2237  
  2238  	mockTerminals := terminals[:2]
  2239  
  2240  	mockDBGetAllTerminals(mock, mockTerminals)
  2241  	mockDBGetTerminalDiskByTerminalID(mock, mockTerminals[0].TerminalID, []model.TerminalDisk{
  2242  		{
  2243  			TerminalDiskID: terminalDiskID,
  2244  			TerminalID:     mockTerminals[0].TerminalID,
  2245  			IncludeDisk:    true,
  2246  			ExpectEmpty:    true,
  2247  			DevicePath:     devicePath,
  2248  			UsePart:        false,
  2249  		},
  2250  	})
  2251  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, mockTerminals[0].TerminalID, []*model.TerminalInterface{})
  2252  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  2253  		WithArgs(mockTerminals[0].TerminalID, sql.NullString{}).
  2254  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  2255  			AddRow(mockTerminals[0].TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  2256  	mockDBGetTerminalDiskByTerminalID(mock, mockTerminals[1].TerminalID, nil)
  2257  	iface := mockTerminals[1].Interfaces[0]
  2258  	mockIfaces := []*model.TerminalInterface{iface}
  2259  	mockAddrs := iface.Addresses
  2260  
  2261  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, mockTerminals[1].TerminalID, mockIfaces)
  2262  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, iface.TerminalInterfaceID, mockAddrs)
  2263  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  2264  		WithArgs(mockTerminals[1].TerminalID, sql.NullString{}).
  2265  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  2266  			AddRow(mockTerminals[1].TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  2267  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  2268  		WithArgs(mockTerminals[0].ClusterEdgeID).
  2269  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  2270  			AddRow("test-org"))
  2271  
  2272  	getKubeResource := func() GetKubeResourceFunc {
  2273  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  2274  			assert.Equal(t, projectID, _projectID)
  2275  			assert.Nil(t, cluster)
  2276  			res := versionResource
  2277  			return []string{res}, nil
  2278  		}
  2279  	}
  2280  	bqClientMock := createMockBQClient(t, getKubeResource())
  2281  	artifactsService := artifacts.NewArtifactsService(db, nil)
  2282  	labelSvc := NewLabelService(artifactsService, db)
  2283  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  2284  
  2285  	allTerminals, err := service.GetTerminals(context.Background(), nil, nil)
  2286  	assert.NoError(t, err)
  2287  
  2288  	terminal1, terminal2 := mockTerminals[0], mockTerminals[1]
  2289  	assert.Equal(t, 2, len(allTerminals))
  2290  	assert.Equal(t, terminal1.TerminalID, allTerminals[0].TerminalID)
  2291  	assert.Equal(t, terminal1.ClusterName, allTerminals[0].ClusterName)
  2292  	assert.Equal(t, terminal1.ClusterEdgeID, allTerminals[0].ClusterEdgeID)
  2293  	assert.Equal(t, terminal1.Role, allTerminals[0].Role)
  2294  	assert.Equal(t, terminal1.Class, allTerminals[0].Class)
  2295  	assert.Equal(t, terminal2.TerminalID, allTerminals[1].TerminalID)
  2296  	assert.Equal(t, terminal2.ClusterEdgeID, allTerminals[1].ClusterEdgeID)
  2297  	assert.Equal(t, terminal2.ClusterName, allTerminals[1].ClusterName)
  2298  	assert.Equal(t, terminal2.Role, allTerminals[1].Role)
  2299  	assert.Equal(t, terminal2.Class, allTerminals[1].Class)
  2300  }
  2301  
  2302  func TestGetTerminalFromInterface(t *testing.T) {
  2303  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  2304  	if err != nil {
  2305  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  2306  	}
  2307  	defer db.Close()
  2308  
  2309  	mockTerminal := terminals[0]
  2310  	iface := mockTerminal.Interfaces[0]
  2311  	mockIfaces := []*model.TerminalInterface{iface}
  2312  	mockAddrs := iface.Addresses
  2313  
  2314  	mockDBGetTerminalIDFromInterfaceQuery(mock, iface.TerminalInterfaceID, []string{mockTerminal.TerminalID})
  2315  	mockDBGetTerminalByID(mock, mockTerminal.TerminalID, &mockTerminal)
  2316  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, mockTerminal.TerminalID, mockIfaces)
  2317  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, iface.TerminalInterfaceID, mockAddrs)
  2318  	mockDBGetTerminalDiskByTerminalID(mock, terminalID, nil)
  2319  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  2320  		WithArgs(mockTerminal.TerminalID, sql.NullString{}).
  2321  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  2322  			AddRow(mockTerminal.TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  2323  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  2324  		WithArgs(mockTerminal.ClusterEdgeID).
  2325  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  2326  			AddRow("test-org"))
  2327  
  2328  	getKubeResource := func() GetKubeResourceFunc {
  2329  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  2330  			assert.Equal(t, projectID, _projectID)
  2331  			assert.Nil(t, cluster)
  2332  			res := versionResource
  2333  			return []string{res}, nil
  2334  		}
  2335  	}
  2336  	bqClientMock := createMockBQClient(t, getKubeResource())
  2337  	artifactsService := artifacts.NewArtifactsService(db, nil)
  2338  	labelSvc := NewLabelService(artifactsService, db)
  2339  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  2340  	terminal, err := service.GetTerminalFromInterface(context.Background(), terminalInterfaceID)
  2341  	assert.NoError(t, err)
  2342  	assert.NotEmpty(t, terminal)
  2343  	assert.Equal(t, mockTerminal.TerminalID, terminal.TerminalID)
  2344  	assert.NotEmpty(t, terminal.Interfaces)
  2345  	assert.Equal(t, mockTerminal.Interfaces[0].TerminalInterfaceID, terminal.Interfaces[0].TerminalInterfaceID)
  2346  	assert.NotEmpty(t, terminal.Interfaces[0].Addresses)
  2347  	assert.Equal(t, mockTerminal.Interfaces[0].Addresses[0].TerminalAddressID, terminal.Interfaces[0].Addresses[0].TerminalAddressID)
  2348  }
  2349  
  2350  func TestGetTerminalFromAddress(t *testing.T) {
  2351  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  2352  	if err != nil {
  2353  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  2354  	}
  2355  	defer db.Close()
  2356  
  2357  	mockTerminal := terminals[0]
  2358  	iface := mockTerminal.Interfaces[0]
  2359  	mockIfaces := []*model.TerminalInterface{iface}
  2360  	mockAddrs := iface.Addresses
  2361  
  2362  	mockDBGetInterfaceIDFromAddressQuery(mock, mockAddrs[0].TerminalAddressID, []string{iface.TerminalInterfaceID})
  2363  	mockDBGetTerminalIDFromInterfaceQuery(mock, iface.TerminalInterfaceID, []string{mockTerminal.TerminalID})
  2364  	mockDBGetTerminalByID(mock, mockTerminal.TerminalID, &mockTerminal)
  2365  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, mockTerminal.TerminalID, mockIfaces)
  2366  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, iface.TerminalInterfaceID, mockAddrs)
  2367  	mockDBGetTerminalDiskByTerminalID(mock, terminalID, nil)
  2368  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  2369  		WithArgs(mockTerminal.TerminalID, sql.NullString{}).
  2370  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  2371  			AddRow(mockTerminal.TerminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  2372  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  2373  		WithArgs(mockTerminal.ClusterEdgeID).
  2374  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  2375  			AddRow("test-org"))
  2376  
  2377  	getKubeResource := func() GetKubeResourceFunc {
  2378  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  2379  			assert.Equal(t, projectID, _projectID)
  2380  			assert.Nil(t, cluster)
  2381  			res := versionResource
  2382  			return []string{res}, nil
  2383  		}
  2384  	}
  2385  	bqClientMock := createMockBQClient(t, getKubeResource())
  2386  	artifactsService := artifacts.NewArtifactsService(db, nil)
  2387  	labelSvc := NewLabelService(artifactsService, db)
  2388  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  2389  	terminal, err := service.GetTerminalFromAddress(context.Background(), terminalAddressID)
  2390  	assert.NoError(t, err)
  2391  	assert.NotEmpty(t, terminal)
  2392  	assert.Equal(t, mockTerminal.TerminalID, terminal.TerminalID)
  2393  	assert.NotEmpty(t, terminal.Interfaces)
  2394  	assert.Equal(t, mockTerminal.Interfaces[0].TerminalInterfaceID, terminal.Interfaces[0].TerminalInterfaceID)
  2395  	assert.NotEmpty(t, terminal.Interfaces[0].Addresses)
  2396  	assert.Equal(t, mockTerminal.Interfaces[0].Addresses[0].TerminalAddressID, terminal.Interfaces[0].Addresses[0].TerminalAddressID)
  2397  }
  2398  
  2399  func TestGetBannerTerminals(t *testing.T) {
  2400  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  2401  	if err != nil {
  2402  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  2403  	}
  2404  	defer db.Close()
  2405  
  2406  	mockDBGetClustersByBannerEdgeIDQuery(mock, terminalBannerEdgeID, terminals)
  2407  
  2408  	mockDBGetTerminalDiskByTerminalID(mock, nil, []model.TerminalDisk{})
  2409  	mockDBGetTerminalDiskByTerminalID(mock, nil, []model.TerminalDisk{})
  2410  
  2411  	mock.ExpectQuery(sqlquery.GetProjectIDByBanner).
  2412  		WithArgs(terminalBannerEdgeID).
  2413  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  2414  			AddRow("test-org"))
  2415  	getKubeResource := func() GetKubeResourceFunc {
  2416  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  2417  			assert.Equal(t, projectID, _projectID)
  2418  			assert.Nil(t, cluster)
  2419  			//assert.Equal(t, mapper.GetHelmReleases(), input)
  2420  			res := versionResource
  2421  			return []string{res}, nil
  2422  		}
  2423  	}
  2424  	bqClientMock := createMockBQClient(t, getKubeResource())
  2425  	artifactsService := artifacts.NewArtifactsService(db, nil)
  2426  	labelSvc := NewLabelService(artifactsService, db)
  2427  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  2428  	bannerTerminals, err := service.GetBannerTerminals(context.Background(), terminalBannerEdgeID, projectID)
  2429  
  2430  	assert.NoError(t, err)
  2431  	assert.NotEmpty(t, bannerTerminals)
  2432  	assert.Equal(t, 2, len(bannerTerminals))
  2433  
  2434  	for _, terminal := range bannerTerminals {
  2435  		if terminal.TerminalID == terminalID {
  2436  			assert.Equal(t, 3, len(terminal.Interfaces))
  2437  			// assert.Equal(t, 1, len(terminal.Interfaces[0].Addresses))
  2438  		} else if terminal.TerminalID == terminalID2 {
  2439  			assert.Equal(t, 1, len(terminal.Interfaces))
  2440  			// assert.Zero(t, len(terminal.Interfaces[0].Addresses))
  2441  			// assert.Equal(t, 1, len(terminal.Interfaces[0].Addresses))
  2442  			// assert.Equal(t, 1, len(terminal.Interfaces[1].Addresses))
  2443  		} else {
  2444  			t.Errorf("Unexpected terminal ID %v", terminal.TerminalID)
  2445  		}
  2446  	}
  2447  }
  2448  
  2449  func TestGetEmptyBannerTerminals(t *testing.T) {
  2450  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  2451  	if err != nil {
  2452  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  2453  	}
  2454  	defer db.Close()
  2455  
  2456  	mockDBGetClustersByBannerEdgeIDQuery(mock, terminalBannerEdgeID, []model.Terminal{})
  2457  	mock.ExpectQuery(sqlquery.GetProjectIDByBanner).
  2458  		WithArgs(terminalBannerEdgeID).
  2459  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  2460  			AddRow("test-org"))
  2461  	getKubeResource := func() GetKubeResourceFunc {
  2462  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  2463  			assert.Equal(t, projectID, _projectID)
  2464  			assert.Nil(t, cluster)
  2465  			//assert.Equal(t, mapper.GetHelmReleases(), input)
  2466  			res := versionResource
  2467  			return []string{res}, nil
  2468  		}
  2469  	}
  2470  
  2471  	bqClientMock := createMockBQClient(t, getKubeResource())
  2472  	artifactsService := artifacts.NewArtifactsService(db, nil)
  2473  	labelSvc := NewLabelService(artifactsService, db)
  2474  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  2475  	bannerTerminals, err := service.GetBannerTerminals(context.Background(), terminalBannerEdgeID, projectID)
  2476  	assert.NoError(t, err)
  2477  	assert.Equal(t, []*model.Terminal{}, bannerTerminals)
  2478  }
  2479  
  2480  func TestGetTerminalBootstrapConfig(t *testing.T) {
  2481  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  2482  	if err != nil {
  2483  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  2484  	}
  2485  	defer db.Close()
  2486  
  2487  	mockTerminal := terminals[0]
  2488  	iface := mockTerminal.Interfaces[0]
  2489  	mockIfaces := []*model.TerminalInterface{iface}
  2490  	mockAddrs := iface.Addresses
  2491  
  2492  	mockDBGetTerminalByID(mock, mockTerminal.TerminalID, &mockTerminal)
  2493  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, mockTerminal.TerminalID, mockIfaces)
  2494  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, iface.TerminalInterfaceID, mockAddrs)
  2495  	mockDBGetTerminalDiskByTerminalID(mock, terminalID, []model.TerminalDisk{
  2496  		{
  2497  			TerminalDiskID: terminalDiskID,
  2498  			TerminalID:     terminalID,
  2499  			ExpectEmpty:    false,
  2500  			IncludeDisk:    true,
  2501  			DevicePath:     devicePath,
  2502  			UsePart:        false,
  2503  		},
  2504  		{
  2505  			TerminalDiskID: terminalDiskID2,
  2506  			TerminalID:     terminalID,
  2507  			ExpectEmpty:    true,
  2508  			IncludeDisk:    true,
  2509  			DevicePath:     devicePath2,
  2510  			UsePart:        false,
  2511  		},
  2512  	})
  2513  	mock.ExpectQuery(sqlquery.GetTerminalLabels).
  2514  		WithArgs(terminalID, sql.NullString{}).
  2515  		WillReturnRows(mock.NewRows([]string{"terminal_id", "terminal_label_edge_id", "label_edge_id", "labelkey", "color", "visible", "editable", "banner", "unique", "description", "label_type"}).
  2516  			AddRow(terminalID, "388d1144-27c5-44e2-856a-e69a3d4f859f", testLabelEdgeID, label.Key, label.Color, label.Visible, label.Editable, label.BannerEdgeID, label.Unique, label.Description, label.Type))
  2517  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  2518  		WithArgs(mockTerminal.ClusterEdgeID).
  2519  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  2520  			AddRow("test-org"))
  2521  	mock.ExpectExec(sqlquery.UploadEdgeBootstrapToken).
  2522  		WithArgs(sqlmock.AnyArg(), sqlmock.AnyArg(), mockTerminal.ClusterEdgeID).
  2523  		WillReturnResult(sqlmock.NewResult(1, 1))
  2524  
  2525  	getKubeResource := func() GetKubeResourceFunc {
  2526  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  2527  			assert.Equal(t, projectID, _projectID)
  2528  			assert.Nil(t, cluster)
  2529  			res := versionResource
  2530  			return []string{res}, nil
  2531  		}
  2532  	}
  2533  	bqClientMock := createMockBQClient(t, getKubeResource())
  2534  	artifactsService := artifacts.NewArtifactsService(db, nil)
  2535  	labelSvc := NewLabelService(artifactsService, db)
  2536  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  2537  	getLabel := true
  2538  	terminal, err := service.GetTerminal(context.Background(), terminalID, &getLabel)
  2539  	assert.NoError(t, err)
  2540  
  2541  	grubSecret, err := grub.New("")
  2542  	assert.NoError(t, err)
  2543  
  2544  	osSecret, err := breakglass.New("")
  2545  	assert.NoError(t, err)
  2546  
  2547  	bootstrapTokenValues, _, err := tokens.GenerateBootstrapJoinToken()
  2548  	assert.NoError(t, err)
  2549  
  2550  	config, err := service.GetTerminalBootstrapConfig(context.Background(), terminal, clusterNetworkServices, osSecret, grubSecret, true, true, "test-org", bootstrapTokenValues, clusterCaHash, "apiEndpoint.dev")
  2551  	assert.NoError(t, err)
  2552  	assert.NotEqual(t, "", config)
  2553  }
  2554  
  2555  func mockTerminalNodeStatus(mock sqlmock.Sqlmock, query, kind, clusterEdgeID, testHostName, row string) func() *sqlmock.ExpectedQuery {
  2556  	return func() *sqlmock.ExpectedQuery {
  2557  		return mock.ExpectQuery(query).
  2558  			WithArgs(kind, clusterEdgeID, testHostName, false).
  2559  			WillReturnRows(sqlmock.NewRows([]string{"value"}).
  2560  				AddRow(row))
  2561  	}
  2562  }
  2563  
  2564  func mockTerminalNodeStatusWithNoRowsErr(mock sqlmock.Sqlmock, kind, clusterEdgeID, testHostName string) func() *sqlmock.ExpectedQuery {
  2565  	return func() *sqlmock.ExpectedQuery {
  2566  		return mock.ExpectQuery(sqlquery.GetTerminalNodeStatus).
  2567  			WithArgs(kind, clusterEdgeID, testHostName, false).
  2568  			WillReturnError(sql.ErrNoRows)
  2569  	}
  2570  }
  2571  
  2572  func TestGetTerminalNodeStatus(t *testing.T) {
  2573  	clusterEdgeID := "3493a0a9-b084-475b-b6e0-16440db48ba0"
  2574  	terminalEdgeID := uuid.NewString()
  2575  	testHostName := "host-a"
  2576  
  2577  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  2578  	if err != nil {
  2579  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  2580  	}
  2581  	defer db.Close()
  2582  
  2583  	artifactsService := artifacts.NewArtifactsService(db, nil)
  2584  	labelSvc := NewLabelService(artifactsService, db)
  2585  	service := NewTerminalService(db, labelSvc)
  2586  
  2587  	tests := []struct {
  2588  		testName      string
  2589  		clusterEdgeID string
  2590  		expected      *model.TerminalStatus
  2591  		mockSQLQuery  []func() *sqlmock.ExpectedQuery
  2592  	}{
  2593  		{
  2594  			testName:      "Node and IENode Ready",
  2595  			clusterEdgeID: clusterEdgeID,
  2596  			expected: &model.TerminalStatus{
  2597  				Status:  status.Ready,
  2598  				Message: status.NodeReadyMessage,
  2599  			},
  2600  			mockSQLQuery: []func() *sqlmock.ExpectedQuery{
  2601  				mockTerminalNodeStatus(mock, sqlquery.GetTerminalNodeStatus, "Node", clusterEdgeID, testHostName, "True"),
  2602  				mockTerminalNodeStatus(mock, sqlquery.GetTerminalNodeStatus, "IENode", clusterEdgeID, testHostName, "True"),
  2603  			},
  2604  		},
  2605  		{
  2606  			testName:      "Node Not Ready",
  2607  			clusterEdgeID: clusterEdgeID,
  2608  			expected: &model.TerminalStatus{
  2609  				Status:  "Error",
  2610  				Message: "Node not ready",
  2611  			},
  2612  			mockSQLQuery: []func() *sqlmock.ExpectedQuery{
  2613  				mockTerminalNodeStatus(mock, sqlquery.GetTerminalNodeStatus, "Node", clusterEdgeID, testHostName, "False"),
  2614  				mockTerminalNodeStatus(mock, sqlquery.GetTerminalNodeStatus, "IENode", clusterEdgeID, testHostName, "True"),
  2615  				mockTerminalNodeStatus(mock, sqlquery.GetTerminalNodeStatusMessage, "Node", clusterEdgeID, testHostName, "Node not ready"),
  2616  			},
  2617  		},
  2618  		{
  2619  			testName:      "IENode Not Ready",
  2620  			clusterEdgeID: clusterEdgeID,
  2621  			expected: &model.TerminalStatus{
  2622  				Status:  "Error",
  2623  				Message: "An error occurred applying customlabels to node",
  2624  			},
  2625  			mockSQLQuery: []func() *sqlmock.ExpectedQuery{
  2626  				mockTerminalNodeStatus(mock, sqlquery.GetTerminalNodeStatus, "Node", clusterEdgeID, testHostName, "True"),
  2627  				mockTerminalNodeStatus(mock, sqlquery.GetTerminalNodeStatus, "IENode", clusterEdgeID, testHostName, "False"),
  2628  				mockTerminalNodeStatus(mock, sqlquery.GetTerminalNodeStatusMessage, "IENode", clusterEdgeID, testHostName, "An error occurred applying customlabels to node"),
  2629  			},
  2630  		},
  2631  		{
  2632  			testName:      "Node and IENode Not Ready",
  2633  			clusterEdgeID: clusterEdgeID,
  2634  			expected: &model.TerminalStatus{
  2635  				Status:  "Error",
  2636  				Message: "Node not ready and An error occurred applying customlabels to node",
  2637  			},
  2638  			mockSQLQuery: []func() *sqlmock.ExpectedQuery{
  2639  				mockTerminalNodeStatus(mock, sqlquery.GetTerminalNodeStatus, "Node", clusterEdgeID, testHostName, "False"),
  2640  				mockTerminalNodeStatus(mock, sqlquery.GetTerminalNodeStatus, "IENode", clusterEdgeID, testHostName, "False"),
  2641  				mockTerminalNodeStatus(mock, sqlquery.GetTerminalNodeStatusMessage, "Node", clusterEdgeID, testHostName, "Node not ready"),
  2642  				mockTerminalNodeStatus(mock, sqlquery.GetTerminalNodeStatusMessage, "IENode", clusterEdgeID, testHostName, "An error occurred applying customlabels to node"),
  2643  			},
  2644  		},
  2645  		{
  2646  			testName:      "Node Status Not Reported and Activation Code has been consumed",
  2647  			clusterEdgeID: clusterEdgeID,
  2648  			expected: &model.TerminalStatus{
  2649  				Status:  status.Disconnected,
  2650  				Message: status.DisconnectedMessage,
  2651  			},
  2652  			mockSQLQuery: []func() *sqlmock.ExpectedQuery{
  2653  				mockTerminalNodeStatusWithNoRowsErr(mock, "Node", clusterEdgeID, testHostName),
  2654  				mockTerminalNodeStatus(mock, sqlquery.GetTerminalNodeStatus, "IENode", clusterEdgeID, testHostName, "True"),
  2655  				func() *sqlmock.ExpectedQuery {
  2656  					return mock.ExpectQuery(edgenode.GetActivationCode).
  2657  						WithArgs(terminalEdgeID).
  2658  						WillReturnRows(sqlmock.NewRows([]string{"activation_code"}).
  2659  							AddRow(""))
  2660  				},
  2661  			},
  2662  		},
  2663  		{
  2664  			testName:      "IENode Status Not Reported and Activation Code has been consumed",
  2665  			clusterEdgeID: clusterEdgeID,
  2666  			expected: &model.TerminalStatus{
  2667  				Status:  status.Disconnected,
  2668  				Message: status.DisconnectedMessage,
  2669  			},
  2670  			mockSQLQuery: []func() *sqlmock.ExpectedQuery{
  2671  				mockTerminalNodeStatus(mock, sqlquery.GetTerminalNodeStatus, "Node", clusterEdgeID, testHostName, "True"),
  2672  				mockTerminalNodeStatusWithNoRowsErr(mock, "IENode", clusterEdgeID, testHostName),
  2673  				func() *sqlmock.ExpectedQuery {
  2674  					return mock.ExpectQuery(edgenode.GetActivationCode).
  2675  						WithArgs(terminalEdgeID).
  2676  						WillReturnRows(sqlmock.NewRows([]string{"activation_code"}).
  2677  							AddRow(""))
  2678  				},
  2679  			},
  2680  		},
  2681  		{
  2682  			testName:      "IENode and Node Status Not Reported and Activation Code has been consumed",
  2683  			clusterEdgeID: clusterEdgeID,
  2684  			expected: &model.TerminalStatus{
  2685  				Status:  status.NotAvailable,
  2686  				Message: status.NotAvailableMessage,
  2687  			},
  2688  			mockSQLQuery: []func() *sqlmock.ExpectedQuery{
  2689  				mockTerminalNodeStatusWithNoRowsErr(mock, "Node", clusterEdgeID, testHostName),
  2690  				mockTerminalNodeStatusWithNoRowsErr(mock, "IENode", clusterEdgeID, testHostName),
  2691  				func() *sqlmock.ExpectedQuery {
  2692  					return mock.ExpectQuery(edgenode.GetActivationCode).
  2693  						WithArgs(terminalEdgeID).
  2694  						WillReturnRows(sqlmock.NewRows([]string{"activation_code"}).
  2695  							AddRow(""))
  2696  				},
  2697  			},
  2698  		},
  2699  		{
  2700  			testName:      "IENode and Node Status Not Reported and Activation Code has not been consumed",
  2701  			clusterEdgeID: clusterEdgeID,
  2702  			expected: &model.TerminalStatus{
  2703  				Status:  status.AwaitingInstallation,
  2704  				Message: status.UnusedActivationCodeMessage,
  2705  			},
  2706  			mockSQLQuery: []func() *sqlmock.ExpectedQuery{
  2707  				mockTerminalNodeStatusWithNoRowsErr(mock, "Node", clusterEdgeID, testHostName),
  2708  				mockTerminalNodeStatusWithNoRowsErr(mock, "IENode", clusterEdgeID, testHostName),
  2709  				func() *sqlmock.ExpectedQuery {
  2710  					return mock.ExpectQuery(edgenode.GetActivationCode).
  2711  						WithArgs(terminalEdgeID).
  2712  						WillReturnRows(sqlmock.NewRows([]string{"activation_code"}).
  2713  							AddRow("123abc"))
  2714  				},
  2715  			},
  2716  		},
  2717  	}
  2718  
  2719  	for _, tc := range tests {
  2720  		for _, mockSQLFn := range tc.mockSQLQuery {
  2721  			mockSQLFn()
  2722  		}
  2723  
  2724  		t.Run(tc.testName, func(t *testing.T) {
  2725  			nodeStatus, err := service.GetTerminalNodeStatus(context.Background(), clusterEdgeID, terminalEdgeID, testHostName)
  2726  			assert.NoError(t, err)
  2727  			assert.Equal(t, tc.expected.Status, nodeStatus.Status)
  2728  			assert.Equal(t, tc.expected.Message, nodeStatus.Message)
  2729  		})
  2730  	}
  2731  }
  2732  
  2733  func mockNodeReplicationName(mock sqlmock.Sqlmock) func(clusterID, hostname string, status *model.ReplicationStatus) *sqlmock.ExpectedQuery {
  2734  	return func(clusterID, hostname string, status *model.ReplicationStatus) *sqlmock.ExpectedQuery {
  2735  		m := mock.ExpectQuery(sqlquery.GetNodeReplicaName).
  2736  			WithArgs(clusterID, fmt.Sprintf("%q", hostname))
  2737  		if status.Name != "" {
  2738  			return m.WillReturnRows(sqlmock.NewRows([]string{"name"}).
  2739  				AddRow(status.Name))
  2740  		}
  2741  		return m.WillReturnError(sql.ErrNoRows)
  2742  	}
  2743  }
  2744  
  2745  func mockNodeReplicationStatus(mock sqlmock.Sqlmock) func(clusterID, hostname string, status *model.ReplicationStatus) *sqlmock.ExpectedQuery {
  2746  	return func(clusterID, _ string, status *model.ReplicationStatus) *sqlmock.ExpectedQuery {
  2747  		m := mock.ExpectQuery(sqlquery.GetReplicationStatusByName).
  2748  			WithArgs(clusterID, status.Name)
  2749  		if status.Name != "" {
  2750  			return m.WillReturnRows(sqlmock.NewRows([]string{"name", "value"}).
  2751  				AddRow(status.Name, status.Status))
  2752  		}
  2753  		return m.WillReturnError(sql.ErrNoRows)
  2754  	}
  2755  }
  2756  
  2757  func TestGetNodeReplicationStatus(t *testing.T) {
  2758  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  2759  	if err != nil {
  2760  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  2761  	}
  2762  	defer db.Close()
  2763  
  2764  	artifactsService := artifacts.NewArtifactsService(db, nil)
  2765  	labelSvc := NewLabelService(artifactsService, db)
  2766  	service := NewTerminalService(db, labelSvc)
  2767  
  2768  	tests := []struct {
  2769  		testName      string
  2770  		hostName      string
  2771  		clusterEdgeID string
  2772  		expected      *model.ReplicationStatus
  2773  		mockSQLQuery  []func(clusterID, hostName string, status *model.ReplicationStatus) *sqlmock.ExpectedQuery
  2774  	}{
  2775  		{
  2776  			testName:      "Replication status success",
  2777  			hostName:      "host-1",
  2778  			clusterEdgeID: uuid.NewString(),
  2779  			expected: &model.ReplicationStatus{
  2780  				Status: "True",
  2781  				Name:   "couchdb-" + uuid.NewString(),
  2782  			},
  2783  			mockSQLQuery: []func(clusterID, hostName string, s *model.ReplicationStatus) *sqlmock.ExpectedQuery{
  2784  				mockNodeReplicationName(mock),
  2785  				mockNodeReplicationStatus(mock),
  2786  			},
  2787  		},
  2788  		{
  2789  			testName:      "Replication status not found",
  2790  			hostName:      "host-2",
  2791  			clusterEdgeID: uuid.NewString(),
  2792  			expected: &model.ReplicationStatus{
  2793  				Status: "NotFound",
  2794  				Name:   "",
  2795  			},
  2796  			mockSQLQuery: []func(clusterID, hostName string, s *model.ReplicationStatus) *sqlmock.ExpectedQuery{
  2797  				mockNodeReplicationName(mock),
  2798  				mockNodeReplicationStatus(mock),
  2799  			},
  2800  		},
  2801  	}
  2802  	for _, tc := range tests {
  2803  		for _, mockSQLFn := range tc.mockSQLQuery {
  2804  			mockSQLFn(tc.clusterEdgeID, tc.hostName, tc.expected)
  2805  		}
  2806  
  2807  		t.Run(tc.testName, func(t *testing.T) {
  2808  			replicationStatus, err := service.GetNodeReplicationStatus(context.Background(), tc.clusterEdgeID, tc.hostName)
  2809  			assert.NoError(t, err)
  2810  			assert.Equal(t, tc.expected.Status, replicationStatus.Status)
  2811  			assert.Equal(t, tc.expected.Name, replicationStatus.Name)
  2812  		})
  2813  	}
  2814  }
  2815  
  2816  func TestGetTerminalDevices(t *testing.T) {
  2817  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
  2818  	if err != nil {
  2819  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  2820  	}
  2821  	defer db.Close()
  2822  
  2823  	mockTerminal := terminals[1]
  2824  	iface := mockTerminal.Interfaces[0]
  2825  	mockIfaces := []*model.TerminalInterface{iface}
  2826  	mockAddrs := []*model.TerminalAddress{}
  2827  
  2828  	mockDBGetTerminalByID(mock, mockTerminal.TerminalID, &mockTerminal)
  2829  	mockDBGetTerminalInterfaceByTerminalIDQuery(mock, mockTerminal.TerminalID, mockIfaces)
  2830  	mockDBGetTerminalAddressByInterfaceIDQuery(mock, iface.TerminalInterfaceID, mockAddrs)
  2831  	mockDBGetTerminalDiskByTerminalID(mock, mockTerminal.TerminalID, nil)
  2832  	mock.ExpectQuery(sqlquery.GetProjectIDByClusterEdgeID).
  2833  		WithArgs(mockTerminal.ClusterEdgeID).
  2834  		WillReturnRows(mock.NewRows([]string{"project_id"}).
  2835  			AddRow("test-org"))
  2836  
  2837  	cardName := "card0-VGA-1 ACR-2199"
  2838  	mock.ExpectQuery(sqlquery.GetTerminalDevices).
  2839  		WithArgs(mockTerminal.Hostname, mockTerminal.ClusterEdgeID).
  2840  		WillReturnRows(mock.NewRows([]string{"value"}).AddRow(fmt.Sprintf(`
  2841  		{
  2842  			"device-system.class.edge.ncr.com/display": [
  2843  				{
  2844  					"name": "%s"
  2845  				}
  2846  			]
  2847  		}
  2848  		`, cardName)))
  2849  
  2850  	getKubeResource := func() GetKubeResourceFunc {
  2851  		return func(_ context.Context, _projectID string, cluster *model.Cluster, _ model.LoqRequest) ([]string, error) {
  2852  			assert.Equal(t, projectID, _projectID)
  2853  			assert.Nil(t, cluster)
  2854  			res := versionResource
  2855  			return []string{res}, nil
  2856  		}
  2857  	}
  2858  	bqClientMock := createMockBQClient(t, getKubeResource())
  2859  	artifactsService := artifacts.NewArtifactsService(db, nil)
  2860  	labelSvc := NewLabelService(artifactsService, db)
  2861  	service := NewTerminalServiceBQ(db, bqClientMock, labelSvc)
  2862  
  2863  	terminalDevices, err := service.TerminalDevices(context.Background(), terminalID2)
  2864  	assert.NoError(t, err)
  2865  	assert.Len(t, terminalDevices.Classes, 1)
  2866  	assert.Len(t, terminalDevices.Classes[0].Devices, 1)
  2867  	assert.Equal(t, terminalDevices.Classes[0].Devices[0].Name, cardName)
  2868  }
  2869  
  2870  func mockDBGetClustersByBannerEdgeIDQuery(mock sqlmock.Sqlmock, bannerEdgeID string, returnTerminals []model.Terminal) {
  2871  	rows := mock.NewRows([]string{"terminal_id", "lane", "terminal_role", "class",
  2872  		"discover_disks", "boot_disk", "primary_interface", "existing_efi_part", "swap_enabled", "cluster_edge_id", "cluster_name", "hostname", "interface_id", "mac_address", "dhcp4", "dhcp6", "gateway4", "gateway6",
  2873  		"terminal_id", "address_id", "ip", "prefix_len", "family", "interface_id"})
  2874  
  2875  	if len(returnTerminals) != 0 {
  2876  		for _, terminal := range returnTerminals {
  2877  			fmt.Println(terminal.TerminalID)
  2878  			fmt.Println(*terminal.Lane)
  2879  			fmt.Println(*terminal.PrimaryInterface)
  2880  
  2881  			if len(terminal.Interfaces) == 0 {
  2882  				// terminal with no interfaces
  2883  				rows.AddRow(terminal.TerminalID, terminal.Lane, terminal.Role, terminal.Class, terminal.DiscoverDisks, terminal.BootDisk, terminal.PrimaryInterface, terminal.ExistingEfiPart, terminal.SwapEnabled,
  2884  					terminal.ClusterEdgeID, terminal.ClusterName, terminal.Hostname, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
  2885  			} else {
  2886  				addTerminalInterfacesForBannerTerminals(rows, terminal)
  2887  			}
  2888  		}
  2889  	}
  2890  
  2891  	mock.ExpectQuery(sqlquery.GetClustersByBannerEdgeIDQuery).
  2892  		WithArgs(bannerEdgeID).
  2893  		WillReturnRows(rows)
  2894  }
  2895  
  2896  func addTerminalInterfacesForBannerTerminals(rows *sqlmock.Rows, terminal model.Terminal) {
  2897  	for _, iface := range terminal.Interfaces {
  2898  		if len(iface.Addresses) == 0 {
  2899  			// interface with no addresses
  2900  			rows.AddRow(terminal.TerminalID, terminal.Lane, terminal.Role, terminal.Class, terminal.DiscoverDisks, terminal.BootDisk, terminal.PrimaryInterface, terminal.ExistingEfiPart, terminal.SwapEnabled,
  2901  				terminal.ClusterEdgeID, terminal.ClusterName, terminal.Hostname, iface.TerminalInterfaceID, iface.MacAddress, iface.Dhcp4, iface.Dhcp6, iface.Gateway4, iface.Gateway6, iface.TerminalID, nil,
  2902  				nil, nil, nil, nil)
  2903  		} else {
  2904  			addTerminalAddressForBannerTerminals(rows, terminal, *iface)
  2905  		}
  2906  	}
  2907  }
  2908  
  2909  func addTerminalAddressForBannerTerminals(rows *sqlmock.Rows, terminal model.Terminal, iface model.TerminalInterface) {
  2910  	for _, addr := range iface.Addresses {
  2911  		rows.AddRow(terminal.TerminalID, terminal.Lane, terminal.Role, terminal.Class, terminal.DiscoverDisks, terminal.BootDisk, terminal.PrimaryInterface, terminal.ExistingEfiPart, terminal.SwapEnabled, terminal.ClusterEdgeID, terminal.ClusterName, terminal.Hostname,
  2912  			iface.TerminalInterfaceID, iface.MacAddress, iface.Dhcp4, iface.Dhcp6, iface.Gateway4, iface.Gateway6, iface.TerminalID, addr.TerminalAddressID,
  2913  			addr.IP, addr.PrefixLen, addr.Family, addr.TerminalInterfaceID)
  2914  	}
  2915  }
  2916  
  2917  func mockDBGetTerminalByID(mock sqlmock.Sqlmock, terminalID string, returnTerminal *model.Terminal) {
  2918  	rows := mock.NewRows(terminalColumns)
  2919  
  2920  	if returnTerminal != nil {
  2921  		rows.AddRow(returnTerminal.TerminalID, returnTerminal.Lane, returnTerminal.Role, returnTerminal.ClusterEdgeID,
  2922  			returnTerminal.ClusterName, returnTerminal.Class, returnTerminal.DiscoverDisks, returnTerminal.BootDisk, returnTerminal.PrimaryInterface, returnTerminal.ExistingEfiPart, returnTerminal.SwapEnabled, returnTerminal.Hostname)
  2923  	}
  2924  
  2925  	mock.ExpectQuery(sqlquery.GetTerminalByIDQuery).
  2926  		WithArgs(terminalID).
  2927  		WillReturnRows(rows)
  2928  }
  2929  
  2930  func mockDBGetTerminalByClusterEdgeID(mock sqlmock.Sqlmock, clusterEdgeID string, returnTerminals []model.Terminal) {
  2931  	rows := mock.NewRows(terminalColumns)
  2932  
  2933  	if len(returnTerminals) != 0 {
  2934  		for _, terminal := range returnTerminals {
  2935  			rows.AddRow(terminal.TerminalID, terminal.Lane, terminal.Role, terminal.ClusterEdgeID, terminal.ClusterName,
  2936  				terminal.Class, terminal.DiscoverDisks, terminal.BootDisk, terminal.PrimaryInterface, terminal.ExistingEfiPart, terminal.SwapEnabled, terminal.Hostname)
  2937  		}
  2938  	}
  2939  
  2940  	mock.ExpectQuery(sqlquery.GetTerminalByClusterEdgeIDQuery).
  2941  		WithArgs(clusterEdgeID).
  2942  		WillReturnRows(rows)
  2943  }
  2944  
  2945  func mockDBGetAllTerminals(mock sqlmock.Sqlmock, returnTerminals []model.Terminal) {
  2946  	rows := mock.NewRows(terminalColumns)
  2947  
  2948  	if len(returnTerminals) != 0 {
  2949  		for _, terminal := range returnTerminals {
  2950  			rows.AddRow(terminal.TerminalID, terminal.Lane, terminal.Role, terminal.ClusterEdgeID, terminal.ClusterName,
  2951  				terminal.Class, terminal.DiscoverDisks, terminal.BootDisk, terminal.PrimaryInterface, terminal.ExistingEfiPart, terminal.SwapEnabled, terminal.Hostname)
  2952  		}
  2953  	}
  2954  
  2955  	mock.ExpectQuery(sqlquery.GetAllTerminalsQuery).
  2956  		WillReturnRows(rows)
  2957  }
  2958  
  2959  func mockDBGetTerminalByHostname(mock sqlmock.Sqlmock, hostname string, returnTerminals []model.Terminal) {
  2960  	rows := mock.NewRows(terminalColumns)
  2961  
  2962  	if len(returnTerminals) != 0 {
  2963  		for _, terminal := range returnTerminals {
  2964  			rows.AddRow(terminal.TerminalID, terminal.Lane, terminal.Role, terminal.ClusterEdgeID, terminal.ClusterName,
  2965  				terminal.Class, terminal.DiscoverDisks, terminal.BootDisk, terminal.PrimaryInterface, terminal.ExistingEfiPart, terminal.SwapEnabled, terminal.Hostname)
  2966  		}
  2967  	}
  2968  
  2969  	mock.ExpectQuery(sqlquery.GetTerminalByHostnameQuery).
  2970  		WithArgs(hostname).
  2971  		WillReturnRows(rows)
  2972  }
  2973  
  2974  func mockDBGetTerminalByClusterEdgeIDAndHostname(mock sqlmock.Sqlmock, clusterEdgeID string, hostname string, returnTerminals []model.Terminal) {
  2975  	rows := mock.NewRows(terminalColumns)
  2976  
  2977  	if len(returnTerminals) != 0 {
  2978  		for _, terminal := range returnTerminals {
  2979  			rows.AddRow(terminal.TerminalID, terminal.Lane, terminal.Role, terminal.ClusterEdgeID, terminal.ClusterName,
  2980  				terminal.Class, terminal.DiscoverDisks, terminal.BootDisk, terminal.PrimaryInterface, terminal.ExistingEfiPart, terminal.SwapEnabled, terminal.Hostname)
  2981  		}
  2982  	}
  2983  
  2984  	mock.ExpectQuery(sqlquery.GetTerminalByClusterEdgeIDAndHostnameQuery).
  2985  		WithArgs(clusterEdgeID, hostname).
  2986  		WillReturnRows(rows)
  2987  }
  2988  
  2989  func mockDBGetAllHostnamesForACluster(mock sqlmock.Sqlmock, clusterEdgeID string, hostnames []string) {
  2990  	rows := mock.NewRows([]string{"hostname"})
  2991  
  2992  	if len(hostnames) != 0 {
  2993  		for _, hostname := range hostnames {
  2994  			rows.AddRow(hostname)
  2995  		}
  2996  	}
  2997  
  2998  	mock.ExpectQuery(sqlquery.GetAllHostnamesForAClusterQuery).
  2999  		WithArgs(clusterEdgeID).
  3000  		WillReturnRows(rows)
  3001  }
  3002  
  3003  func mockDBGetAllLanesForACluster(mock sqlmock.Sqlmock, clusterEdgeID string, lanesAndHostnames []terminalLaneAndHostname) {
  3004  	rows := mock.NewRows([]string{"lane", "hostname"})
  3005  
  3006  	if len(lanesAndHostnames) != 0 {
  3007  		for _, laneAndHostname := range lanesAndHostnames {
  3008  			if laneAndHostname.lane == nil {
  3009  				rows.AddRow(nil, laneAndHostname.hostname)
  3010  			} else {
  3011  				rows.AddRow(*laneAndHostname.lane, laneAndHostname.hostname)
  3012  			}
  3013  		}
  3014  	}
  3015  
  3016  	mock.ExpectQuery(sqlquery.GetAllLanesForAClusterQuery).
  3017  		WithArgs(clusterEdgeID).
  3018  		WillReturnRows(rows)
  3019  }
  3020  
  3021  func mockDBTerminalCreate(mock sqlmock.Sqlmock, terminal model.Terminal, result driver.Result) {
  3022  	input := []driver.Value{
  3023  		sqlmock.AnyArg(),
  3024  		terminal.Lane,
  3025  		terminal.Role,
  3026  		terminal.Class,
  3027  		terminal.DiscoverDisks,
  3028  		terminal.BootDisk,
  3029  		terminal.ClusterEdgeID,
  3030  		terminal.Hostname,
  3031  		terminal.ActivationCode,
  3032  		terminal.ExistingEfiPart,
  3033  		terminal.SwapEnabled,
  3034  	}
  3035  
  3036  	mock.ExpectExec(sqlquery.TerminalCreateQuery).
  3037  		WithArgs(input...).
  3038  		WillReturnResult(result)
  3039  }
  3040  
  3041  func mockDBTerminalDelete(mock sqlmock.Sqlmock, terminalID string, result driver.Result) {
  3042  	mock.ExpectExec(sqlquery.TerminalDeleteQuery).
  3043  		WithArgs(terminalID).
  3044  		WillReturnResult(result)
  3045  }
  3046  
  3047  func mockDBTerminalUpdate(mock sqlmock.Sqlmock, terminalID string, updateTerminal model.TerminalUpdateInput, result driver.Result) {
  3048  	update := []driver.Value{
  3049  		updateTerminal.Lane,
  3050  		updateTerminal.Role,
  3051  		updateTerminal.Class,
  3052  		updateTerminal.DiscoverDisks,
  3053  		updateTerminal.BootDisk,
  3054  		updateTerminal.PrimaryInterface,
  3055  		updateTerminal.ExistingEfiPart,
  3056  		updateTerminal.SwapEnabled,
  3057  		terminalID,
  3058  	}
  3059  	mock.ExpectExec(sqlquery.TerminalUpdateQuery).
  3060  		WithArgs(update...).
  3061  		WillReturnResult(result)
  3062  }
  3063  
  3064  func mockDBTerminalInterfaceCreateQuery(mock sqlmock.Sqlmock, createIfaceInput model.TerminalInterface, result driver.Result) {
  3065  	input := []driver.Value{
  3066  		sqlmock.AnyArg(),
  3067  		createIfaceInput.MacAddress,
  3068  		createIfaceInput.Dhcp4,
  3069  		createIfaceInput.Dhcp6,
  3070  		createIfaceInput.Gateway4,
  3071  		createIfaceInput.Gateway6,
  3072  		sqlmock.AnyArg(),
  3073  	}
  3074  
  3075  	mock.ExpectExec(sqlquery.TerminalInterfaceCreateQuery).
  3076  		WithArgs(input...).
  3077  		WillReturnResult(result)
  3078  }
  3079  
  3080  func mockDBTerminalInterfaceDeleteQuery(mock sqlmock.Sqlmock, ifaceID string, result driver.Result) {
  3081  	mock.ExpectExec(sqlquery.TerminalInterfaceDeleteQuery).
  3082  		WithArgs(ifaceID).
  3083  		WillReturnResult(result)
  3084  }
  3085  
  3086  func mockDBTerminalInterfaceUpdateQuery(mock sqlmock.Sqlmock, ifaceID string, ifaceUpdateInput model.TerminalInterfaceUpdateInput, result driver.Result) {
  3087  	input := []driver.Value{
  3088  		ifaceUpdateInput.MacAddress,
  3089  		ifaceUpdateInput.Dhcp4,
  3090  		ifaceUpdateInput.Dhcp6,
  3091  		ifaceUpdateInput.Gateway4,
  3092  		ifaceUpdateInput.Gateway6,
  3093  		ifaceID,
  3094  	}
  3095  
  3096  	mock.ExpectExec(sqlquery.TerminalInterfaceUpdateQuery).
  3097  		WithArgs(input...).
  3098  		WillReturnResult(result)
  3099  }
  3100  
  3101  func mockDBGetTerminalInterfaceQuery(mock sqlmock.Sqlmock, interfaceID string, ifaces []*model.TerminalInterface) {
  3102  	rows := mock.NewRows(terminalIfaceColumns)
  3103  
  3104  	for _, iface := range ifaces {
  3105  		if iface != nil {
  3106  			rows.AddRow(iface.TerminalInterfaceID, iface.MacAddress, iface.Dhcp4, iface.Dhcp6, iface.Gateway4, iface.Gateway6, iface.TerminalID)
  3107  		}
  3108  	}
  3109  
  3110  	mock.ExpectQuery(sqlquery.GetTerminalInterfaceQuery).
  3111  		WithArgs(interfaceID).
  3112  		WillReturnRows(rows)
  3113  }
  3114  
  3115  func mockDBGetTerminalInterfaceByTerminalIDQuery(mock sqlmock.Sqlmock, terminalID string, ifaces []*model.TerminalInterface) {
  3116  	rows := mock.NewRows(terminalIfaceColumns)
  3117  
  3118  	for _, iface := range ifaces {
  3119  		if iface != nil {
  3120  			rows.AddRow(iface.TerminalInterfaceID, iface.MacAddress, iface.Dhcp4, iface.Dhcp6, iface.Gateway4, iface.Gateway6, iface.TerminalID)
  3121  		}
  3122  	}
  3123  
  3124  	mock.ExpectQuery(sqlquery.GetTerminalInterfaceByTerminalIDQuery).
  3125  		WithArgs(terminalID).
  3126  		WillReturnRows(rows)
  3127  }
  3128  
  3129  func mockDBGetTerminalIDFromInterfaceQuery(mock sqlmock.Sqlmock, ifaceID string, returnedTerminalIDs []string) {
  3130  	rows := mock.NewRows([]string{"terminal_id"})
  3131  
  3132  	for _, tID := range returnedTerminalIDs {
  3133  		rows.AddRow(tID)
  3134  	}
  3135  
  3136  	mock.ExpectQuery(sqlquery.GetTerminalIDFromInterfaceQuery).
  3137  		WithArgs(ifaceID).
  3138  		WillReturnRows(rows)
  3139  }
  3140  
  3141  func mockDBTerminalAddressCreateQuery(mock sqlmock.Sqlmock, createAddrInput model.TerminalAddress, result driver.Result) {
  3142  	input := []driver.Value{
  3143  		sqlmock.AnyArg(),
  3144  		createAddrInput.IP,
  3145  		createAddrInput.PrefixLen,
  3146  		createAddrInput.Family,
  3147  		sqlmock.AnyArg(),
  3148  	}
  3149  
  3150  	mock.ExpectExec(sqlquery.TerminalAddressCreateQuery).
  3151  		WithArgs(input...).
  3152  		WillReturnResult(result)
  3153  }
  3154  
  3155  func mockDBTerminalAddressDeleteQuery(mock sqlmock.Sqlmock, addrID string, result driver.Result) {
  3156  	mock.ExpectExec(sqlquery.TerminalAddressDeleteQuery).
  3157  		WithArgs(addrID).
  3158  		WillReturnResult(result)
  3159  }
  3160  
  3161  func mockDBTerminalAddressUpdateQuery(mock sqlmock.Sqlmock, addrID string, addrUpdateInput model.TerminalAddressUpdateInput, result driver.Result) {
  3162  	input := []driver.Value{
  3163  		addrUpdateInput.IP,
  3164  		addrUpdateInput.PrefixLen,
  3165  		addrUpdateInput.Family,
  3166  		addrID,
  3167  	}
  3168  
  3169  	mock.ExpectExec(sqlquery.TerminalAddressUpdateQuery).
  3170  		WithArgs(input...).
  3171  		WillReturnResult(result)
  3172  }
  3173  
  3174  func mockDBGetTerminalAddressQuery(mock sqlmock.Sqlmock, addressID string, returnedAddrs []*model.TerminalAddress) {
  3175  	rows := mock.NewRows(terminalAddrColumns)
  3176  
  3177  	for _, addr := range returnedAddrs {
  3178  		rows.AddRow(addr.TerminalAddressID, addr.IP, addr.PrefixLen, addr.Family, addr.TerminalInterfaceID)
  3179  	}
  3180  
  3181  	mock.ExpectQuery(sqlquery.GetTerminalAddressQuery).
  3182  		WithArgs(addressID).
  3183  		WillReturnRows(rows)
  3184  }
  3185  
  3186  func mockDBGetTerminalAddressByInterfaceIDQuery(mock sqlmock.Sqlmock, ifaceID string, returnedAddrs []*model.TerminalAddress) {
  3187  	rows := mock.NewRows(terminalAddrColumns)
  3188  
  3189  	for _, addr := range returnedAddrs {
  3190  		rows.AddRow(addr.TerminalAddressID, addr.IP, addr.PrefixLen, addr.Family, addr.TerminalInterfaceID)
  3191  	}
  3192  
  3193  	mock.ExpectQuery(sqlquery.GetTerminalAddressByInterfaceIDQuery).
  3194  		WithArgs(ifaceID).
  3195  		WillReturnRows(rows)
  3196  }
  3197  
  3198  func mockDBGetInterfaceIDFromAddressQuery(mock sqlmock.Sqlmock, addrID string, returnedIfaceIDs []string) {
  3199  	rows := mock.NewRows([]string{"interface_id"})
  3200  
  3201  	for _, ifaceID := range returnedIfaceIDs {
  3202  		rows.AddRow(ifaceID)
  3203  	}
  3204  
  3205  	mock.ExpectQuery(sqlquery.GetInterfaceIDFromAddressQuery).
  3206  		WithArgs(addrID).
  3207  		WillReturnRows(rows)
  3208  }
  3209  
  3210  func getTerminalCreateInput(terminal model.Terminal) *model.TerminalCreateInput {
  3211  	return &model.TerminalCreateInput{
  3212  		Hostname:        &terminal.Hostname,
  3213  		Lane:            terminal.Lane,
  3214  		Role:            terminal.Role,
  3215  		Class:           terminal.Class,
  3216  		DiscoverDisks:   terminal.DiscoverDisks,
  3217  		BootDisk:        terminal.BootDisk,
  3218  		ClusterEdgeID:   terminal.ClusterEdgeID,
  3219  		ExistingEfiPart: terminal.ExistingEfiPart,
  3220  		SwapEnabled:     &terminal.SwapEnabled,
  3221  	}
  3222  }
  3223  
  3224  func getIfaceCreateInput(iface model.TerminalInterface) *model.TerminalInterfaceCreateInput {
  3225  	return &model.TerminalInterfaceCreateInput{
  3226  		MacAddress: iface.MacAddress,
  3227  		Dhcp4:      iface.Dhcp4,
  3228  		Dhcp6:      iface.Dhcp6,
  3229  		Gateway4:   iface.Gateway4,
  3230  		Gateway6:   iface.Gateway6,
  3231  	}
  3232  }
  3233  
  3234  func getAddrCreateInput(addr model.TerminalAddress) *model.TerminalAddressCreateInput {
  3235  	return &model.TerminalAddressCreateInput{
  3236  		IP:        addr.IP,
  3237  		PrefixLen: addr.PrefixLen,
  3238  		Family:    addr.Family,
  3239  	}
  3240  }
  3241  

View as plain text