diff --git a/.github/.golangci.yml b/.github/.golangci.yml index 0f7707b2..e0cddf80 100644 --- a/.github/.golangci.yml +++ b/.github/.golangci.yml @@ -40,7 +40,7 @@ linters-settings: - operation - return govet: - check-shadowing: true + shadow: true misspell: locale: US nestif: @@ -133,4 +133,4 @@ issues: - docs run: - timeout: 5m \ No newline at end of file + timeout: 5m diff --git a/.golangci.yml b/.golangci.yml index 0f7707b2..e0cddf80 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -40,7 +40,7 @@ linters-settings: - operation - return govet: - check-shadowing: true + shadow: true misspell: locale: US nestif: @@ -133,4 +133,4 @@ issues: - docs run: - timeout: 5m \ No newline at end of file + timeout: 5m diff --git a/go.mod b/go.mod index 833b6c4e..e9ff5f49 100644 --- a/go.mod +++ b/go.mod @@ -62,7 +62,7 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect - github.com/open-amt-cloud-toolkit/go-wsman-messages/v2 v2.10.0 + github.com/open-amt-cloud-toolkit/go-wsman-messages/v2 v2.11.1 github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect diff --git a/go.sum b/go.sum index b2977b8c..268d755e 100644 --- a/go.sum +++ b/go.sum @@ -138,8 +138,8 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/open-amt-cloud-toolkit/go-wsman-messages/v2 v2.10.0 h1:W+gGMkbbr6zzcvYkUIkkA6SBf2IpW2cDhukFX/DLh/Y= -github.com/open-amt-cloud-toolkit/go-wsman-messages/v2 v2.10.0/go.mod h1:LyY8fOvYBt5gawHYuivROR7EBySRuSR0u/k8QosnCeU= +github.com/open-amt-cloud-toolkit/go-wsman-messages/v2 v2.11.1 h1:Q+Yj4E1i+5rzN+9QqXRAP3zX2ggkqrO53IpvkG/DkhA= +github.com/open-amt-cloud-toolkit/go-wsman-messages/v2 v2.11.1/go.mod h1:LyY8fOvYBt5gawHYuivROR7EBySRuSR0u/k8QosnCeU= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= diff --git a/internal/controller/http/v1/devicemanagement_mocks_test.go b/internal/controller/http/v1/devicemanagement_mocks_test.go index dd2320af..65fb4a03 100644 --- a/internal/controller/http/v1/devicemanagement_mocks_test.go +++ b/internal/controller/http/v1/devicemanagement_mocks_test.go @@ -72,6 +72,18 @@ func (mr *MockWSMANMockRecorder) SetupWsmanClient(device, isRedirection, logMess return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetupWsmanClient", reflect.TypeOf((*MockWSMAN)(nil).SetupWsmanClient), device, isRedirection, logMessages) } +// Worker mocks base method. +func (m *MockWSMAN) Worker() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Worker") +} + +// Worker indicates an expected call of Worker. +func (mr *MockWSMANMockRecorder) Worker() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Worker", reflect.TypeOf((*MockWSMAN)(nil).Worker)) +} + // MockRedirection is a mock of Redirection interface. type MockRedirection struct { ctrl *gomock.Controller diff --git a/internal/usecase/devices/alarms_test.go b/internal/usecase/devices/alarms_test.go index 74895661..1dfb612b 100644 --- a/internal/usecase/devices/alarms_test.go +++ b/internal/usecase/devices/alarms_test.go @@ -26,6 +26,8 @@ func initAlarmsTest(t *testing.T) (*devices.UseCase, *MockWSMAN, *MockManagement repo := NewMockRepository(mockCtl) wsmanMock := NewMockWSMAN(mockCtl) + wsmanMock.EXPECT().Worker().Return().AnyTimes() + management := NewMockManagement(mockCtl) log := logger.New("error") diff --git a/internal/usecase/devices/certificates_test.go b/internal/usecase/devices/certificates_test.go index ff348758..dc830171 100644 --- a/internal/usecase/devices/certificates_test.go +++ b/internal/usecase/devices/certificates_test.go @@ -27,6 +27,8 @@ func initCertificateTest(t *testing.T) (*devices.UseCase, *MockWSMAN, *MockManag repo := NewMockRepository(mockCtl) wsmanMock := NewMockWSMAN(mockCtl) + wsmanMock.EXPECT().Worker().Return().AnyTimes() + management := NewMockManagement(mockCtl) log := logger.New("error") u := devices.New(repo, wsmanMock, NewMockRedirection(mockCtl), log) diff --git a/internal/usecase/devices/consent_test.go b/internal/usecase/devices/consent_test.go index ec7001b5..b771c784 100644 --- a/internal/usecase/devices/consent_test.go +++ b/internal/usecase/devices/consent_test.go @@ -25,6 +25,7 @@ func initConsentTest(t *testing.T) (*devices.UseCase, *MockWSMAN, *MockManagemen repo := NewMockRepository(mockCtl) wsmanMock := NewMockWSMAN(mockCtl) + wsmanMock.EXPECT().Worker().Return().AnyTimes() management := NewMockManagement(mockCtl) diff --git a/internal/usecase/devices/info_test.go b/internal/usecase/devices/info_test.go index 1abeb8ea..c6ad76b9 100644 --- a/internal/usecase/devices/info_test.go +++ b/internal/usecase/devices/info_test.go @@ -28,6 +28,8 @@ func initInfoTest(t *testing.T) (*devices.UseCase, *MockWSMAN, *MockManagement, repo := NewMockRepository(mockCtl) wsmanMock := NewMockWSMAN(mockCtl) + wsmanMock.EXPECT().Worker().Return().AnyTimes() + management := NewMockManagement(mockCtl) log := logger.New("error") @@ -41,8 +43,7 @@ func TestGetVersion(t *testing.T) { t.Parallel() device := &entity.Device{ - GUID: "device-guid-123", - + GUID: "device-guid-123", TenantID: "tenant-id-456", } @@ -51,47 +52,30 @@ func TestGetVersion(t *testing.T) { responses := []setupandconfiguration.SetupAndConfigurationServiceResponse{} response := setupandconfiguration.SetupAndConfigurationServiceResponse{ - XMLName: xml.Name{Local: "AMT_SetupAndConfigurationService"}, - - RequestedState: 1, - - EnabledState: 1, - - ElementName: "SampleElementName", - - SystemCreationClassName: "SampleSystemCreationClassName", - - SystemName: "SampleSystemName", - - CreationClassName: "SampleCreationClassName", - - Name: "SampleName", - - ProvisioningMode: 1, - - ProvisioningState: 1, - + XMLName: xml.Name{Local: "AMT_SetupAndConfigurationService"}, + RequestedState: 1, + EnabledState: 1, + ElementName: "SampleElementName", + SystemCreationClassName: "SampleSystemCreationClassName", + SystemName: "SampleSystemName", + CreationClassName: "SampleCreationClassName", + Name: "SampleName", + ProvisioningMode: 1, + ProvisioningState: 1, ZeroTouchConfigurationEnabled: true, - - ProvisioningServerOTP: "SampleProvisioningServerOTP", - - ConfigurationServerFQDN: "SampleConfigurationServerFQDN", - - PasswordModel: 1, - - DhcpDNSSuffix: "SampleDhcpDNSSuffix", - - TrustedDNSSuffix: "SampleTrustedDNSSuffix", + ProvisioningServerOTP: "SampleProvisioningServerOTP", + ConfigurationServerFQDN: "SampleConfigurationServerFQDN", + PasswordModel: 1, + DhcpDNSSuffix: "SampleDhcpDNSSuffix", + TrustedDNSSuffix: "SampleTrustedDNSSuffix", } responses = append(responses, response) tests := []test{ { - name: "success", - + name: "success", action: 0, - manMock: func(man *MockWSMAN, man2 *MockManagement) { man.EXPECT(). SetupWsmanClient(gomock.Any(), false, true). @@ -104,41 +88,53 @@ func TestGetVersion(t *testing.T) { GetSetupAndConfiguration(). Return(responses, nil) }, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(device, nil) }, - - res: map[string]interface{}{"AMT_SetupAndConfigurationService": map[string]interface{}{"response": setupandconfiguration.SetupAndConfigurationServiceResponse{XMLName: xml.Name{Space: "", Local: "AMT_SetupAndConfigurationService"}, RequestedState: 1, EnabledState: 1, ElementName: "SampleElementName", SystemCreationClassName: "SampleSystemCreationClassName", SystemName: "SampleSystemName", CreationClassName: "SampleCreationClassName", Name: "SampleName", ProvisioningMode: 1, ProvisioningState: 1, ZeroTouchConfigurationEnabled: true, ProvisioningServerOTP: "SampleProvisioningServerOTP", ConfigurationServerFQDN: "SampleConfigurationServerFQDN", PasswordModel: 1, DhcpDNSSuffix: "SampleDhcpDNSSuffix", TrustedDNSSuffix: "SampleTrustedDNSSuffix"}}, "CIM_SoftwareIdentity": map[string]interface{}{"responses": []software.SoftwareIdentity{}}}, - + res: map[string]interface{}{ + "AMT_SetupAndConfigurationService": map[string]interface{}{ + "response": setupandconfiguration.SetupAndConfigurationServiceResponse{ + XMLName: xml.Name{Space: "", Local: "AMT_SetupAndConfigurationService"}, + RequestedState: 1, + EnabledState: 1, + ElementName: "SampleElementName", + SystemCreationClassName: "SampleSystemCreationClassName", + SystemName: "SampleSystemName", + CreationClassName: "SampleCreationClassName", + Name: "SampleName", + ProvisioningMode: 1, + ProvisioningState: 1, + ZeroTouchConfigurationEnabled: true, + ProvisioningServerOTP: "SampleProvisioningServerOTP", + ConfigurationServerFQDN: "SampleConfigurationServerFQDN", + PasswordModel: 1, + DhcpDNSSuffix: "SampleDhcpDNSSuffix", + TrustedDNSSuffix: "SampleTrustedDNSSuffix", + }, + }, + "CIM_SoftwareIdentity": map[string]interface{}{ + "responses": []software.SoftwareIdentity{}, + }, + }, err: nil, }, - { - name: "GetById fails", - - action: 0, - + name: "GetById fails", + action: 0, manMock: func(_ *MockWSMAN, _ *MockManagement) {}, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(nil, ErrGeneral) }, - res: map[string]interface{}(nil), - err: devices.ErrDatabase, }, - { - name: "GetAMTVersion fails", - + name: "GetAMTVersion fails", action: 0, - manMock: func(man *MockWSMAN, man2 *MockManagement) { man.EXPECT(). SetupWsmanClient(gomock.Any(), false, true). @@ -147,23 +143,17 @@ func TestGetVersion(t *testing.T) { GetAMTVersion(). Return(softwares, ErrGeneral) }, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(device, nil) }, - res: map[string]interface{}(nil), - err: ErrGeneral, }, - { - name: "GetSetupAndConfiguration fails", - + name: "GetSetupAndConfiguration fails", action: 0, - manMock: func(man *MockWSMAN, man2 *MockManagement) { man.EXPECT(). SetupWsmanClient(gomock.Any(), false, true). @@ -176,15 +166,12 @@ func TestGetVersion(t *testing.T) { GetSetupAndConfiguration(). Return(responses, ErrGeneral) }, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(device, nil) }, - res: map[string]interface{}(nil), - err: ErrGeneral, }, } @@ -214,17 +201,14 @@ func TestGetFeatures(t *testing.T) { t.Parallel() device := &entity.Device{ - GUID: "device-guid-123", - + GUID: "device-guid-123", TenantID: "tenant-id-456", } tests := []test{ { - name: "success", - + name: "success", action: 0, - manMock: func(man *MockWSMAN, man2 *MockManagement) { man.EXPECT(). SetupWsmanClient(gomock.Any(), false, true). @@ -233,41 +217,29 @@ func TestGetFeatures(t *testing.T) { GetFeatures(). Return(dto.Features{}, nil) }, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(device, nil) }, - res: dto.Features{}, - err: nil, }, - { - name: "GetById fails", - - action: 0, - + name: "GetById fails", + action: 0, manMock: func(_ *MockWSMAN, _ *MockManagement) {}, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(nil, ErrGeneral) }, - res: dto.Features{}, - err: devices.ErrDatabase, }, - { - name: "GetFeatures fails", - + name: "GetFeatures fails", action: 0, - manMock: func(man *MockWSMAN, man2 *MockManagement) { man.EXPECT(). SetupWsmanClient(gomock.Any(), false, true). @@ -276,15 +248,12 @@ func TestGetFeatures(t *testing.T) { GetFeatures(). Return(dto.Features{}, ErrGeneral) }, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(device, nil) }, - res: dto.Features{}, - err: ErrGeneral, }, } @@ -314,27 +283,21 @@ func TestSetFeatures(t *testing.T) { t.Parallel() device := &entity.Device{ - GUID: "device-guid-123", - + GUID: "device-guid-123", TenantID: "tenant-id-456", } featureSet := dto.Features{ UserConsent: "kvm", - - EnableSOL: true, - - EnableIDER: true, - - EnableKVM: true, + EnableSOL: true, + EnableIDER: true, + EnableKVM: true, } tests := []test{ { - name: "success", - + name: "success", action: 0, - manMock: func(man *MockWSMAN, man2 *MockManagement) { man.EXPECT(). SetupWsmanClient(gomock.Any(), false, true). @@ -343,41 +306,29 @@ func TestSetFeatures(t *testing.T) { SetFeatures(featureSet). Return(featureSet, nil) }, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(device, nil) }, - res: featureSet, - err: nil, }, - { - name: "GetById fails", - - action: 0, - + name: "GetById fails", + action: 0, manMock: func(_ *MockWSMAN, _ *MockManagement) {}, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(nil, ErrGeneral) }, - res: featureSet, - err: devices.ErrDatabase, }, - { - name: "GetFeatures fails", - + name: "GetFeatures fails", action: 0, - manMock: func(man *MockWSMAN, man2 *MockManagement) { man.EXPECT(). SetupWsmanClient(gomock.Any(), false, true). @@ -386,15 +337,12 @@ func TestSetFeatures(t *testing.T) { SetFeatures(featureSet). Return(featureSet, ErrGeneral) }, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(device, nil) }, - res: featureSet, - err: ErrGeneral, }, } @@ -424,17 +372,14 @@ func TestGetHardwareInfo(t *testing.T) { t.Parallel() device := &entity.Device{ - GUID: "device-guid-123", - + GUID: "device-guid-123", TenantID: "tenant-id-456", } tests := []test{ { - name: "success", - + name: "success", action: 0, - manMock: func(man *MockWSMAN, man2 *MockManagement) { man.EXPECT(). SetupWsmanClient(gomock.Any(), false, true). @@ -443,41 +388,29 @@ func TestGetHardwareInfo(t *testing.T) { GetHardwareInfo(). Return(gomock.Any(), nil) }, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(device, nil) }, - res: gomock.Any(), - err: nil, }, - { - name: "GetById fails", - - action: 0, - + name: "GetById fails", + action: 0, manMock: func(_ *MockWSMAN, _ *MockManagement) {}, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(nil, ErrGeneral) }, - res: nil, - err: devices.ErrDatabase, }, - { - name: "GetFeatures fails", - + name: "GetFeatures fails", action: 0, - manMock: func(man *MockWSMAN, man2 *MockManagement) { man.EXPECT(). SetupWsmanClient(gomock.Any(), false, true). @@ -486,15 +419,12 @@ func TestGetHardwareInfo(t *testing.T) { GetHardwareInfo(). Return(nil, ErrGeneral) }, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(device, nil) }, - res: nil, - err: ErrGeneral, }, } @@ -514,7 +444,6 @@ func TestGetHardwareInfo(t *testing.T) { res, err := useCase.GetHardwareInfo(context.Background(), device.GUID) require.Equal(t, tc.res, res) - require.IsType(t, tc.err, err) }) } @@ -524,17 +453,13 @@ func TestGetAuditLog(t *testing.T) { t.Parallel() device := &entity.Device{ - GUID: "device-guid-123", - - TenantID: "tenant-id-456", + GUID: "device-guid-123", TenantID: "tenant-id-456", } tests := []test{ { - name: "success", - + name: "success", action: 0, - manMock: func(man *MockWSMAN, man2 *MockManagement) { man.EXPECT(). SetupWsmanClient(gomock.Any(), false, true). @@ -543,41 +468,32 @@ func TestGetAuditLog(t *testing.T) { GetAuditLog(1). Return(auditlog.Response{}, nil) }, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(device, nil) }, - res: dto.AuditLog{}, - err: nil, }, - { - name: "GetById fails", - - action: 0, - + name: "GetById fails", + action: 0, manMock: func(_ *MockWSMAN, _ *MockManagement) {}, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(nil, ErrGeneral) }, - - res: dto.AuditLog{TotalCount: 0, Records: nil}, - + res: dto.AuditLog{ + TotalCount: 0, + Records: nil, + }, err: devices.ErrDatabase, }, - { - name: "GetFeatures fails", - + name: "GetFeatures fails", action: 0, - manMock: func(man *MockWSMAN, man2 *MockManagement) { man.EXPECT(). SetupWsmanClient(gomock.Any(), false, true). @@ -586,15 +502,12 @@ func TestGetAuditLog(t *testing.T) { GetAuditLog(1). Return(auditlog.Response{}, ErrGeneral) }, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(device, nil) }, - res: dto.AuditLog{TotalCount: 0, Records: nil}, - err: ErrGeneral, }, } @@ -614,7 +527,6 @@ func TestGetAuditLog(t *testing.T) { res, err := useCase.GetAuditLog(context.Background(), 1, device.GUID) require.Equal(t, tc.res, res) - require.IsType(t, tc.err, err) }) } @@ -624,17 +536,13 @@ func TestGetEventLog(t *testing.T) { t.Parallel() device := &entity.Device{ - GUID: "device-guid-123", - - TenantID: "tenant-id-456", + GUID: "device-guid-123", TenantID: "tenant-id-456", } tests := []test{ { - name: "success", - + name: "success", action: 0, - manMock: func(man *MockWSMAN, man2 *MockManagement) { man.EXPECT(). SetupWsmanClient(gomock.Any(), false, true). @@ -643,41 +551,29 @@ func TestGetEventLog(t *testing.T) { GetEventLog(). Return(messagelog.GetRecordsResponse{}, nil) }, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(device, nil) }, - res: []dto.EventLog{}, - err: nil, }, - { - name: "GetById fails", - - action: 0, - + name: "GetById fails", + action: 0, manMock: func(_ *MockWSMAN, _ *MockManagement) {}, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(nil, ErrGeneral) }, - res: []dto.EventLog(nil), - err: devices.ErrDatabase, }, - { - name: "GetFeatures fails", - + name: "GetFeatures fails", action: 0, - manMock: func(man *MockWSMAN, man2 *MockManagement) { man.EXPECT(). SetupWsmanClient(gomock.Any(), false, true). @@ -686,15 +582,12 @@ func TestGetEventLog(t *testing.T) { GetEventLog(). Return(messagelog.GetRecordsResponse{}, ErrGeneral) }, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(device, nil) }, - res: []dto.EventLog(nil), - err: ErrGeneral, }, } @@ -714,7 +607,6 @@ func TestGetEventLog(t *testing.T) { res, err := useCase.GetEventLog(context.Background(), device.GUID) require.Equal(t, tc.res, res) - require.IsType(t, tc.err, err) }) } @@ -724,17 +616,13 @@ func TestGetGeneralSettings(t *testing.T) { t.Parallel() device := &entity.Device{ - GUID: "device-guid-123", - - TenantID: "tenant-id-456", + GUID: "device-guid-123", TenantID: "tenant-id-456", } tests := []test{ { - name: "success", - + name: "success", action: 0, - manMock: func(man *MockWSMAN, man2 *MockManagement) { man.EXPECT(). SetupWsmanClient(gomock.Any(), false, true). @@ -743,41 +631,29 @@ func TestGetGeneralSettings(t *testing.T) { GetGeneralSettings(). Return(gomock.Any(), nil) }, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(device, nil) }, - res: map[string]interface{}{"Body": gomock.Any()}, - err: nil, }, - { - name: "GetById fails", - - action: 0, - + name: "GetById fails", + action: 0, manMock: func(_ *MockWSMAN, _ *MockManagement) {}, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(nil, ErrGeneral) }, - res: nil, - err: devices.ErrDatabase, }, - { - name: "GetFeatures fails", - + name: "GetFeatures fails", action: 0, - manMock: func(man *MockWSMAN, man2 *MockManagement) { man.EXPECT(). SetupWsmanClient(gomock.Any(), false, true). @@ -786,15 +662,12 @@ func TestGetGeneralSettings(t *testing.T) { GetGeneralSettings(). Return(nil, ErrGeneral) }, - repoMock: func(repo *MockRepository) { repo.EXPECT(). GetByID(context.Background(), device.GUID, ""). Return(device, nil) }, - res: nil, - err: ErrGeneral, }, } @@ -814,7 +687,6 @@ func TestGetGeneralSettings(t *testing.T) { res, err := useCase.GetGeneralSettings(context.Background(), device.GUID) require.Equal(t, tc.res, res) - require.IsType(t, tc.err, err) }) } diff --git a/internal/usecase/devices/interfaces.go b/internal/usecase/devices/interfaces.go index 5ef994b4..6b46db9b 100644 --- a/internal/usecase/devices/interfaces.go +++ b/internal/usecase/devices/interfaces.go @@ -16,6 +16,7 @@ type ( WSMAN interface { SetupWsmanClient(device dto.Device, isRedirection, logMessages bool) wsmanAPI.Management DestroyWsmanClient(device dto.Device) + Worker() } Redirection interface { diff --git a/internal/usecase/devices/mocks_test.go b/internal/usecase/devices/mocks_test.go index f52fc4b0..3ee1eadb 100644 --- a/internal/usecase/devices/mocks_test.go +++ b/internal/usecase/devices/mocks_test.go @@ -72,6 +72,18 @@ func (mr *MockWSMANMockRecorder) SetupWsmanClient(device, isRedirection, logMess return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetupWsmanClient", reflect.TypeOf((*MockWSMAN)(nil).SetupWsmanClient), device, isRedirection, logMessages) } +// Worker mocks base method. +func (m *MockWSMAN) Worker() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Worker") +} + +// Worker indicates an expected call of Worker. +func (mr *MockWSMANMockRecorder) Worker() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Worker", reflect.TypeOf((*MockWSMAN)(nil).Worker)) +} + // MockRedirection is a mock of Redirection interface. type MockRedirection struct { ctrl *gomock.Controller diff --git a/internal/usecase/devices/network_test.go b/internal/usecase/devices/network_test.go index 8cdccb56..dc9326be 100644 --- a/internal/usecase/devices/network_test.go +++ b/internal/usecase/devices/network_test.go @@ -20,6 +20,8 @@ func initNetworkTest(t *testing.T) (*devices.UseCase, *MockWSMAN, *MockManagemen repo := NewMockRepository(mockCtl) wsmanMock := NewMockWSMAN(mockCtl) + wsmanMock.EXPECT().Worker().Return().AnyTimes() + management := NewMockManagement(mockCtl) log := logger.New("error") u := devices.New(repo, wsmanMock, NewMockRedirection(mockCtl), log) diff --git a/internal/usecase/devices/power_test.go b/internal/usecase/devices/power_test.go index 6f75a98a..6b50ade3 100644 --- a/internal/usecase/devices/power_test.go +++ b/internal/usecase/devices/power_test.go @@ -39,6 +39,8 @@ func initPowerTest(t *testing.T) (*devices.UseCase, *MockWSMAN, *MockManagement, repo := NewMockRepository(mockCtl) wsmanMock := NewMockWSMAN(mockCtl) + wsmanMock.EXPECT().Worker().Return().AnyTimes() + managementMock := NewMockManagement(mockCtl) log := logger.New("error") u := devices.New(repo, wsmanMock, NewMockRedirection(mockCtl), log) diff --git a/internal/usecase/devices/redirection_wsman_test.go b/internal/usecase/devices/redirection_wsman_test.go index d70f9442..f8193ca4 100644 --- a/internal/usecase/devices/redirection_wsman_test.go +++ b/internal/usecase/devices/redirection_wsman_test.go @@ -55,6 +55,12 @@ func (m *MockClient) Listen() ([]byte, error) { return args.Get(0).([]byte), args.Error(1) } +func (m *MockClient) IsAuthenticated() bool { + args := m.Called() + + return args.Get(0).(bool) +} + type wsmanTest struct { name string diff --git a/internal/usecase/devices/repo_test.go b/internal/usecase/devices/repo_test.go index ec70a442..f651fe12 100644 --- a/internal/usecase/devices/repo_test.go +++ b/internal/usecase/devices/repo_test.go @@ -31,11 +31,13 @@ func devicesTest(t *testing.T) (*devices.UseCase, *MockRepository, *MockWSMAN) { defer mockCtl.Finish() repo := NewMockRepository(mockCtl) - management := NewMockWSMAN(mockCtl) + wsmanMock := NewMockWSMAN(mockCtl) + wsmanMock.EXPECT().Worker().Return().AnyTimes() + log := logger.New("error") - u := devices.New(repo, management, NewMockRedirection(mockCtl), log) + u := devices.New(repo, wsmanMock, NewMockRedirection(mockCtl), log) - return u, repo, management + return u, repo, wsmanMock } func TestGetCount(t *testing.T) { diff --git a/internal/usecase/devices/usecase.go b/internal/usecase/devices/usecase.go index f0697b82..bfcd90df 100644 --- a/internal/usecase/devices/usecase.go +++ b/internal/usecase/devices/usecase.go @@ -46,13 +46,17 @@ var ErrAMT = AMTError{Console: consoleerrors.CreateConsoleError("DevicesUseCase" // New -. func New(r Repository, d WSMAN, redirection Redirection, log logger.Interface) *UseCase { - return &UseCase{ + uc := &UseCase{ repo: r, device: d, redirection: redirection, redirConnections: make(map[string]*DeviceConnection), log: log, } + // start up the worker + go d.Worker() + + return uc } // convert dto.Device to entity.Device. diff --git a/internal/usecase/devices/wsman/message.go b/internal/usecase/devices/wsman/message.go index 75758cc1..1d5e6c4b 100644 --- a/internal/usecase/devices/wsman/message.go +++ b/internal/usecase/devices/wsman/message.go @@ -56,10 +56,17 @@ import ( "github.com/open-amt-cloud-toolkit/console/pkg/logger" ) +const deviceCallBuffer = 100 + var ( - connections = make(map[string]*ConnectionEntry) - connectionsMu sync.Mutex - expireAfter = 5 * time.Minute // Set the expiration duration as needed + connections = make(map[string]*ConnectionEntry) + connectionsMu sync.Mutex + waitForAuthTickTime = 1 * time.Second + queueTickTime = 500 * time.Millisecond + expireAfter = 30 * time.Second // expire the stored connection after 30 seconds + waitForAuth = 3 * time.Second // wait for 3 seconds for the connection to authenticate, prevents multiple api calls trying to auth at the same time + requestQueue = make(chan func(), deviceCallBuffer) // Buffered channel to queue requests + shutdownSignal = make(chan struct{}) ) type ConnectionEntry struct { @@ -84,7 +91,30 @@ func (g GoWSMANMessages) DestroyWsmanClient(device dto.Device) { } } +func (g GoWSMANMessages) Worker() { + for { + select { + case request := <-requestQueue: + request() + time.Sleep(queueTickTime) + case <-shutdownSignal: + return + } + } +} + func (g GoWSMANMessages) SetupWsmanClient(device dto.Device, isRedirection, logAMTMessages bool) Management { + resultChan := make(chan *ConnectionEntry) + + // Queue the request + requestQueue <- func() { + resultChan <- g.setupWsmanClientInternal(device, isRedirection, logAMTMessages) + } + + return <-resultChan +} + +func (g GoWSMANMessages) setupWsmanClientInternal(device dto.Device, isRedirection, logAMTMessages bool) *ConnectionEntry { clientParams := client.Parameters{ Target: device.Hostname, Username: device.Username, @@ -96,32 +126,62 @@ func (g GoWSMANMessages) SetupWsmanClient(device dto.Device, isRedirection, logA IsRedirection: isRedirection, } - connectionsMu.Lock() - defer connectionsMu.Unlock() + timer := time.AfterFunc(expireAfter, func() { + removeConnection(device.GUID) + }) if entry, ok := connections[device.GUID]; ok { - entry.Timer.Stop() // Stop the previous timer - entry.Timer = time.AfterFunc(expireAfter, func() { - removeConnection(device.GUID) - }) - } else { - wsmanMsgs := wsman.NewMessages(clientParams) - timer := time.AfterFunc(expireAfter, func() { - removeConnection(device.GUID) - }) - connections[device.GUID] = &ConnectionEntry{ - WsmanMessages: wsmanMsgs, - Timer: timer, + if entry.WsmanMessages.Client.IsAuthenticated() { + entry.Timer.Stop() // Stop the previous timer + entry.Timer = time.AfterFunc(expireAfter, func() { + removeConnection(device.GUID) + }) + + return connections[device.GUID] + } + + ticker := time.NewTicker(waitForAuthTickTime) + + defer ticker.Stop() + + timeout := time.After(waitForAuth) + + for { + select { + case <-ticker.C: + if entry.WsmanMessages.Client.IsAuthenticated() { + // Your logic when the function check is successful + return connections[device.GUID] + } + case <-timeout: + connectionsMu.Lock() + connections[device.GUID] = &ConnectionEntry{ + WsmanMessages: wsman.NewMessages(clientParams), + Timer: timer, + } + connectionsMu.Unlock() + + return connections[device.GUID] + } } } + wsmanMsgs := wsman.NewMessages(clientParams) + + connectionsMu.Lock() + connections[device.GUID] = &ConnectionEntry{ + WsmanMessages: wsmanMsgs, + Timer: timer, + } + connections[device.GUID].WsmanMessages.Client.IsAuthenticated() + connectionsMu.Unlock() + return connections[device.GUID] } func removeConnection(guid string) { connectionsMu.Lock() defer connectionsMu.Unlock() - delete(connections, guid) }