diff --git a/pkg/subnet/utils.go b/pkg/subnet/utils.go index aeaddcaf2..0a11122f8 100644 --- a/pkg/subnet/utils.go +++ b/pkg/subnet/utils.go @@ -18,11 +18,13 @@ package subnet import ( "bytes" + "compress/gzip" "encoding/base64" "encoding/json" "fmt" "io" "io/ioutil" + "mime/multipart" "net/http" xhttp "github.com/minio/console/pkg/http" @@ -64,6 +66,62 @@ func LogWebhookURL() string { return subnetBaseURL() + "/api/logs" } +func UploadURL(uploadType string, filename string) string { + return fmt.Sprintf("%s/api/%s/upload?filename=%s", subnetBaseURL(), uploadType, filename) +} + +func UploadAuthHeaders(apiKey string) map[string]string { + return map[string]string{"x-subnet-api-key": apiKey} +} + +func UploadFileToSubnet(info interface{}, client *xhttp.Client, filename string, reqURL string, headers map[string]string) (string, error) { + req, e := subnetUploadReq(info, reqURL, filename) + if e != nil { + return "", e + } + resp, e := subnetReqDo(client, req, headers) + return resp, e +} + +func subnetUploadReq(info interface{}, url string, filename string) (*http.Request, error) { + var body bytes.Buffer + writer := multipart.NewWriter(&body) + zipWriter := gzip.NewWriter(&body) + version := "3" + enc := json.NewEncoder(zipWriter) + + header := struct { + Version string `json:"version"` + }{Version: version} + + if e := enc.Encode(header); e != nil { + return nil, e + } + + if e := enc.Encode(info); e != nil { + return nil, e + } + zipWriter.Close() + temp := body + part, e := writer.CreateFormFile("file", filename) + if e != nil { + return nil, e + } + if _, e = io.Copy(part, &temp); e != nil { + return nil, e + } + + writer.Close() + + r, e := http.NewRequest(http.MethodPost, url, &body) + if e != nil { + return nil, e + } + r.Header.Add("Content-Type", writer.FormDataContentType()) + + return r, nil +} + func GenerateRegToken(clusterRegInfo mc.ClusterRegistrationInfo) (string, error) { token, e := json.Marshal(clusterRegInfo) if e != nil { diff --git a/portal-ui/src/screens/Console/HealthInfo/HealthInfo.tsx b/portal-ui/src/screens/Console/HealthInfo/HealthInfo.tsx index 060130a50..f1cf47cce 100644 --- a/portal-ui/src/screens/Console/HealthInfo/HealthInfo.tsx +++ b/portal-ui/src/screens/Console/HealthInfo/HealthInfo.tsx @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . import React, { Fragment, useEffect, useState } from "react"; -import clsx from "clsx"; + import { ICloseEvent, IMessageEvent, @@ -72,7 +72,7 @@ const styles = (theme: Theme) => color: "#07193E", fontWeight: "bold", textAlign: "center", - marginBottom: 10, + marginBottom: 20, }, progressResult: { textAlign: "center", @@ -94,8 +94,6 @@ const styles = (theme: Theme) => interface IHealthInfo { classes: any; - namespace: string; - tenant: string; } const HealthInfo = ({ classes }: IHealthInfo) => { @@ -104,22 +102,19 @@ const HealthInfo = ({ classes }: IHealthInfo) => { const message = useSelector((state: AppState) => state.healthInfo.message); - const clusterRegistered = registeredCluster(); - const serverDiagnosticStatus = useSelector( (state: AppState) => state.system.serverDiagnosticStatus ); const [startDiagnostic, setStartDiagnostic] = useState(false); + const [downloadDisabled, setDownloadDisabled] = useState(true); const [localMessage, setMessage] = useState(""); const [buttonStartText, setButtonStartText] = useState("Start Diagnostic"); const [title, setTitle] = useState("New Diagnostic"); const [diagFileContent, setDiagFileContent] = useState(""); - - const isDiagnosticComplete = - serverDiagnosticStatus === DiagStatSuccess || - serverDiagnosticStatus === DiagStatError; + const [subnetResponse, setSubnetResponse] = useState(""); + const clusterRegistered = registeredCluster(); const download = () => { let element = document.createElement("a"); @@ -195,7 +190,6 @@ const HealthInfo = ({ classes }: IHealthInfo) => { const c = new W3CWebSocket( `${wsProt}://${url.hostname}:${port}${baseUrl}ws/health-info?deadline=1h` ); - let interval: any | null = null; if (c !== null) { c.onopen = () => { @@ -220,6 +214,9 @@ const HealthInfo = ({ classes }: IHealthInfo) => { if (m.encoded !== "") { setDiagFileContent(m.encoded); } + if (m.subnetResponse) { + setSubnetResponse(m.subnetResponse); + } }; c.onerror = (error: Error) => { console.log("error closing websocket:", error.message); @@ -275,38 +272,70 @@ const HealthInfo = ({ classes }: IHealthInfo) => { className={classes.progressResult} >
{localMessage}
+
+ {" "} + {subnetResponse !== "" && + !subnetResponse.toLowerCase().includes("error") && ( + + + Health report uploaded to Subnet successfully! + +  {" "} + + See the results on your{" "} + Subnet Dashboard{" "} + + + )} + {(subnetResponse === "" || + subnetResponse.toLowerCase().includes("error")) && + serverDiagnosticStatus === DiagStatSuccess && ( + + + Something went wrong uploading your Health report to + Subnet. + +  {" "} + + Log into your{" "} + Subnet Account to + manually upload your Health report. + + + )} +
{serverDiagnosticStatus === DiagStatInProgress ? (
) : ( - {serverDiagnosticStatus !== DiagStatError && - !downloadDisabled && ( + + + {serverDiagnosticStatus !== DiagStatError && + !downloadDisabled && ( +