Skip to content

Commit 6c50c38

Browse files
fix health report upload error (#3275)
1 parent 3aac62c commit 6c50c38

File tree

7 files changed

+56
-124
lines changed

7 files changed

+56
-124
lines changed

api/admin_health_info.go

Lines changed: 48 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,22 @@
1717
package api
1818

1919
import (
20-
"bytes"
2120
"context"
2221
b64 "encoding/base64"
2322
"encoding/json"
2423
"errors"
2524
"fmt"
2625
"net/http"
27-
"strings"
26+
"net/url"
27+
"os"
2828
"time"
2929

30+
"github.com/minio/console/pkg/logger"
3031
"github.com/minio/console/pkg/utils"
3132

32-
"github.com/klauspost/compress/gzip"
33-
xhttp "github.com/minio/console/pkg/http"
3433
subnet "github.com/minio/console/pkg/subnet"
3534
"github.com/minio/madmin-go/v3"
35+
mc "github.com/minio/mc/cmd"
3636
"github.com/minio/websocket"
3737
)
3838

@@ -63,7 +63,7 @@ func startHealthInfo(ctx context.Context, conn WSConn, client MinioAdmin, deadli
6363
return err
6464
}
6565

66-
compressedDiag, err := tarGZ(healthInfo, version)
66+
compressedDiag, err := mc.TarGZHealthInfo(healthInfo, version)
6767
if err != nil {
6868
return err
6969
}
@@ -75,11 +75,11 @@ func startHealthInfo(ctx context.Context, conn WSConn, client MinioAdmin, deadli
7575
}
7676

7777
ctx = context.WithValue(ctx, utils.ContextClientIP, conn.remoteAddress())
78-
subnetResp, err := sendHealthInfoToSubnet(ctx, healthInfo, client)
78+
err = sendHealthInfoToSubnet(ctx, healthInfo, client)
7979
report := messageReport{
8080
Encoded: encodedDiag,
8181
ServerHealthInfo: healthInfo,
82-
SubnetResponse: subnetResp,
82+
SubnetResponse: mc.SubnetBaseURL() + "/health",
8383
}
8484
if err != nil {
8585
report.SubnetResponse = fmt.Sprintf("Error: %s", err.Error())
@@ -94,31 +94,6 @@ func startHealthInfo(ctx context.Context, conn WSConn, client MinioAdmin, deadli
9494
return conn.writeMessage(websocket.TextMessage, message)
9595
}
9696

97-
// compress and tar MinIO diagnostics output
98-
func tarGZ(healthInfo interface{}, version string) ([]byte, error) {
99-
buffer := bytes.NewBuffer(nil)
100-
gzWriter := gzip.NewWriter(buffer)
101-
102-
enc := json.NewEncoder(gzWriter)
103-
104-
header := struct {
105-
Version string `json:"version"`
106-
}{Version: version}
107-
108-
if err := enc.Encode(header); err != nil {
109-
return nil, err
110-
}
111-
112-
if err := enc.Encode(healthInfo); err != nil {
113-
return nil, err
114-
}
115-
err := gzWriter.Close()
116-
if err != nil {
117-
return nil, err
118-
}
119-
return buffer.Bytes(), nil
120-
}
121-
12297
// getHealthInfoOptionsFromReq gets duration for startHealthInfo request
12398
// path come as : `/health-info?deadline=2h`
12499
func getHealthInfoOptionsFromReq(req *http.Request) (*time.Duration, error) {
@@ -129,49 +104,69 @@ func getHealthInfoOptionsFromReq(req *http.Request) (*time.Duration, error) {
129104
return &deadlineDuration, nil
130105
}
131106

132-
func sendHealthInfoToSubnet(ctx context.Context, healthInfo interface{}, client MinioAdmin) (string, error) {
133-
filename := fmt.Sprintf("health_%d.json", time.Now().Unix())
134-
135-
clientIP := utils.ClientIPFromContext(ctx)
107+
func updateMcGlobals(subnetTokenConfig subnet.LicenseTokenConfig) error {
108+
mc.GlobalDevMode = getConsoleDevMode()
109+
if len(subnetTokenConfig.Proxy) > 0 {
110+
proxyURL, e := url.Parse(subnetTokenConfig.Proxy)
111+
if e != nil {
112+
return e
113+
}
114+
mc.GlobalSubnetProxyURL = proxyURL
115+
}
116+
return nil
117+
}
136118

137-
subnetUploadURL := subnet.UploadURL("health", filename)
138-
subnetHTTPClient := &xhttp.Client{Client: GetConsoleHTTPClient("", clientIP)}
119+
func sendHealthInfoToSubnet(ctx context.Context, healthInfo interface{}, client MinioAdmin) error {
120+
filename := fmt.Sprintf("health_%d.json.gz", time.Now().Unix())
139121
subnetTokenConfig, e := GetSubnetKeyFromMinIOConfig(ctx, client)
140122
if e != nil {
141-
return "", e
123+
return e
124+
}
125+
e = updateMcGlobals(*subnetTokenConfig)
126+
if e != nil {
127+
return e
142128
}
143129
var apiKey string
144130
if len(subnetTokenConfig.APIKey) != 0 {
145131
apiKey = subnetTokenConfig.APIKey
146132
} else {
147133
apiKey, e = subnet.GetSubnetAPIKeyUsingLicense(subnetTokenConfig.License)
148134
if e != nil {
149-
return "", e
135+
return e
150136
}
151137
}
152-
headers := subnet.UploadAuthHeaders(apiKey)
153-
uploadInfo, formDataType, e := subnet.ProcessUploadInfo(healthInfo, "health", filename)
138+
compressedHealthInfo, e := mc.TarGZHealthInfo(healthInfo, madmin.HealthInfoVersion)
154139
if e != nil {
155-
return "", e
140+
return e
156141
}
157-
resp, e := subnet.UploadFileToSubnet(uploadInfo, subnetHTTPClient, subnetUploadURL, headers, formDataType)
158-
142+
e = os.WriteFile(filename, compressedHealthInfo, 0o666)
159143
if e != nil {
160-
return "", e
144+
return e
145+
}
146+
headers := mc.SubnetAPIKeyAuthHeaders(apiKey)
147+
resp, e := (&mc.SubnetFileUploader{
148+
FilePath: filename,
149+
ReqURL: mc.SubnetUploadURL("health"),
150+
Headers: headers,
151+
DeleteAfterUpload: true,
152+
}).UploadFileToSubnet()
153+
if e != nil {
154+
// file gets deleted only if upload is successful
155+
// so we delete explicitly here as we already have the bytes
156+
logger.LogIf(ctx, os.Remove(filename))
157+
return e
161158
}
159+
162160
type SubnetResponse struct {
163-
ClusterURL string `json:"cluster_url,omitempty"`
161+
LicenseV2 string `json:"license_v2,omitempty"`
162+
APIKey string `json:"api_key,omitempty"`
164163
}
165164

166165
var subnetResp SubnetResponse
167166
e = json.Unmarshal([]byte(resp), &subnetResp)
168167
if e != nil {
169-
return "", e
170-
}
171-
if len(subnetResp.ClusterURL) != 0 {
172-
subnetClusterURL := strings.ReplaceAll(subnetResp.ClusterURL, "%2f", "/")
173-
return subnetClusterURL, nil
168+
return e
174169
}
175170

176-
return "", ErrSubnetUploadFail
171+
return nil
177172
}

api/configure_console.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ func replaceBaseInIndex(indexPageBytes []byte, basePath string) []byte {
506506
func replaceLicense(indexPageBytes []byte) []byte {
507507
indexPageStr := string(indexPageBytes)
508508
newPlan := fmt.Sprintf("<meta name=\"minio-license\" content=\"%s\" />", InstanceLicensePlan.String())
509-
indexPageStr = strings.Replace(indexPageStr, "<meta name=\"minio-license\" content=\"apgl\"/>", newPlan, 1)
509+
indexPageStr = strings.Replace(indexPageStr, "<meta name=\"minio-license\" content=\"agpl\"/>", newPlan, 1)
510510
indexPageBytes = []byte(indexPageStr)
511511
return indexPageBytes
512512
}

api/errors.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ var (
7272
ErrEncryptionConfigNotFound = errors.New("encryption configuration not found")
7373
ErrPolicyNotFound = errors.New("policy does not exist")
7474
ErrLoginNotAllowed = errors.New("login not allowed")
75-
ErrSubnetUploadFail = errors.New("SUBNET upload failed")
7675
ErrHealthReportFail = errors.New("failure to generate Health report")
7776
)
7877

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ require (
2121
github.com/minio/cli v1.24.2
2222
github.com/minio/highwayhash v1.0.2
2323
github.com/minio/kes v0.23.0
24-
github.com/minio/madmin-go/v3 v3.0.50-0.20240307075442-63b4fc3ac1fd
25-
github.com/minio/mc v0.0.0-20240320210729-9043bbf545d2
24+
github.com/minio/madmin-go/v3 v3.0.50
25+
github.com/minio/mc v0.0.0-20240330152952-9f8147bf0e03
2626
github.com/minio/minio-go/v7 v7.0.69
2727
github.com/minio/selfupdate v0.6.0
2828
github.com/minio/websocket v1.6.0

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,10 @@ github.com/minio/kes v0.23.0 h1:T0zHtyDoI3JdKrVvzdM4xwVryYYyh5pKwNUVBoqxsNs=
184184
github.com/minio/kes v0.23.0/go.mod h1:vvXVGcgu9mYLkbVWlEvFFl6bYR196RQlOU2Q+rHApl8=
185185
github.com/minio/kes-go v0.2.1 h1:KnqS+p6xoSFJZbQhmJaz/PbxeA6nQyRqT/ywrn5lU2o=
186186
github.com/minio/kes-go v0.2.1/go.mod h1:76xf7l41Wrh+IifisABXK2S8uZWYgWV1IGBKC3GdOJk=
187-
github.com/minio/madmin-go/v3 v3.0.50-0.20240307075442-63b4fc3ac1fd h1:oZycRrLgzEg4+lGZ5Tkua3BKvK7rOtDlmoOR3gq58l4=
188-
github.com/minio/madmin-go/v3 v3.0.50-0.20240307075442-63b4fc3ac1fd/go.mod h1:ZDF7kf5fhmxLhbGTqyq5efs4ao0v4eWf7nOuef/ljJs=
189-
github.com/minio/mc v0.0.0-20240320210729-9043bbf545d2 h1:zF4kiN6HJp4B5IFp+riDA8roY0r+UJV0RvaaVitchH4=
190-
github.com/minio/mc v0.0.0-20240320210729-9043bbf545d2/go.mod h1:YgeY0RTYvbm/H6Gzwb+rpRsQ/XREi3NwITZUcTNATOQ=
187+
github.com/minio/madmin-go/v3 v3.0.50 h1:+RQMetVFvPQmAOEDN/xmLhwk9+xOzu3rqwnlZEskgvg=
188+
github.com/minio/madmin-go/v3 v3.0.50/go.mod h1:ZDF7kf5fhmxLhbGTqyq5efs4ao0v4eWf7nOuef/ljJs=
189+
github.com/minio/mc v0.0.0-20240330152952-9f8147bf0e03 h1:xF1hntqvs/CVEHGBETSrIMTW3iSU3k2j/YCFXGDWoBs=
190+
github.com/minio/mc v0.0.0-20240330152952-9f8147bf0e03/go.mod h1:RMCe706GTL9EOO6pxzFXd9Vp+3w2L1uctPiycmLDr9U=
191191
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
192192
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
193193
github.com/minio/minio-go/v7 v7.0.69 h1:l8AnsQFyY1xiwa/DaQskY4NXSLA2yrGsW5iD9nRPVS0=

pkg/subnet/utils.go

Lines changed: 0 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,11 @@ package subnet
1818

1919
import (
2020
"bytes"
21-
"compress/gzip"
2221
"crypto/tls"
2322
"encoding/base64"
2423
"encoding/json"
25-
"errors"
2624
"fmt"
2725
"io"
28-
"mime/multipart"
2926
"net"
3027
"net/http"
3128
"time"
@@ -79,65 +76,6 @@ func UploadAuthHeaders(apiKey string) map[string]string {
7976
return map[string]string{"x-subnet-api-key": apiKey}
8077
}
8178

82-
func ProcessUploadInfo(info interface{}, uploadType string, filename string) ([]byte, string, error) {
83-
if uploadType == "health" {
84-
return processHealthReport(info, filename)
85-
}
86-
return nil, "", errors.New("invalid SUBNET upload type")
87-
}
88-
89-
func UploadFileToSubnet(info []byte, client *xhttp.Client, reqURL string, headers map[string]string, formDataType string) (string, error) {
90-
req, e := subnetUploadReq(info, reqURL, formDataType)
91-
if e != nil {
92-
return "", e
93-
}
94-
resp, e := subnetReqDo(client, req, headers)
95-
return resp, e
96-
}
97-
98-
func processHealthReport(info interface{}, filename string) ([]byte, string, error) {
99-
var body bytes.Buffer
100-
writer := multipart.NewWriter(&body)
101-
zipWriter := gzip.NewWriter(&body)
102-
version := "3"
103-
enc := json.NewEncoder(zipWriter)
104-
105-
header := struct {
106-
Version string `json:"version"`
107-
}{Version: version}
108-
109-
if e := enc.Encode(header); e != nil {
110-
return nil, "", e
111-
}
112-
113-
if e := enc.Encode(info); e != nil {
114-
return nil, "", e
115-
}
116-
zipWriter.Close()
117-
temp := body
118-
part, e := writer.CreateFormFile("file", filename)
119-
if e != nil {
120-
return nil, "", e
121-
}
122-
if _, e = io.Copy(part, &temp); e != nil {
123-
return nil, "", e
124-
}
125-
126-
writer.Close()
127-
return body.Bytes(), writer.FormDataContentType(), nil
128-
}
129-
130-
func subnetUploadReq(body []byte, url string, formDataType string) (*http.Request, error) {
131-
uploadDataBody := bytes.NewReader(body)
132-
r, e := http.NewRequest(http.MethodPost, url, uploadDataBody)
133-
if e != nil {
134-
return nil, e
135-
}
136-
r.Header.Add("Content-Type", formDataType)
137-
138-
return r, nil
139-
}
140-
14179
func GenerateRegToken(clusterRegInfo mc.ClusterRegistrationInfo) (string, error) {
14280
token, e := json.Marshal(clusterRegInfo)
14381
if e != nil {

web-app/public/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
name="theme-color"
1616
/>
1717
<meta content="MinIO Console" name="description" />
18-
<meta name="minio-license" content="apgl" />
18+
<meta name="minio-license" content="agpl" />
1919
<!--
2020
manifest.json provides metadata used when your web app is installed on a
2121
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/

0 commit comments

Comments
 (0)