From 46e6b32079cd44e2908c94f414ec7a67bb322505 Mon Sep 17 00:00:00 2001 From: Antonia Avramova Date: Tue, 28 Feb 2023 17:04:32 +0200 Subject: [PATCH 1/8] Common logic for device resources Signed-off-by: Antonia Avramova --- integration/util/registry.go | 286 +++++++++++++++++++++++++++++++++++ integration/util/web.go | 29 +++- 2 files changed, 312 insertions(+), 3 deletions(-) create mode 100644 integration/util/registry.go diff --git a/integration/util/registry.go b/integration/util/registry.go new file mode 100644 index 00000000..13904166 --- /dev/null +++ b/integration/util/registry.go @@ -0,0 +1,286 @@ +// Copyright (c) 2023 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 + +package util + +import ( + "encoding/json" + "fmt" + "net/http" + "os" + "os/exec" + "strings" +) + +const ( + Indent = " " + + deletedTemplate = "%s '%s' deleted\n" + done = "... done" + + deviceJSON = `{"authorities":["auto-provisioning-enabled"]}` + + authJSON = `[{ + "type": "hashed-password", + "auth-id": "%s", + "secrets": [{ + "pwd-plain": "%s" + }] + }]` + + thingJSON = `{"policyId": "%s"}` + + configDefaultMode = 0666 + + systemctl = "systemctl" +) + +type Resource struct { + url string + + method string + body string + + user string + pass string + + delete bool +} + +type BootstrapConfiguration struct { + LogFile string `json:"logFile"` + PostBootstrapFile string `json:"postBootstrapFile"` + PostBootstrapScript []string `json:"postBootstrapScript"` + CaCert string `json:"caCert"` + Address string `json:"address"` + TenantID string `json:"tenantId"` + DeviceID string `json:"deviceId"` + AuthID string `json:"authId"` + Password string `json:"password"` +} + +type ConnectorConfiguration struct { + CaCert string `json:"caCert"` + LogFile string `json:"logFile"` + Address string `json:"address"` + TenantID string `json:"tenantId"` + DeviceID string `json:"deviceId"` + AuthID string `json:"authId"` + Password string `json:"password"` +} + +// CreateDeviceResources creates device resources. +func CreateDeviceResources(newDeviceId string, resources []*Resource, + tenantID, policyID, password, registryAPI, registryAPIUsername, registryAPIPassword string, + cfg *TestConfiguration) (*Resource, []*Resource) { + + devicePath := tenantID + "/" + newDeviceId + deviceResource := &Resource{url: registryAPI + "/devices/" + devicePath, method: http.MethodPost, + body: deviceJSON, user: registryAPIUsername, pass: registryAPIPassword, delete: true} + resources = append(resources, deviceResource) + + authID := strings.ReplaceAll(newDeviceId, ":", "_") + auth := fmt.Sprintf(authJSON, authID, password) + resources = append(resources, &Resource{url: registryAPI + "/credentials/" + devicePath, method: http.MethodPut, + body: auth, user: registryAPIUsername, pass: registryAPIPassword, delete: false}) + + thingURL := GetThingURL(cfg.DigitalTwinAPIAddress, newDeviceId) + thing := fmt.Sprintf(thingJSON, policyID) + resources = append(resources, &Resource{url: thingURL, method: http.MethodPut, + body: thing, user: cfg.DigitalTwinAPIUsername, pass: cfg.DigitalTwinAPIPassword, delete: true}) + return deviceResource, resources +} + +// WriteConfigFile writes interface data to the path file, creating it if necessary. +func WriteConfigFile(path string, cfg interface{}) error { + jsonContents, err := json.MarshalIndent(cfg, "", "\t") + if err != nil { + return fmt.Errorf("unable to marshal to json: %v", err) + } + + // Preserve the file mode if the file already exists + mode := getFileModeOrDefault(path, configDefaultMode) + err = os.WriteFile(path, jsonContents, mode) + if err != nil { + return fmt.Errorf("unable to save file %s: %v", path, err) + } + return nil +} + +func getFileModeOrDefault(path string, defaultMode os.FileMode) os.FileMode { + mode := defaultMode + fileInfo, err := os.Stat(path) + if err == nil { + mode = fileInfo.Mode() + } + return mode +} + +// DeleteResources deletes all given resources and all related devices. +func DeleteResources(cfg *TestConfiguration, resources []*Resource, deviceId, url, user, pass string) bool { + ok := deleteRelatedDevices(cfg, deviceId, url, user, pass) + fmt.Println("deleting initially created things...") + // Delete in reverse order of creation + for i := len(resources) - 1; i >= 0; i-- { + r := resources[i] + + if !r.delete { + continue + } + + if _, err := SendDeviceRegistryRequest(nil, http.MethodDelete, r.url, r.user, r.pass); err != nil { + ok = false + fmt.Printf("%s unable to delete '%s', error: %v\n", Indent, r.url, err) + } else { + fmt.Printf(deletedTemplate, Indent, r.url) + } + } + return ok +} + +func deleteRelatedDevices(cfg *TestConfiguration, viaDeviceID, url, user, pass string) bool { + devicesVia, ok := findDeviceRegistryDevicesVia(viaDeviceID, url, user, pass) + // Digital Twin API things are created after Device Registry devices, so delete them first + fmt.Println("deleting automatically created things...") + if !deleteDigitalTwinThings(cfg, devicesVia) { + ok = false + } + // Then delete Device Registry devices + fmt.Println("deleting automatically created devices...") + if !deleteRegistryDevices(devicesVia, url, user, pass) { + ok = false + } + return ok +} + +func findDeviceRegistryDevicesVia(viaDeviceID, url, user, pass string) ([]string, bool) { + var devicesVia []string + ok := true + + type registryDevice struct { + ID string `json:"id"` + Via []string `json:"via"` + } + + type registryDevices struct { + Devices []*registryDevice `json:"result"` + } + + contains := func(where []string, what string) bool { + for _, item := range where { + if item == what { + return true + } + } + return false + } + + devicesJSON, err := SendDeviceRegistryRequest(nil, http.MethodGet, url, user, pass) + if err != nil { + ok = false + fmt.Printf("unable to list devices from the device registry, error: %v\n", err) + } else { + devices := ®istryDevices{} + err = json.Unmarshal(devicesJSON, devices) + if err != nil { + ok = false + fmt.Printf("unable to parse devices JSON returned from the device registry, error: %v\n", err) + devices.Devices = nil + } + for _, device := range devices.Devices { + if contains(device.Via, viaDeviceID) { + devicesVia = append(devicesVia, device.ID) + } + } + } + + return devicesVia, ok +} + +func deleteDigitalTwinThings(cfg *TestConfiguration, things []string) bool { + ok := true + for _, thingID := range things { + url := GetThingURL(cfg.DigitalTwinAPIAddress, thingID) + _, err := SendDigitalTwinRequest(cfg, http.MethodDelete, url, nil) + if err != nil { + ok = false + fmt.Printf("error deleting thing: %v\n", err) + } else { + fmt.Printf(deletedTemplate, Indent, url) + } + } + return ok +} + +func deleteRegistryDevices(devices []string, tenantURL, user, pass string) bool { + ok := true + for _, device := range devices { + url := tenantURL + device + if _, err := SendDeviceRegistryRequest(nil, http.MethodDelete, url, user, pass); err != nil { + ok = false + fmt.Printf("error deleting device: %v\n", err) + } else { + fmt.Printf(deletedTemplate, Indent, url) + } + } + return ok +} + +// RestartService restarts the service with given name +func RestartService(service string) bool { + fmt.Printf("restarting %s...", service) + cmd := exec.Command(systemctl, "restart", service) + stdout, err := cmd.Output() + if err != nil { + fmt.Printf("error restarting %s: %v", service, err) + return false + } + fmt.Println(string(stdout)) + fmt.Println(done) + return true +} + +// StopService stops the service with given name +func StopService(service string) bool { + fmt.Printf("stopping %s...", service) + cmd := exec.Command(systemctl, "stop", service) + stdout, err := cmd.Output() + if err != nil { + fmt.Printf("error stopping %s: %v", service, err) + return false + } + fmt.Println(string(stdout)) + fmt.Println(done) + return true +} + +// CopyFile copies source file to the destination. +func CopyFile(src, dst string) error { + data, err := os.ReadFile(src) + if err != nil { + return err + } + // If the destination file exists, preserve its file mode. + // If the destination file doesn't exist, use the file mode of the source file. + srcMode := getFileModeOrDefault(src, configDefaultMode) + dstMode := getFileModeOrDefault(dst, srcMode) + return os.WriteFile(dst, data, dstMode) +} + +// DeleteFile removes the named file or directory. +func DeleteFile(path string) bool { + if err := os.Remove(path); err != nil { + fmt.Printf("unable to delete file %s, error: %v", path, err) + return false + } + return true +} diff --git a/integration/util/web.go b/integration/util/web.go index ab761262..1307b154 100644 --- a/integration/util/web.go +++ b/integration/util/web.go @@ -60,8 +60,25 @@ const ( StopSendMessages UnsubscribeEventType = "STOP-SEND-MESSAGES" ) -// SendDigitalTwinRequest sends а new HTTP request to the Ditto REST API +// SendDigitalTwinRequest sends a new HTTP request to the Ditto REST API func SendDigitalTwinRequest(cfg *TestConfiguration, method string, url string, body interface{}) ([]byte, error) { + req, err := createRequest(make([]byte, 0), body, method, url, cfg.DigitalTwinAPIUsername, cfg.DigitalTwinAPIPassword) + if err != nil { + return nil, err + } + return sendRequest(req, method, url) +} + +// SendDeviceRegistryRequest sends a new HTTP request to the Ditto API +func SendDeviceRegistryRequest(payload []byte, method string, url string, username string, password string) ([]byte, error) { + req, err := createRequest(payload, nil, method, url, username, password) + if err != nil { + return nil, err + } + return sendRequest(req, method, url) +} + +func createRequest(payload []byte, body interface{}, method, url, username, password string) (*http.Request, error) { var reqBody io.Reader if body != nil { @@ -70,6 +87,8 @@ func SendDigitalTwinRequest(cfg *TestConfiguration, method string, url string, b return nil, err } reqBody = bytes.NewBuffer(jsonValue) + } else { + reqBody = bytes.NewBuffer(payload) } req, err := http.NewRequest(method, url, reqBody) @@ -77,14 +96,18 @@ func SendDigitalTwinRequest(cfg *TestConfiguration, method string, url string, b return nil, err } + req.Header.Add("Content-Type", "application/json") if body != nil { correlationID := uuid.New().String() - req.Header.Add("Content-Type", "application/json") req.Header.Add("correlation-id", correlationID) req.Header.Add("response-required", "true") } - req.SetBasicAuth(cfg.DigitalTwinAPIUsername, cfg.DigitalTwinAPIPassword) + req.SetBasicAuth(username, password) + return req, nil +} + +func sendRequest(req *http.Request, method string, url string) ([]byte, error) { resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err From 4cf7574fb2c1cca36fc2bd8dff9a960d2e817569 Mon Sep 17 00:00:00 2001 From: Antonia Avramova Date: Mon, 6 Mar 2023 12:13:51 +0200 Subject: [PATCH 2/8] Common logic for device resources Signed-off-by: Antonia Avramova --- integration/util/registry.go | 112 ++++++++++------------------------- 1 file changed, 31 insertions(+), 81 deletions(-) diff --git a/integration/util/registry.go b/integration/util/registry.go index 13904166..5b40130a 100644 --- a/integration/util/registry.go +++ b/integration/util/registry.go @@ -22,11 +22,6 @@ import ( ) const ( - Indent = " " - - deletedTemplate = "%s '%s' deleted\n" - done = "... done" - deviceJSON = `{"authorities":["auto-provisioning-enabled"]}` authJSON = `[{ @@ -79,10 +74,11 @@ type ConnectorConfiguration struct { } // CreateDeviceResources creates device resources. -func CreateDeviceResources(newDeviceId string, resources []*Resource, - tenantID, policyID, password, registryAPI, registryAPIUsername, registryAPIPassword string, +func CreateDeviceResources(newDeviceId, tenantID, policyID, password, registryAPI, + registryAPIUsername, registryAPIPassword string, cfg *TestConfiguration) (*Resource, []*Resource) { + resources := make([]*Resource, 0, 3) devicePath := tenantID + "/" + newDeviceId deviceResource := &Resource{url: registryAPI + "/devices/" + devicePath, method: http.MethodPost, body: deviceJSON, user: registryAPIUsername, pass: registryAPIPassword, delete: true} @@ -126,9 +122,10 @@ func getFileModeOrDefault(path string, defaultMode os.FileMode) os.FileMode { } // DeleteResources deletes all given resources and all related devices. -func DeleteResources(cfg *TestConfiguration, resources []*Resource, deviceId, url, user, pass string) bool { - ok := deleteRelatedDevices(cfg, deviceId, url, user, pass) - fmt.Println("deleting initially created things...") +func DeleteResources(cfg *TestConfiguration, resources []*Resource, deviceId, url, user, pass string) error { + if err := deleteRelatedDevices(cfg, deviceId, url, user, pass); err != nil { + return err + } // Delete in reverse order of creation for i := len(resources) - 1; i >= 0; i-- { r := resources[i] @@ -138,33 +135,27 @@ func DeleteResources(cfg *TestConfiguration, resources []*Resource, deviceId, ur } if _, err := SendDeviceRegistryRequest(nil, http.MethodDelete, r.url, r.user, r.pass); err != nil { - ok = false - fmt.Printf("%s unable to delete '%s', error: %v\n", Indent, r.url, err) - } else { - fmt.Printf(deletedTemplate, Indent, r.url) + return err } } - return ok + return nil } -func deleteRelatedDevices(cfg *TestConfiguration, viaDeviceID, url, user, pass string) bool { - devicesVia, ok := findDeviceRegistryDevicesVia(viaDeviceID, url, user, pass) +func deleteRelatedDevices(cfg *TestConfiguration, viaDeviceID, url, user, pass string) error { + devicesVia, err := findDeviceRegistryDevicesVia(viaDeviceID, url, user, pass) + if err != nil { + return err + } // Digital Twin API things are created after Device Registry devices, so delete them first - fmt.Println("deleting automatically created things...") - if !deleteDigitalTwinThings(cfg, devicesVia) { - ok = false + if err = deleteDigitalTwinThings(cfg, devicesVia); err != nil { + return err } // Then delete Device Registry devices - fmt.Println("deleting automatically created devices...") - if !deleteRegistryDevices(devicesVia, url, user, pass) { - ok = false - } - return ok + return deleteRegistryDevices(devicesVia, url, user, pass) } -func findDeviceRegistryDevicesVia(viaDeviceID, url, user, pass string) ([]string, bool) { +func findDeviceRegistryDevicesVia(viaDeviceID, url, user, pass string) ([]string, error) { var devicesVia []string - ok := true type registryDevice struct { ID string `json:"id"` @@ -186,15 +177,13 @@ func findDeviceRegistryDevicesVia(viaDeviceID, url, user, pass string) ([]string devicesJSON, err := SendDeviceRegistryRequest(nil, http.MethodGet, url, user, pass) if err != nil { - ok = false - fmt.Printf("unable to list devices from the device registry, error: %v\n", err) + return devicesVia, err } else { devices := ®istryDevices{} err = json.Unmarshal(devicesJSON, devices) if err != nil { - ok = false - fmt.Printf("unable to parse devices JSON returned from the device registry, error: %v\n", err) devices.Devices = nil + return devicesVia, err } for _, device := range devices.Devices { if contains(device.Via, viaDeviceID) { @@ -203,64 +192,34 @@ func findDeviceRegistryDevicesVia(viaDeviceID, url, user, pass string) ([]string } } - return devicesVia, ok + return devicesVia, nil } -func deleteDigitalTwinThings(cfg *TestConfiguration, things []string) bool { - ok := true +func deleteDigitalTwinThings(cfg *TestConfiguration, things []string) error { for _, thingID := range things { url := GetThingURL(cfg.DigitalTwinAPIAddress, thingID) _, err := SendDigitalTwinRequest(cfg, http.MethodDelete, url, nil) if err != nil { - ok = false - fmt.Printf("error deleting thing: %v\n", err) - } else { - fmt.Printf(deletedTemplate, Indent, url) + return err } } - return ok + return nil } -func deleteRegistryDevices(devices []string, tenantURL, user, pass string) bool { - ok := true +func deleteRegistryDevices(devices []string, tenantURL, user, pass string) error { for _, device := range devices { url := tenantURL + device if _, err := SendDeviceRegistryRequest(nil, http.MethodDelete, url, user, pass); err != nil { - ok = false - fmt.Printf("error deleting device: %v\n", err) - } else { - fmt.Printf(deletedTemplate, Indent, url) + return err } } - return ok -} - -// RestartService restarts the service with given name -func RestartService(service string) bool { - fmt.Printf("restarting %s...", service) - cmd := exec.Command(systemctl, "restart", service) - stdout, err := cmd.Output() - if err != nil { - fmt.Printf("error restarting %s: %v", service, err) - return false - } - fmt.Println(string(stdout)) - fmt.Println(done) - return true + return nil } -// StopService stops the service with given name -func StopService(service string) bool { - fmt.Printf("stopping %s...", service) - cmd := exec.Command(systemctl, "stop", service) - stdout, err := cmd.Output() - if err != nil { - fmt.Printf("error stopping %s: %v", service, err) - return false - } - fmt.Println(string(stdout)) - fmt.Println(done) - return true +// ExecuteCommandToService executes command to the service with given name +func ExecuteCommandToService(command, service string) ([]byte, error) { + cmd := exec.Command(systemctl, command, service) + return cmd.Output() } // CopyFile copies source file to the destination. @@ -275,12 +234,3 @@ func CopyFile(src, dst string) error { dstMode := getFileModeOrDefault(dst, srcMode) return os.WriteFile(dst, data, dstMode) } - -// DeleteFile removes the named file or directory. -func DeleteFile(path string) bool { - if err := os.Remove(path); err != nil { - fmt.Printf("unable to delete file %s, error: %v", path, err) - return false - } - return true -} From 7a2ecca013e40f1af5b4fdafdc042d9732302623 Mon Sep 17 00:00:00 2001 From: Antonia Avramova Date: Tue, 7 Mar 2023 17:49:55 +0200 Subject: [PATCH 3/8] Common logic for device resources Signed-off-by: Antonia Avramova --- integration/util/registry.go | 96 +++++++++++++++++++++--------------- integration/util/web.go | 37 ++++++++------ 2 files changed, 79 insertions(+), 54 deletions(-) diff --git a/integration/util/registry.go b/integration/util/registry.go index 5b40130a..4312ec5c 100644 --- a/integration/util/registry.go +++ b/integration/util/registry.go @@ -24,14 +24,6 @@ import ( const ( deviceJSON = `{"authorities":["auto-provisioning-enabled"]}` - authJSON = `[{ - "type": "hashed-password", - "auth-id": "%s", - "secrets": [{ - "pwd-plain": "%s" - }] - }]` - thingJSON = `{"policyId": "%s"}` configDefaultMode = 0666 @@ -85,9 +77,8 @@ func CreateDeviceResources(newDeviceId, tenantID, policyID, password, registryAP resources = append(resources, deviceResource) authID := strings.ReplaceAll(newDeviceId, ":", "_") - auth := fmt.Sprintf(authJSON, authID, password) resources = append(resources, &Resource{url: registryAPI + "/credentials/" + devicePath, method: http.MethodPut, - body: auth, user: registryAPIUsername, pass: registryAPIPassword, delete: false}) + body: getCredentialsBody(authID, password), user: registryAPIUsername, pass: registryAPIPassword, delete: false}) thingURL := GetThingURL(cfg.DigitalTwinAPIAddress, newDeviceId) thing := fmt.Sprintf(thingJSON, policyID) @@ -96,6 +87,24 @@ func CreateDeviceResources(newDeviceId, tenantID, policyID, password, registryAP return deviceResource, resources } +func getCredentialsBody(authID, pass string) string { + type pwdPlain struct { + PwdPlain string `json:"pwd-plain"` + } + + type authStruct struct { + TypeStr string `json:"type"` + AuthId string `json:"auth-id"` + Secrets []pwdPlain `json:"secrets"` + } + pwds := []pwdPlain{pwdPlain{pass}} + + auth := authStruct{"hashed-password", authID, pwds} + authJson := []authStruct{auth} + data, _ := json.MarshalIndent(authJson, "", "\t") + return string(data) +} + // WriteConfigFile writes interface data to the path file, creating it if necessary. func WriteConfigFile(path string, cfg interface{}) error { jsonContents, err := json.MarshalIndent(cfg, "", "\t") @@ -104,28 +113,27 @@ func WriteConfigFile(path string, cfg interface{}) error { } // Preserve the file mode if the file already exists - mode := getFileModeOrDefault(path, configDefaultMode) - err = os.WriteFile(path, jsonContents, mode) + mode, err := getFileModeOrDefault(path, configDefaultMode) if err != nil { + return fmt.Errorf("unable to get file mode %s: %v", path, err) + } + if err = os.WriteFile(path, jsonContents, mode); err != nil { return fmt.Errorf("unable to save file %s: %v", path, err) } return nil } -func getFileModeOrDefault(path string, defaultMode os.FileMode) os.FileMode { - mode := defaultMode +func getFileModeOrDefault(path string, defaultMode os.FileMode) (os.FileMode, error) { fileInfo, err := os.Stat(path) - if err == nil { - mode = fileInfo.Mode() + if err != nil { + return defaultMode, err } - return mode + return fileInfo.Mode(), nil } // DeleteResources deletes all given resources and all related devices. -func DeleteResources(cfg *TestConfiguration, resources []*Resource, deviceId, url, user, pass string) error { - if err := deleteRelatedDevices(cfg, deviceId, url, user, pass); err != nil { - return err - } +func DeleteResources(cfg *TestConfiguration, resources []*Resource, deviceId, url, user, pass string) []error { + deleteErrors := deleteRelatedDevices(cfg, deviceId, url, user, pass) // Delete in reverse order of creation for i := len(resources) - 1; i >= 0; i-- { r := resources[i] @@ -135,23 +143,27 @@ func DeleteResources(cfg *TestConfiguration, resources []*Resource, deviceId, ur } if _, err := SendDeviceRegistryRequest(nil, http.MethodDelete, r.url, r.user, r.pass); err != nil { - return err + deleteErrors = append(deleteErrors, err) } } - return nil + return deleteErrors } -func deleteRelatedDevices(cfg *TestConfiguration, viaDeviceID, url, user, pass string) error { +func deleteRelatedDevices(cfg *TestConfiguration, viaDeviceID, url, user, pass string) []error { + var deleteErrors []error devicesVia, err := findDeviceRegistryDevicesVia(viaDeviceID, url, user, pass) if err != nil { - return err + deleteErrors = append(deleteErrors, err) } // Digital Twin API things are created after Device Registry devices, so delete them first - if err = deleteDigitalTwinThings(cfg, devicesVia); err != nil { - return err + if delErrors := deleteDigitalTwinThings(cfg, devicesVia); delErrors != nil { + deleteErrors = append(deleteErrors, delErrors...) } // Then delete Device Registry devices - return deleteRegistryDevices(devicesVia, url, user, pass) + if delErrors := deleteRegistryDevices(devicesVia, url, user, pass); delErrors != nil { + deleteErrors = append(deleteErrors, delErrors...) + } + return deleteErrors } func findDeviceRegistryDevicesVia(viaDeviceID, url, user, pass string) ([]string, error) { @@ -182,7 +194,6 @@ func findDeviceRegistryDevicesVia(viaDeviceID, url, user, pass string) ([]string devices := ®istryDevices{} err = json.Unmarshal(devicesJSON, devices) if err != nil { - devices.Devices = nil return devicesVia, err } for _, device := range devices.Devices { @@ -195,25 +206,26 @@ func findDeviceRegistryDevicesVia(viaDeviceID, url, user, pass string) ([]string return devicesVia, nil } -func deleteDigitalTwinThings(cfg *TestConfiguration, things []string) error { +func deleteDigitalTwinThings(cfg *TestConfiguration, things []string) []error { + var deleteErrors []error for _, thingID := range things { url := GetThingURL(cfg.DigitalTwinAPIAddress, thingID) - _, err := SendDigitalTwinRequest(cfg, http.MethodDelete, url, nil) - if err != nil { - return err + if _, err := SendDigitalTwinRequest(cfg, http.MethodDelete, url, nil); err != nil { + deleteErrors = append(deleteErrors, err) } } - return nil + return deleteErrors } -func deleteRegistryDevices(devices []string, tenantURL, user, pass string) error { +func deleteRegistryDevices(devices []string, tenantURL, user, pass string) []error { + var deleteErrors []error for _, device := range devices { url := tenantURL + device if _, err := SendDeviceRegistryRequest(nil, http.MethodDelete, url, user, pass); err != nil { - return err + deleteErrors = append(deleteErrors, err) } } - return nil + return deleteErrors } // ExecuteCommandToService executes command to the service with given name @@ -230,7 +242,13 @@ func CopyFile(src, dst string) error { } // If the destination file exists, preserve its file mode. // If the destination file doesn't exist, use the file mode of the source file. - srcMode := getFileModeOrDefault(src, configDefaultMode) - dstMode := getFileModeOrDefault(dst, srcMode) + srcMode, err := getFileModeOrDefault(src, configDefaultMode) + if err != nil { + return err + } + dstMode, err := getFileModeOrDefault(dst, srcMode) + if err != nil { + return err + } return os.WriteFile(dst, data, dstMode) } diff --git a/integration/util/web.go b/integration/util/web.go index 1307b154..7b7bf5d1 100644 --- a/integration/util/web.go +++ b/integration/util/web.go @@ -62,7 +62,18 @@ const ( // SendDigitalTwinRequest sends a new HTTP request to the Ditto REST API func SendDigitalTwinRequest(cfg *TestConfiguration, method string, url string, body interface{}) ([]byte, error) { - req, err := createRequest(make([]byte, 0), body, method, url, cfg.DigitalTwinAPIUsername, cfg.DigitalTwinAPIPassword) + var ( + payload []byte + err error + ) + if body != nil { + payload, err = json.Marshal(body) + if err != nil { + return nil, err + } + } + + req, err := createRequest(payload, true, method, url, cfg.DigitalTwinAPIUsername, cfg.DigitalTwinAPIPassword) if err != nil { return nil, err } @@ -71,23 +82,17 @@ func SendDigitalTwinRequest(cfg *TestConfiguration, method string, url string, b // SendDeviceRegistryRequest sends a new HTTP request to the Ditto API func SendDeviceRegistryRequest(payload []byte, method string, url string, username string, password string) ([]byte, error) { - req, err := createRequest(payload, nil, method, url, username, password) + req, err := createRequest(payload, false, method, url, username, password) if err != nil { return nil, err } return sendRequest(req, method, url) } -func createRequest(payload []byte, body interface{}, method, url, username, password string) (*http.Request, error) { +func createRequest(payload []byte, rspRequired bool, method, url, username, password string) (*http.Request, error) { var reqBody io.Reader - if body != nil { - jsonValue, err := json.Marshal(body) - if err != nil { - return nil, err - } - reqBody = bytes.NewBuffer(jsonValue) - } else { + if payload != nil { reqBody = bytes.NewBuffer(payload) } @@ -96,11 +101,13 @@ func createRequest(payload []byte, body interface{}, method, url, username, pass return nil, err } - req.Header.Add("Content-Type", "application/json") - if body != nil { - correlationID := uuid.New().String() - req.Header.Add("correlation-id", correlationID) - req.Header.Add("response-required", "true") + if payload != nil { + req.Header.Add("Content-Type", "application/json") + if rspRequired { + correlationID := uuid.New().String() + req.Header.Add("correlation-id", correlationID) + req.Header.Add("response-required", "true") + } } req.SetBasicAuth(username, password) From 1fee4c8fea729a8339e5553c9dcf2782940d5c03 Mon Sep 17 00:00:00 2001 From: Antonia Avramova Date: Wed, 8 Mar 2023 17:16:39 +0200 Subject: [PATCH 4/8] Common logic for device resources Signed-off-by: Antonia Avramova --- integration/util/registry.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/integration/util/registry.go b/integration/util/registry.go index 4312ec5c..c86f1827 100644 --- a/integration/util/registry.go +++ b/integration/util/registry.go @@ -67,8 +67,7 @@ type ConnectorConfiguration struct { // CreateDeviceResources creates device resources. func CreateDeviceResources(newDeviceId, tenantID, policyID, password, registryAPI, - registryAPIUsername, registryAPIPassword string, - cfg *TestConfiguration) (*Resource, []*Resource) { + registryAPIUsername, registryAPIPassword string, cfg *TestConfiguration) []*Resource { resources := make([]*Resource, 0, 3) devicePath := tenantID + "/" + newDeviceId @@ -84,7 +83,7 @@ func CreateDeviceResources(newDeviceId, tenantID, policyID, password, registryAP thing := fmt.Sprintf(thingJSON, policyID) resources = append(resources, &Resource{url: thingURL, method: http.MethodPut, body: thing, user: cfg.DigitalTwinAPIUsername, pass: cfg.DigitalTwinAPIPassword, delete: true}) - return deviceResource, resources + return resources } func getCredentialsBody(authID, pass string) string { From 77736b2c0754da39b096439d0b20f32090bb6f2f Mon Sep 17 00:00:00 2001 From: Antonia Avramova Date: Thu, 9 Mar 2023 17:11:30 +0200 Subject: [PATCH 5/8] Common logic for device resources Signed-off-by: Antonia Avramova --- integration/util/registry.go | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/integration/util/registry.go b/integration/util/registry.go index c86f1827..ce908ef5 100644 --- a/integration/util/registry.go +++ b/integration/util/registry.go @@ -22,10 +22,6 @@ import ( ) const ( - deviceJSON = `{"authorities":["auto-provisioning-enabled"]}` - - thingJSON = `{"policyId": "%s"}` - configDefaultMode = 0666 systemctl = "systemctl" @@ -69,21 +65,18 @@ type ConnectorConfiguration struct { func CreateDeviceResources(newDeviceId, tenantID, policyID, password, registryAPI, registryAPIUsername, registryAPIPassword string, cfg *TestConfiguration) []*Resource { - resources := make([]*Resource, 0, 3) devicePath := tenantID + "/" + newDeviceId - deviceResource := &Resource{url: registryAPI + "/devices/" + devicePath, method: http.MethodPost, - body: deviceJSON, user: registryAPIUsername, pass: registryAPIPassword, delete: true} - resources = append(resources, deviceResource) - - authID := strings.ReplaceAll(newDeviceId, ":", "_") - resources = append(resources, &Resource{url: registryAPI + "/credentials/" + devicePath, method: http.MethodPut, - body: getCredentialsBody(authID, password), user: registryAPIUsername, pass: registryAPIPassword, delete: false}) - - thingURL := GetThingURL(cfg.DigitalTwinAPIAddress, newDeviceId) - thing := fmt.Sprintf(thingJSON, policyID) - resources = append(resources, &Resource{url: thingURL, method: http.MethodPut, - body: thing, user: cfg.DigitalTwinAPIUsername, pass: cfg.DigitalTwinAPIPassword, delete: true}) - return resources + return []*Resource{ + &Resource{url: registryAPI + "/devices/" + devicePath, method: http.MethodPost, + body: `{"authorities":["auto-provisioning-enabled"]}`, + user: registryAPIUsername, pass: registryAPIPassword, delete: true}, + &Resource{url: registryAPI + "/credentials/" + devicePath, method: http.MethodPut, + body: getCredentialsBody(strings.ReplaceAll(newDeviceId, ":", "_"), password), + user: registryAPIUsername, pass: registryAPIPassword, delete: false}, + &Resource{url: GetThingURL(cfg.DigitalTwinAPIAddress, newDeviceId), method: http.MethodPut, + body: fmt.Sprintf(`{"policyId": "%s"}`, policyID), + user: cfg.DigitalTwinAPIUsername, pass: cfg.DigitalTwinAPIPassword, delete: true}, + } } func getCredentialsBody(authID, pass string) string { @@ -96,11 +89,9 @@ func getCredentialsBody(authID, pass string) string { AuthId string `json:"auth-id"` Secrets []pwdPlain `json:"secrets"` } - pwds := []pwdPlain{pwdPlain{pass}} + auth := authStruct{"hashed-password", authID, []pwdPlain{pwdPlain{pass}}} - auth := authStruct{"hashed-password", authID, pwds} - authJson := []authStruct{auth} - data, _ := json.MarshalIndent(authJson, "", "\t") + data, _ := json.MarshalIndent([]authStruct{auth}, "", "\t") return string(data) } From 79c7c6df790e0df4f7b27da63f1279231ba54f02 Mon Sep 17 00:00:00 2001 From: Antonia Avramova Date: Fri, 10 Mar 2023 16:39:15 +0200 Subject: [PATCH 6/8] Common logic for device resources Signed-off-by: Antonia Avramova --- integration/util/common.go | 55 ++++++++++- integration/util/registry.go | 173 +++++++++++++---------------------- integration/util/web.go | 3 +- 3 files changed, 118 insertions(+), 113 deletions(-) diff --git a/integration/util/common.go b/integration/util/common.go index 1b635f27..6052bdd6 100644 --- a/integration/util/common.go +++ b/integration/util/common.go @@ -12,7 +12,15 @@ package util -import "encoding/json" +import ( + "encoding/json" + "fmt" + "os" +) + +const ( + configDefaultMode = 0666 +) // Convert marshals an object(e.g. map) to a JSON payload and unmarshals it to the given structure func Convert(from interface{}, to interface{}) error { @@ -22,3 +30,48 @@ func Convert(from interface{}, to interface{}) error { } return json.Unmarshal(jsonValue, to) } + +// WriteConfigFile writes interface data to the path file, creating it if necessary. +func WriteConfigFile(path string, cfg interface{}) error { + jsonContents, err := json.MarshalIndent(cfg, "", "\t") + if err != nil { + return fmt.Errorf("unable to marshal to json: %v", err) + } + + // Preserve the file mode if the file already exists + mode, err := getFileModeOrDefault(path, configDefaultMode) + if err != nil { + return fmt.Errorf("unable to get file mode %s: %v", path, err) + } + if err = os.WriteFile(path, jsonContents, mode); err != nil { + return fmt.Errorf("unable to save file %s: %v", path, err) + } + return nil +} + +func getFileModeOrDefault(path string, defaultMode os.FileMode) (os.FileMode, error) { + fileInfo, err := os.Stat(path) + if err != nil { + return defaultMode, err + } + return fileInfo.Mode(), nil +} + +// CopyFile copies source file to the destination. +func CopyFile(src, dst string) error { + data, err := os.ReadFile(src) + if err != nil { + return err + } + // If the destination file exists, preserve its file mode. + // If the destination file doesn't exist, use the file mode of the source file. + srcMode, err := getFileModeOrDefault(src, configDefaultMode) + if err != nil { + return err + } + dstMode, err := getFileModeOrDefault(dst, srcMode) + if err != nil { + return err + } + return os.WriteFile(dst, data, dstMode) +} diff --git a/integration/util/registry.go b/integration/util/registry.go index ce908ef5..f04c36c9 100644 --- a/integration/util/registry.go +++ b/integration/util/registry.go @@ -16,17 +16,9 @@ import ( "encoding/json" "fmt" "net/http" - "os" - "os/exec" "strings" ) -const ( - configDefaultMode = 0666 - - systemctl = "systemctl" -) - type Resource struct { url string @@ -67,15 +59,26 @@ func CreateDeviceResources(newDeviceId, tenantID, policyID, password, registryAP devicePath := tenantID + "/" + newDeviceId return []*Resource{ - &Resource{url: registryAPI + "/devices/" + devicePath, method: http.MethodPost, - body: `{"authorities":["auto-provisioning-enabled"]}`, - user: registryAPIUsername, pass: registryAPIPassword, delete: true}, - &Resource{url: registryAPI + "/credentials/" + devicePath, method: http.MethodPut, - body: getCredentialsBody(strings.ReplaceAll(newDeviceId, ":", "_"), password), - user: registryAPIUsername, pass: registryAPIPassword, delete: false}, - &Resource{url: GetThingURL(cfg.DigitalTwinAPIAddress, newDeviceId), method: http.MethodPut, - body: fmt.Sprintf(`{"policyId": "%s"}`, policyID), - user: cfg.DigitalTwinAPIUsername, pass: cfg.DigitalTwinAPIPassword, delete: true}, + &Resource{ + url: registryAPI + "/devices/" + devicePath, + method: http.MethodPost, + body: `{"authorities":["auto-provisioning-enabled"]}`, + user: registryAPIUsername, + pass: registryAPIPassword, + delete: true}, + &Resource{ + url: registryAPI + "/credentials/" + devicePath, + method: http.MethodPut, + body: getCredentialsBody(strings.ReplaceAll(newDeviceId, ":", "_"), password), + user: registryAPIUsername, + pass: registryAPIPassword}, + &Resource{ + url: GetThingURL(cfg.DigitalTwinAPIAddress, newDeviceId), + method: http.MethodPut, + body: fmt.Sprintf(`{"policyId": "%s"}`, policyID), + user: cfg.DigitalTwinAPIUsername, + pass: cfg.DigitalTwinAPIPassword, + delete: true}, } } @@ -95,35 +98,13 @@ func getCredentialsBody(authID, pass string) string { return string(data) } -// WriteConfigFile writes interface data to the path file, creating it if necessary. -func WriteConfigFile(path string, cfg interface{}) error { - jsonContents, err := json.MarshalIndent(cfg, "", "\t") - if err != nil { - return fmt.Errorf("unable to marshal to json: %v", err) - } - - // Preserve the file mode if the file already exists - mode, err := getFileModeOrDefault(path, configDefaultMode) - if err != nil { - return fmt.Errorf("unable to get file mode %s: %v", path, err) - } - if err = os.WriteFile(path, jsonContents, mode); err != nil { - return fmt.Errorf("unable to save file %s: %v", path, err) - } - return nil -} - -func getFileModeOrDefault(path string, defaultMode os.FileMode) (os.FileMode, error) { - fileInfo, err := os.Stat(path) - if err != nil { - return defaultMode, err +// DeleteResources deletes all given resources and all related devices. +func DeleteResources(cfg *TestConfiguration, resources []*Resource, deviceId, url, user, pass string) error { + var errStrings []string + if err := deleteRelatedDevices(cfg, deviceId, url, user, pass); err != nil { + errStrings = append(errStrings, err.Error()) } - return fileInfo.Mode(), nil -} -// DeleteResources deletes all given resources and all related devices. -func DeleteResources(cfg *TestConfiguration, resources []*Resource, deviceId, url, user, pass string) []error { - deleteErrors := deleteRelatedDevices(cfg, deviceId, url, user, pass) // Delete in reverse order of creation for i := len(resources) - 1; i >= 0; i-- { r := resources[i] @@ -133,62 +114,53 @@ func DeleteResources(cfg *TestConfiguration, resources []*Resource, deviceId, ur } if _, err := SendDeviceRegistryRequest(nil, http.MethodDelete, r.url, r.user, r.pass); err != nil { - deleteErrors = append(deleteErrors, err) + errStrings = append(errStrings, err.Error()) } } - return deleteErrors + return combineErrors(errStrings) } -func deleteRelatedDevices(cfg *TestConfiguration, viaDeviceID, url, user, pass string) []error { - var deleteErrors []error +func deleteRelatedDevices(cfg *TestConfiguration, viaDeviceID, url, user, pass string) error { devicesVia, err := findDeviceRegistryDevicesVia(viaDeviceID, url, user, pass) if err != nil { - deleteErrors = append(deleteErrors, err) + return err } + + var errStrings []string // Digital Twin API things are created after Device Registry devices, so delete them first - if delErrors := deleteDigitalTwinThings(cfg, devicesVia); delErrors != nil { - deleteErrors = append(deleteErrors, delErrors...) + if err = deleteDigitalTwinThings(cfg, devicesVia); err != nil { + errStrings = append(errStrings, err.Error()) } // Then delete Device Registry devices - if delErrors := deleteRegistryDevices(devicesVia, url, user, pass); delErrors != nil { - deleteErrors = append(deleteErrors, delErrors...) + if err = deleteRegistryDevices(devicesVia, url, user, pass); err != nil { + errStrings = append(errStrings, err.Error()) } - return deleteErrors + return combineErrors(errStrings) } func findDeviceRegistryDevicesVia(viaDeviceID, url, user, pass string) ([]string, error) { - var devicesVia []string - type registryDevice struct { ID string `json:"id"` Via []string `json:"via"` } - type registryDevices struct { Devices []*registryDevice `json:"result"` } - - contains := func(where []string, what string) bool { - for _, item := range where { - if item == what { - return true - } - } - return false - } - devicesJSON, err := SendDeviceRegistryRequest(nil, http.MethodGet, url, user, pass) if err != nil { - return devicesVia, err - } else { - devices := ®istryDevices{} - err = json.Unmarshal(devicesJSON, devices) - if err != nil { - return devicesVia, err - } - for _, device := range devices.Devices { - if contains(device.Via, viaDeviceID) { + return nil, err + } + devices := ®istryDevices{} + err = json.Unmarshal(devicesJSON, devices) + if err != nil { + return nil, err + } + var devicesVia []string + for _, device := range devices.Devices { + for _, via := range device.Via { + if via == viaDeviceID { devicesVia = append(devicesVia, device.ID) + break } } } @@ -196,49 +168,30 @@ func findDeviceRegistryDevicesVia(viaDeviceID, url, user, pass string) ([]string return devicesVia, nil } -func deleteDigitalTwinThings(cfg *TestConfiguration, things []string) []error { - var deleteErrors []error +func deleteDigitalTwinThings(cfg *TestConfiguration, things []string) error { + var errStrings []string for _, thingID := range things { - url := GetThingURL(cfg.DigitalTwinAPIAddress, thingID) - if _, err := SendDigitalTwinRequest(cfg, http.MethodDelete, url, nil); err != nil { - deleteErrors = append(deleteErrors, err) + if _, err := SendDigitalTwinRequest( + cfg, http.MethodDelete, GetThingURL(cfg.DigitalTwinAPIAddress, thingID), nil); err != nil { + errStrings = append(errStrings, err.Error()) } } - return deleteErrors + return combineErrors(errStrings) } -func deleteRegistryDevices(devices []string, tenantURL, user, pass string) []error { - var deleteErrors []error +func deleteRegistryDevices(devices []string, tenantURL, user, pass string) error { + var errStrings []string for _, device := range devices { - url := tenantURL + device - if _, err := SendDeviceRegistryRequest(nil, http.MethodDelete, url, user, pass); err != nil { - deleteErrors = append(deleteErrors, err) + if _, err := SendDeviceRegistryRequest(nil, http.MethodDelete, tenantURL+device, user, pass); err != nil { + errStrings = append(errStrings, err.Error()) } } - return deleteErrors + return combineErrors(errStrings) } -// ExecuteCommandToService executes command to the service with given name -func ExecuteCommandToService(command, service string) ([]byte, error) { - cmd := exec.Command(systemctl, command, service) - return cmd.Output() -} - -// CopyFile copies source file to the destination. -func CopyFile(src, dst string) error { - data, err := os.ReadFile(src) - if err != nil { - return err - } - // If the destination file exists, preserve its file mode. - // If the destination file doesn't exist, use the file mode of the source file. - srcMode, err := getFileModeOrDefault(src, configDefaultMode) - if err != nil { - return err +func combineErrors(errStrings []string) error { + if errStrings != nil { + return fmt.Errorf(strings.Join(errStrings, "\n")) } - dstMode, err := getFileModeOrDefault(dst, srcMode) - if err != nil { - return err - } - return os.WriteFile(dst, data, dstMode) + return nil } diff --git a/integration/util/web.go b/integration/util/web.go index 7b7bf5d1..010130ed 100644 --- a/integration/util/web.go +++ b/integration/util/web.go @@ -104,8 +104,7 @@ func createRequest(payload []byte, rspRequired bool, method, url, username, pass if payload != nil { req.Header.Add("Content-Type", "application/json") if rspRequired { - correlationID := uuid.New().String() - req.Header.Add("correlation-id", correlationID) + req.Header.Add("correlation-id", uuid.New().String()) req.Header.Add("response-required", "true") } } From 3ba23ddba0557b7871c3b84450650957534f21db Mon Sep 17 00:00:00 2001 From: Antonia Avramova Date: Mon, 13 Mar 2023 13:10:38 +0200 Subject: [PATCH 7/8] Common logic for device resources Signed-off-by: Antonia Avramova --- integration/util/common.go | 12 ++++++++--- integration/util/registry.go | 42 +++++++++++++++--------------------- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/integration/util/common.go b/integration/util/common.go index 6052bdd6..2d93fb9d 100644 --- a/integration/util/common.go +++ b/integration/util/common.go @@ -18,9 +18,7 @@ import ( "os" ) -const ( - configDefaultMode = 0666 -) +const configDefaultMode = 0666 // Convert marshals an object(e.g. map) to a JSON payload and unmarshals it to the given structure func Convert(from interface{}, to interface{}) error { @@ -31,6 +29,14 @@ func Convert(from interface{}, to interface{}) error { return json.Unmarshal(jsonValue, to) } +// CombineErrors combine multiple errors in one error. +func CombineErrors(errors []error) error { + if errors != nil { + return fmt.Errorf("%s", errors) + } + return nil +} + // WriteConfigFile writes interface data to the path file, creating it if necessary. func WriteConfigFile(path string, cfg interface{}) error { jsonContents, err := json.MarshalIndent(cfg, "", "\t") diff --git a/integration/util/registry.go b/integration/util/registry.go index f04c36c9..c3fb4874 100644 --- a/integration/util/registry.go +++ b/integration/util/registry.go @@ -100,24 +100,23 @@ func getCredentialsBody(authID, pass string) string { // DeleteResources deletes all given resources and all related devices. func DeleteResources(cfg *TestConfiguration, resources []*Resource, deviceId, url, user, pass string) error { - var errStrings []string + var errors []error if err := deleteRelatedDevices(cfg, deviceId, url, user, pass); err != nil { - errStrings = append(errStrings, err.Error()) + errors = append(errors, err) } // Delete in reverse order of creation for i := len(resources) - 1; i >= 0; i-- { r := resources[i] - if !r.delete { - continue + if r.delete { + if _, err := SendDeviceRegistryRequest(nil, http.MethodDelete, r.url, r.user, r.pass); err != nil { + errors = append(errors, err) + } } - if _, err := SendDeviceRegistryRequest(nil, http.MethodDelete, r.url, r.user, r.pass); err != nil { - errStrings = append(errStrings, err.Error()) - } } - return combineErrors(errStrings) + return CombineErrors(errors) } func deleteRelatedDevices(cfg *TestConfiguration, viaDeviceID, url, user, pass string) error { @@ -126,16 +125,16 @@ func deleteRelatedDevices(cfg *TestConfiguration, viaDeviceID, url, user, pass s return err } - var errStrings []string + var errors []error // Digital Twin API things are created after Device Registry devices, so delete them first if err = deleteDigitalTwinThings(cfg, devicesVia); err != nil { - errStrings = append(errStrings, err.Error()) + errors = append(errors, err) } // Then delete Device Registry devices if err = deleteRegistryDevices(devicesVia, url, user, pass); err != nil { - errStrings = append(errStrings, err.Error()) + errors = append(errors, err) } - return combineErrors(errStrings) + return CombineErrors(errors) } func findDeviceRegistryDevicesVia(viaDeviceID, url, user, pass string) ([]string, error) { @@ -169,29 +168,22 @@ func findDeviceRegistryDevicesVia(viaDeviceID, url, user, pass string) ([]string } func deleteDigitalTwinThings(cfg *TestConfiguration, things []string) error { - var errStrings []string + var errors []error for _, thingID := range things { if _, err := SendDigitalTwinRequest( cfg, http.MethodDelete, GetThingURL(cfg.DigitalTwinAPIAddress, thingID), nil); err != nil { - errStrings = append(errStrings, err.Error()) + errors = append(errors, err) } } - return combineErrors(errStrings) + return CombineErrors(errors) } func deleteRegistryDevices(devices []string, tenantURL, user, pass string) error { - var errStrings []string + var errors []error for _, device := range devices { if _, err := SendDeviceRegistryRequest(nil, http.MethodDelete, tenantURL+device, user, pass); err != nil { - errStrings = append(errStrings, err.Error()) + errors = append(errors, err) } } - return combineErrors(errStrings) -} - -func combineErrors(errStrings []string) error { - if errStrings != nil { - return fmt.Errorf(strings.Join(errStrings, "\n")) - } - return nil + return CombineErrors(errors) } From 039502fb32af88daac3b4b8c96981d4a13d625f3 Mon Sep 17 00:00:00 2001 From: Antonia Avramova Date: Tue, 14 Mar 2023 10:33:22 +0200 Subject: [PATCH 8/8] Common logic for device resources Signed-off-by: Antonia Avramova --- integration/util/registry.go | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/integration/util/registry.go b/integration/util/registry.go index c3fb4874..2f43bef1 100644 --- a/integration/util/registry.go +++ b/integration/util/registry.go @@ -19,6 +19,7 @@ import ( "strings" ) +// Resource holds all needed properties to create resources for the device. type Resource struct { url string @@ -31,6 +32,8 @@ type Resource struct { delete bool } +// BootstrapConfiguration holds the required configuration to suite bootstrapping to connect and +// where to receive post bootstrapping files and script. type BootstrapConfiguration struct { LogFile string `json:"logFile"` PostBootstrapFile string `json:"postBootstrapFile"` @@ -43,6 +46,7 @@ type BootstrapConfiguration struct { Password string `json:"password"` } +// ConnectorConfiguration holds the minimum required configuration to suite connector to connect. type ConnectorConfiguration struct { CaCert string `json:"caCert"` LogFile string `json:"logFile"` @@ -54,10 +58,10 @@ type ConnectorConfiguration struct { } // CreateDeviceResources creates device resources. -func CreateDeviceResources(newDeviceId, tenantID, policyID, password, registryAPI, +func CreateDeviceResources(newDeviceID, tenantID, policyID, password, registryAPI, registryAPIUsername, registryAPIPassword string, cfg *TestConfiguration) []*Resource { - devicePath := tenantID + "/" + newDeviceId + devicePath := tenantID + "/" + newDeviceID return []*Resource{ &Resource{ url: registryAPI + "/devices/" + devicePath, @@ -69,11 +73,11 @@ func CreateDeviceResources(newDeviceId, tenantID, policyID, password, registryAP &Resource{ url: registryAPI + "/credentials/" + devicePath, method: http.MethodPut, - body: getCredentialsBody(strings.ReplaceAll(newDeviceId, ":", "_"), password), + body: getCredentialsBody(strings.ReplaceAll(newDeviceID, ":", "_"), password), user: registryAPIUsername, pass: registryAPIPassword}, &Resource{ - url: GetThingURL(cfg.DigitalTwinAPIAddress, newDeviceId), + url: GetThingURL(cfg.DigitalTwinAPIAddress, newDeviceID), method: http.MethodPut, body: fmt.Sprintf(`{"policyId": "%s"}`, policyID), user: cfg.DigitalTwinAPIUsername, @@ -89,7 +93,7 @@ func getCredentialsBody(authID, pass string) string { type authStruct struct { TypeStr string `json:"type"` - AuthId string `json:"auth-id"` + AuthID string `json:"auth-id"` Secrets []pwdPlain `json:"secrets"` } auth := authStruct{"hashed-password", authID, []pwdPlain{pwdPlain{pass}}} @@ -99,9 +103,9 @@ func getCredentialsBody(authID, pass string) string { } // DeleteResources deletes all given resources and all related devices. -func DeleteResources(cfg *TestConfiguration, resources []*Resource, deviceId, url, user, pass string) error { +func DeleteResources(cfg *TestConfiguration, resources []*Resource, deviceID, url, user, pass string) error { var errors []error - if err := deleteRelatedDevices(cfg, deviceId, url, user, pass); err != nil { + if err := deleteRelatedDevices(cfg, deviceID, url, user, pass); err != nil { errors = append(errors, err) }