Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

move getSupportBundle query to go #868

Merged
merged 1 commit into from
Jul 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions kotsadm/pkg/apiserver/server.go
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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.
sgalsaleh marked this conversation as resolved.
Show resolved Hide resolved
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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);