Skip to content

Commit

Permalink
move getSupportBundle query to go
Browse files Browse the repository at this point in the history
  • Loading branch information
sgalsaleh committed Jul 28, 2020
1 parent d64c457 commit cc1191c
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 20 deletions.
1 change: 1 addition & 0 deletions kotsadm/pkg/apiserver/server.go
Expand Up @@ -66,6 +66,7 @@ func Start() {
// Support Bundles
r.Path("/api/v1/troubleshoot").Methods("OPTIONS", "GET").HandlerFunc(handlers.GetDefaultTroubleshoot)
r.Path("/api/v1/troubleshoot/{appSlug}").Methods("OPTIONS", "GET").HandlerFunc(handlers.GetTroubleshoot)
r.Path("/api/v1/troubleshoot/supportbundle/{bundleSlug}").Methods("OPTIONS", "GET").HandlerFunc(handlers.GetSupportBundle)
r.Path("/api/v1/troubleshoot/{appId}/{bundleId}").Methods("OPTIONS", "PUT").HandlerFunc(handlers.UploadSupportBundle)
r.Path("/api/v1/troubleshoot/app/{appSlug}/supportbundles").Methods("OPTIONS", "GET").HandlerFunc(handlers.ListSupportBundles)
r.Path("/api/v1/troubleshoot/supportbundle/{bundleId}/files").Methods("OPTIONS", "GET").HandlerFunc(handlers.GetSupportBundleFiles)
Expand Down
74 changes: 74 additions & 0 deletions kotsadm/pkg/handlers/troubleshoot.go
Expand Up @@ -39,6 +39,21 @@ import (
"k8s.io/client-go/kubernetes/scheme"
)

type GetSupportBundleResponse struct {
ID string `json:"id"`
Slug string `json:"slug"`
AppID string `json:"appId"`
Name string `json:"name"`
Size float64 `json:"size"`
Status string `json:"status"`
TreeIndex string `json:"treeIndex"`
CreatedAt time.Time `json:"createdAt"`
UploadedAt *time.Time `json:"uploadedAt"`
IsArchived bool `json:"isArchived"`
LicenseType string `json:"licenseType,omitempty"`
Analysis *types.SupportBundleAnalysis `json:"analysis"`
}

type GetSupportBundleFilesResponse struct {
Files map[string][]byte `json:"files"`

Expand Down Expand Up @@ -74,6 +89,65 @@ type PutSupportBundleRedactions struct {
Redactions redact2.RedactionList `json:"redactions"`
}

func GetSupportBundle(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "content-type, origin, accept, authorization")

if r.Method == "OPTIONS" {
w.WriteHeader(200)
return
}

sess, err := session.Parse(r.Header.Get("Authorization"))
if err != nil {
logger.Error(err)
w.WriteHeader(401)
return
}

// we don't currently have roles, all valid tokens are valid sessions
if sess == nil || sess.ID == "" {
w.WriteHeader(401)
return
}

bundleSlug := mux.Vars(r)["bundleSlug"]

bundle, err := supportbundle.GetFromSlug(bundleSlug)
if err != nil {
logger.Error(err)
w.WriteHeader(500)
return
}

licenseType, err := supportbundle.GetLicenseType(bundle.ID)
if err != nil {
logger.Error(errors.Wrapf(err, "failed to get license type for bundle %s", bundle.Slug))
}

analysis, err := supportbundle.GetBundleAnalysis(bundle.ID)
if err != nil {
logger.Error(errors.Wrapf(err, "failed to get analysis for bundle %s", bundle.Slug))
}

getSupportBundleResponse := GetSupportBundleResponse{
ID: bundle.ID,
Slug: bundle.Slug,
AppID: bundle.AppID,
Name: bundle.Name,
Size: bundle.Size,
Status: bundle.Status,
TreeIndex: bundle.TreeIndex,
CreatedAt: bundle.CreatedAt,
UploadedAt: bundle.UploadedAt,
IsArchived: bundle.IsArchived,
LicenseType: licenseType,
Analysis: analysis,
}

JSON(w, 200, getSupportBundleResponse)
}

func GetSupportBundleFiles(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "content-type, origin, accept, authorization")
Expand Down
45 changes: 45 additions & 0 deletions kotsadm/pkg/supportbundle/supportbundle.go
Expand Up @@ -21,6 +21,7 @@ import (

func List(appID string) ([]*types.SupportBundle, error) {
db := persistence.MustGetPGSession()
// DANGER ZONE: changing sort order here affects what support bundle is shown in the analysis view.
query := `select id, slug, watch_id, name, size, status, created_at, uploaded_at, is_archived from supportbundle where watch_id = $1 order by created_at desc`

rows, err := db.Query(query, appID)
Expand Down Expand Up @@ -55,6 +56,50 @@ func List(appID string) ([]*types.SupportBundle, error) {
return supportBundles, nil
}

func GetFromSlug(slug string) (*types.SupportBundle, error) {
db := persistence.MustGetPGSession()
query := `select id from supportbundle where slug = $1`
row := db.QueryRow(query, slug)

id := ""
if err := row.Scan(&id); err != nil {
if err == sql.ErrNoRows {
return nil, nil
}
return nil, errors.Wrap(err, "failed to scan id")
}

return Get(id)
}

func Get(id string) (*types.SupportBundle, error) {
db := persistence.MustGetPGSession()
query := `select id, slug, watch_id, name, size, status, tree_index, created_at, uploaded_at, is_archived from supportbundle where slug = $1`
row := db.QueryRow(query, id)

var name sql.NullString
var size sql.NullFloat64
var treeIndex sql.NullString
var uploadedAt sql.NullTime
var isArchived sql.NullBool

s := &types.SupportBundle{}
if err := row.Scan(&s.ID, &s.Slug, &s.AppID, &name, &size, &s.Status, &treeIndex, &s.CreatedAt, &uploadedAt, &isArchived); err != nil {
return nil, errors.Wrap(err, "failed to scan")
}

s.Name = name.String
s.Size = size.Float64
s.TreeIndex = treeIndex.String
s.IsArchived = isArchived.Bool

if uploadedAt.Valid {
s.UploadedAt = &uploadedAt.Time
}

return s, nil
}

func CreateBundle(requestedID string, appID string, archivePath string) (*types.SupportBundle, error) {
fi, err := os.Stat(archivePath)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions kotsadm/pkg/supportbundle/types/types.go
Expand Up @@ -11,6 +11,7 @@ type SupportBundle struct {
Name string `json:"name"`
Size float64 `json:"size"`
Status string `json:"status"`
TreeIndex string `json:"treeIndex,omitempty"`
CreatedAt time.Time `json:"createdAt"`
UploadedAt *time.Time `json:"uploadedAt"`
IsArchived bool `json:"isArchived"`
Expand Down
56 changes: 36 additions & 20 deletions kotsadm/web/src/components/troubleshoot/SupportBundleAnalysis.jsx
@@ -1,13 +1,11 @@
import * as React from "react";
import { withRouter, Switch, Route, Link } from "react-router-dom";
import { graphql, compose, withApollo } from "react-apollo";
import dayjs from "dayjs";

import Loader from "../shared/Loader";
import AnalyzerInsights from "./AnalyzerInsights";
import AnalyzerFileTree from "./AnalyzerFileTree";
import AnalyzerRedactorReport from "./AnalyzerRedactorReport";
import { getSupportBundle } from "../../queries/TroubleshootQueries";
import { Utilities } from "../../utilities/utilities";
import "../../scss/components/troubleshoot/SupportBundleAnalysis.scss";
import download from "downloadjs";
Expand All @@ -18,7 +16,9 @@ export class SupportBundleAnalysis extends React.Component {
this.state = {
activeTab: props.location.pathname.indexOf("/contents") !== -1 ? "fileTree" : location.pathname.indexOf("/redactor") !== -1 ? "redactorReport" : "bundleAnalysis",
filterTiles: "0",
downloadingBundle: false
downloadingBundle: false,
bundle: null,
loading: false,
};
}

Expand All @@ -43,12 +43,39 @@ export class SupportBundleAnalysis extends React.Component {
})
}

getSupportBundle = async () => {
this.setState({ loading: true });

fetch(`${window.env.API_ENDPOINT}/troubleshoot/supportbundle/${this.props.match.params.bundleSlug}`, {
headers: {
"Content-Type": "application/json",
"Authorization": Utilities.getToken(),
},
method: "GET",
})
.then(async (res) => {
const bundle = await res.json();
this.setState({
bundle: bundle,
loading: false,
});
})
.catch((err) => {
console.log(err);
this.setState({ loading: false });
});
}

toggleAnalysisAction = (active) => {
this.setState({
activeTab: active,
});
}

componentDidMount() {
this.getSupportBundle();
}

componentDidUpdate = (lastProps) => {
const { location } = this.props;
if (location !== lastProps.location) {
Expand All @@ -59,10 +86,10 @@ export class SupportBundleAnalysis extends React.Component {
}

render() {
const { watch, getSupportBundle } = this.props;
const bundle = getSupportBundle?.getSupportBundle;
const { watch } = this.props;
const { bundle, loading } = this.state;

if (getSupportBundle.loading) {
if (loading) {
return (
<div className="flex-column flex1 justifyContent--center alignItems--center">
<Loader size="60" />
Expand Down Expand Up @@ -104,7 +131,7 @@ export class SupportBundleAnalysis extends React.Component {
</div>
</div>
</div>
{bundle.kotsLicenseType === "community" &&
{bundle.licenseType === "community" &&
<div className="flex">
<div className="CommunityLicenseBundle--wrapper flex flex1 alignItems--center">
<div className="flex flex-auto">
Expand All @@ -131,7 +158,7 @@ export class SupportBundleAnalysis extends React.Component {
<Route exact path={insightsUrl} render={() =>
<AnalyzerInsights
status={bundle.status}
refetchSupportBundle={this.props.getSupportBundle.refetch}
refetchSupportBundle={this.getSupportBundle}
insights={bundle.analysis?.insights}
/>
} />
Expand Down Expand Up @@ -160,15 +187,4 @@ export class SupportBundleAnalysis extends React.Component {
}
}

export default withRouter(compose(
withApollo,
graphql(getSupportBundle, {
name: "getSupportBundle",
options: ({ match }) => ({
variables: {
watchSlug: match.params.bundleSlug
},
fetchPolicy: "no-cache"
}),
})
)(SupportBundleAnalysis));
export default withRouter(SupportBundleAnalysis);

0 comments on commit cc1191c

Please sign in to comment.