From a8c5b53a2c6ed5303f7390d3fbff3afcb4c5f70b Mon Sep 17 00:00:00 2001 From: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com> Date: Tue, 26 Dec 2023 14:29:11 -0600 Subject: [PATCH] Pkg Subnet Utils Tests (#3173) Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com> --- pkg/subnet/utils.go | 19 +- pkg/subnet/utils_test.go | 607 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 610 insertions(+), 16 deletions(-) create mode 100644 pkg/subnet/utils_test.go diff --git a/pkg/subnet/utils.go b/pkg/subnet/utils.go index 33de9185e..dd288b01f 100644 --- a/pkg/subnet/utils.go +++ b/pkg/subnet/utils.go @@ -1,5 +1,5 @@ // This file is part of MinIO Console Server -// Copyright (c) 2021 MinIO, Inc. +// Copyright (c) 2023 MinIO, Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -245,7 +245,7 @@ func getDriveSpaceInfo(admInfo madmin.InfoMessage) (uint64, uint64) { } func GetSubnetAPIKeyUsingLicense(lic string) (string, error) { - return getSubnetAPIKeyUsingAuthHeaders(subnetLicenseAuthHeaders(lic)) + return getSubnetAPIKeyUsingAuthHeaders(map[string]string{"x-subnet-license": lic}) } func getSubnetAPIKeyUsingAuthHeaders(authHeaders map[string]string) (string, error) { @@ -264,10 +264,6 @@ func extractSubnetCred(key string, resp gjson.Result) (string, error) { return result.String(), nil } -func subnetLicenseAuthHeaders(lic string) map[string]string { - return map[string]string{"x-subnet-license": lic} -} - func subnetGetReqMC(reqURL string, headers map[string]string) (string, error) { r, e := http.NewRequest(http.MethodGet, reqURL, nil) if e != nil { @@ -286,7 +282,7 @@ func subnetReqDoMC(r *http.Request, headers map[string]string) (string, error) { r.Header.Add("Content-Type", "application/json") } - resp, e := subnetHTTPDo(r) + resp, e := httpClientSubnet(0).Do(r) if e != nil { return "", e } @@ -304,15 +300,6 @@ func subnetReqDoMC(r *http.Request, headers map[string]string) (string, error) { return respStr, fmt.Errorf("Request failed with code %d with error: %s", resp.StatusCode, respStr) } -func subnetHTTPDo(req *http.Request) (*http.Response, error) { - return getSubnetClient().Do(req) -} - -func getSubnetClient() *http.Client { - client := httpClientSubnet(0) - return client -} - func httpClientSubnet(reqTimeout time.Duration) *http.Client { return &http.Client{ Timeout: reqTimeout, diff --git a/pkg/subnet/utils_test.go b/pkg/subnet/utils_test.go new file mode 100644 index 000000000..92f608e97 --- /dev/null +++ b/pkg/subnet/utils_test.go @@ -0,0 +1,607 @@ +// This file is part of MinIO Console Server +// Copyright (c) 2023 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package subnet + +import ( + "os" + "reflect" + "testing" + + "github.com/minio/madmin-go/v3" + "github.com/minio/mc/cmd" +) + +func Test_subnetBaseURL(t *testing.T) { + type args struct { + env map[string]string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "default", + args: args{ + env: nil, + }, + want: "https://subnet.min.io", + }, + { + name: "with env", + args: args{ + env: map[string]string{ + "CONSOLE_SUBNET_URL": "http://oorgle", + }, + }, + want: "http://oorgle", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.args.env != nil { + for k, v := range tt.args.env { + os.Setenv(k, v) + } + } + if got := subnetBaseURL(); got != tt.want { + t.Errorf("subnetBaseURL() = %v, want %v", got, tt.want) + } + if tt.args.env != nil { + for k := range tt.args.env { + os.Unsetenv(k) + } + } + }) + } +} + +func Test_subnetRegisterURL(t *testing.T) { + type args struct { + env map[string]string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "default", + args: args{ + env: nil, + }, + want: "https://subnet.min.io/api/cluster/register", + }, + { + name: "with env", + args: args{ + env: map[string]string{ + "CONSOLE_SUBNET_URL": "http://oorgle", + }, + }, + want: "http://oorgle/api/cluster/register", + }, + } + for _, tt := range tests { + if tt.args.env != nil { + for k, v := range tt.args.env { + os.Setenv(k, v) + } + } + t.Run(tt.name, func(t *testing.T) { + if got := subnetRegisterURL(); got != tt.want { + t.Errorf("subnetRegisterURL() = %v, want %v", got, tt.want) + } + }) + if tt.args.env != nil { + for k := range tt.args.env { + os.Unsetenv(k) + } + } + } +} + +func Test_subnetLoginURL(t *testing.T) { + type args struct { + env map[string]string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "default", + args: args{ + env: nil, + }, + want: "https://subnet.min.io/api/auth/login", + }, + { + name: "with env", + args: args{ + env: map[string]string{ + "CONSOLE_SUBNET_URL": "http://oorgle", + }, + }, + want: "http://oorgle/api/auth/login", + }, + } + for _, tt := range tests { + if tt.args.env != nil { + for k, v := range tt.args.env { + os.Setenv(k, v) + } + } + t.Run(tt.name, func(t *testing.T) { + if got := subnetLoginURL(); got != tt.want { + t.Errorf("subnetLoginURL() = %v, want %v", got, tt.want) + } + }) + if tt.args.env != nil { + for k := range tt.args.env { + os.Unsetenv(k) + } + } + } +} + +func Test_subnetOrgsURL(t *testing.T) { + type args struct { + env map[string]string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "default", + args: args{ + env: nil, + }, + want: "https://subnet.min.io/api/auth/organizations", + }, + { + name: "with env", + args: args{ + env: map[string]string{ + "CONSOLE_SUBNET_URL": "http://oorgle", + }, + }, + want: "http://oorgle/api/auth/organizations", + }, + } + for _, tt := range tests { + if tt.args.env != nil { + for k, v := range tt.args.env { + os.Setenv(k, v) + } + } + t.Run(tt.name, func(t *testing.T) { + if got := subnetOrgsURL(); got != tt.want { + t.Errorf("subnetOrgsURL() = %v, want %v", got, tt.want) + } + }) + if tt.args.env != nil { + for k := range tt.args.env { + os.Unsetenv(k) + } + } + } +} + +func Test_subnetMFAURL(t *testing.T) { + type args struct { + env map[string]string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "default", + args: args{ + env: nil, + }, + want: "https://subnet.min.io/api/auth/mfa-login", + }, + { + name: "with env", + args: args{ + env: map[string]string{ + "CONSOLE_SUBNET_URL": "http://oorgle", + }, + }, + want: "http://oorgle/api/auth/mfa-login", + }, + } + for _, tt := range tests { + if tt.args.env != nil { + for k, v := range tt.args.env { + os.Setenv(k, v) + } + } + t.Run(tt.name, func(t *testing.T) { + if got := subnetMFAURL(); got != tt.want { + t.Errorf("subnetMFAURL() = %v, want %v", got, tt.want) + } + }) + if tt.args.env != nil { + for k := range tt.args.env { + os.Unsetenv(k) + } + } + } +} + +func Test_subnetAPIKeyURL(t *testing.T) { + type args struct { + env map[string]string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "default", + args: args{ + env: nil, + }, + want: "https://subnet.min.io/api/auth/api-key", + }, + { + name: "with env", + args: args{ + env: map[string]string{ + "CONSOLE_SUBNET_URL": "http://oorgle", + }, + }, + want: "http://oorgle/api/auth/api-key", + }, + } + for _, tt := range tests { + if tt.args.env != nil { + for k, v := range tt.args.env { + os.Setenv(k, v) + } + } + t.Run(tt.name, func(t *testing.T) { + if got := subnetAPIKeyURL(); got != tt.want { + t.Errorf("subnetAPIKeyURL() = %v, want %v", got, tt.want) + } + }) + if tt.args.env != nil { + for k := range tt.args.env { + os.Unsetenv(k) + } + } + } +} + +func TestLogWebhookURL(t *testing.T) { + type args struct { + env map[string]string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "default", + args: args{ + env: nil, + }, + want: "https://subnet.min.io/api/logs", + }, + { + name: "with env", + args: args{ + env: map[string]string{ + "CONSOLE_SUBNET_URL": "http://oorgle", + }, + }, + want: "http://oorgle/api/logs", + }, + } + for _, tt := range tests { + if tt.args.env != nil { + for k, v := range tt.args.env { + os.Setenv(k, v) + } + } + t.Run(tt.name, func(t *testing.T) { + if got := LogWebhookURL(); got != tt.want { + t.Errorf("LogWebhookURL() = %v, want %v", got, tt.want) + } + }) + if tt.args.env != nil { + for k := range tt.args.env { + os.Unsetenv(k) + } + } + } +} + +func TestUploadURL(t *testing.T) { + type args struct { + env map[string]string + uploadType string + filename string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "default", + args: args{ + env: nil, + uploadType: "x", + filename: "y.jpg", + }, + want: "https://subnet.min.io/api/x/upload?filename=y.jpg", + }, + { + name: "with env", + args: args{ + env: map[string]string{ + "CONSOLE_SUBNET_URL": "http://oorgle", + }, + uploadType: "x", + filename: "y.jpg", + }, + want: "http://oorgle/api/x/upload?filename=y.jpg", + }, + } + for _, tt := range tests { + if tt.args.env != nil { + for k, v := range tt.args.env { + os.Setenv(k, v) + } + } + t.Run(tt.name, func(t *testing.T) { + if got := UploadURL(tt.args.uploadType, tt.args.filename); got != tt.want { + t.Errorf("UploadURL() = %v, want %v", got, tt.want) + } + }) + if tt.args.env != nil { + for k := range tt.args.env { + os.Unsetenv(k) + } + } + } +} + +func TestUploadAuthHeaders(t *testing.T) { + type args struct { + apiKey string + } + tests := []struct { + name string + args args + want map[string]string + }{ + { + name: "basic", + args: args{ + apiKey: "xx", + }, + want: map[string]string{"x-subnet-api-key": "xx"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := UploadAuthHeaders(tt.args.apiKey); !reflect.DeepEqual(got, tt.want) { + t.Errorf("UploadAuthHeaders() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGenerateRegToken(t *testing.T) { + type args struct { + clusterRegInfo cmd.ClusterRegistrationInfo + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "basic", + args: args{ + clusterRegInfo: cmd.ClusterRegistrationInfo{ + DeploymentID: "x", + ClusterName: "y", + UsedCapacity: 1, + Info: cmd.ClusterInfo{}, + }, + }, + want: "eyJkZXBsb3ltZW50X2lkIjoieCIsImNsdXN0ZXJfbmFtZSI6InkiLCJ1c2VkX2NhcGFjaXR5IjoxLCJpbmZvIjp7Im1pbmlvX3ZlcnNpb24iOiIiLCJub19vZl9zZXJ2ZXJfcG9vbHMiOjAsIm5vX29mX3NlcnZlcnMiOjAsIm5vX29mX2RyaXZlcyI6MCwibm9fb2ZfYnVja2V0cyI6MCwibm9fb2Zfb2JqZWN0cyI6MCwidG90YWxfZHJpdmVfc3BhY2UiOjAsInVzZWRfZHJpdmVfc3BhY2UiOjB9fQ==", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GenerateRegToken(tt.args.clusterRegInfo) + if (err != nil) != tt.wantErr { + t.Errorf("GenerateRegToken() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("GenerateRegToken() got = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_subnetAuthHeaders(t *testing.T) { + type args struct { + authToken string + } + tests := []struct { + name string + args args + want map[string]string + }{ + { + name: "basic", + args: args{ + authToken: "x", + }, + want: map[string]string{"Authorization": "Bearer x"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := subnetAuthHeaders(tt.args.authToken); !reflect.DeepEqual(got, tt.want) { + t.Errorf("subnetAuthHeaders() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_getDriveSpaceInfo(t *testing.T) { + type args struct { + admInfo madmin.InfoMessage + } + tests := []struct { + name string + args args + want uint64 + want1 uint64 + }{ + { + name: "basic", + args: args{ + admInfo: madmin.InfoMessage{ + Servers: []madmin.ServerProperties{ + { + Disks: []madmin.Disk{ + { + TotalSpace: 1, + UsedSpace: 1, + }, + }, + }, + }, + }, + }, + want: 1, + want1: 1, + }, + { + name: "basic two disks", + args: args{ + admInfo: madmin.InfoMessage{ + Servers: []madmin.ServerProperties{ + { + Disks: []madmin.Disk{ + { + TotalSpace: 1, + UsedSpace: 1, + }, + { + TotalSpace: 1, + UsedSpace: 1, + }, + }, + }, + }, + }, + }, + want: 2, + want1: 2, + }, + { + name: "basic two servers two disks", + args: args{ + admInfo: madmin.InfoMessage{ + Servers: []madmin.ServerProperties{ + { + Disks: []madmin.Disk{ + { + TotalSpace: 1, + UsedSpace: 1, + }, + { + TotalSpace: 1, + UsedSpace: 1, + }, + }, + }, + { + Disks: []madmin.Disk{ + { + TotalSpace: 1, + UsedSpace: 1, + }, + { + TotalSpace: 1, + UsedSpace: 1, + }, + }, + }, + }, + }, + }, + want: 4, + want1: 4, + }, + { + name: "no servers", + args: args{ + admInfo: madmin.InfoMessage{ + Servers: nil, + }, + }, + want: 0, + want1: 0, + }, + { + name: "no disks", + args: args{ + admInfo: madmin.InfoMessage{ + Servers: []madmin.ServerProperties{ + { + Disks: nil, + }, + }, + }, + }, + want: 0, + want1: 0, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, got1 := getDriveSpaceInfo(tt.args.admInfo) + if got != tt.want { + t.Errorf("getDriveSpaceInfo() got = %v, want %v", got, tt.want) + } + if got1 != tt.want1 { + t.Errorf("getDriveSpaceInfo() got1 = %v, want %v", got1, tt.want1) + } + }) + } +}