mirror of
https://github.com/turbot/steampipe.git
synced 2026-02-27 02:00:52 -05:00
146 lines
4.3 KiB
Go
146 lines
4.3 KiB
Go
package cloud
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"path"
|
|
"strings"
|
|
|
|
"github.com/spf13/viper"
|
|
steampipecloud "github.com/turbot/steampipe-cloud-sdk-go"
|
|
"github.com/turbot/steampipe/pkg/constants"
|
|
"github.com/turbot/steampipe/pkg/dashboard/dashboardtypes"
|
|
"github.com/turbot/steampipe/pkg/export"
|
|
"github.com/turbot/steampipe/pkg/steampipeconfig"
|
|
"github.com/turbot/steampipe/sperr"
|
|
)
|
|
|
|
func PublishSnapshot(ctx context.Context, snapshot *dashboardtypes.SteampipeSnapshot, share bool) (string, error) {
|
|
snapshotLocation := viper.GetString(constants.ArgSnapshotLocation)
|
|
// snapshotLocation must be set (validation should ensure this)
|
|
if snapshotLocation == "" {
|
|
return "", sperr.New("to share a snapshot, snapshot-location must be set")
|
|
}
|
|
|
|
// if snapshot location is a workspace handle, upload it
|
|
if steampipeconfig.IsCloudWorkspaceIdentifier(snapshotLocation) {
|
|
url, err := uploadSnapshot(ctx, snapshot, share)
|
|
if err != nil {
|
|
return "", sperr.Wrap(err)
|
|
}
|
|
return fmt.Sprintf("\nSnapshot uploaded to %s\n", url), nil
|
|
}
|
|
|
|
// otherwise assume snapshot location is a file path
|
|
filePath, err := exportSnapshot(snapshot)
|
|
if err != nil {
|
|
return "", sperr.Wrap(err)
|
|
}
|
|
return fmt.Sprintf("\nSnapshot saved to %s\n", filePath), nil
|
|
}
|
|
|
|
func exportSnapshot(snapshot *dashboardtypes.SteampipeSnapshot) (string, error) {
|
|
exporter := &export.SnapshotExporter{}
|
|
|
|
fileName := export.GenerateDefaultExportFileName(snapshot.FileNameRoot, exporter.FileExtension())
|
|
dirName := viper.GetString(constants.ArgSnapshotLocation)
|
|
filePath := path.Join(dirName, fileName)
|
|
|
|
err := exporter.Export(context.Background(), snapshot, filePath)
|
|
if err != nil {
|
|
return "", sperr.Wrap(err)
|
|
}
|
|
return filePath, nil
|
|
}
|
|
|
|
func uploadSnapshot(ctx context.Context, snapshot *dashboardtypes.SteampipeSnapshot, share bool) (string, error) {
|
|
client := newSteampipeCloudClient(viper.GetString(constants.ArgCloudToken))
|
|
|
|
cloudWorkspace := viper.GetString(constants.ArgSnapshotLocation)
|
|
parts := strings.Split(cloudWorkspace, "/")
|
|
if len(parts) != 2 {
|
|
return "", sperr.New("failed to resolve username and workspace handle from workspace %s", cloudWorkspace)
|
|
}
|
|
identityHandle := parts[0]
|
|
workspaceHandle := parts[1]
|
|
|
|
// no determine whether this is a user or org workspace
|
|
// get the identity
|
|
identity, _, err := client.Identities.Get(ctx, identityHandle).Execute()
|
|
if err != nil {
|
|
return "", sperr.Wrap(err)
|
|
}
|
|
|
|
workspaceType := identity.Type
|
|
|
|
// set the visibility
|
|
visibility := "workspace"
|
|
if share {
|
|
visibility = "anyone_with_link"
|
|
}
|
|
|
|
// resolve the snapshot title
|
|
title := resolveSnapshotTitle(snapshot)
|
|
log.Printf("[TRACE] Uploading snapshot with title %s", title)
|
|
// populate map of tags tags been set?
|
|
tags := getTags()
|
|
|
|
cloudSnapshot, err := snapshot.AsCloudSnapshot()
|
|
if err != nil {
|
|
return "", sperr.Wrap(err)
|
|
}
|
|
|
|
// strip verbose/sensitive fields
|
|
dashboardtypes.StripSnapshot(cloudSnapshot)
|
|
|
|
req := steampipecloud.CreateWorkspaceSnapshotRequest{Data: *cloudSnapshot, Tags: tags, Visibility: &visibility}
|
|
req.SetTitle(title)
|
|
|
|
var uploadedSnapshot steampipecloud.WorkspaceSnapshot
|
|
if identity.Type == "user" {
|
|
uploadedSnapshot, _, err = client.UserWorkspaceSnapshots.Create(ctx, identityHandle, workspaceHandle).Request(req).Execute()
|
|
} else {
|
|
uploadedSnapshot, _, err = client.OrgWorkspaceSnapshots.Create(ctx, identityHandle, workspaceHandle).Request(req).Execute()
|
|
}
|
|
if err != nil {
|
|
return "", sperr.Wrap(err)
|
|
}
|
|
|
|
snapshotId := uploadedSnapshot.Id
|
|
snapshotUrl := fmt.Sprintf("https://%s/%s/%s/workspace/%s/snapshot/%s",
|
|
viper.GetString(constants.ArgCloudHost),
|
|
workspaceType,
|
|
identityHandle,
|
|
workspaceHandle,
|
|
snapshotId)
|
|
|
|
return snapshotUrl, nil
|
|
}
|
|
|
|
func resolveSnapshotTitle(snapshot *dashboardtypes.SteampipeSnapshot) string {
|
|
if titleArg := viper.GetString(constants.ArgSnapshotTitle); titleArg != "" {
|
|
return titleArg
|
|
}
|
|
// is there a title property set on the snapshot
|
|
if snapshotTitle := snapshot.Title; snapshotTitle != "" {
|
|
return snapshotTitle
|
|
}
|
|
// fall back to the fully qualified name of the root resource (which is also the FileNameRoot)
|
|
return snapshot.FileNameRoot
|
|
}
|
|
|
|
func getTags() map[string]any {
|
|
tags := viper.GetStringSlice(constants.ArgSnapshotTag)
|
|
res := map[string]any{}
|
|
|
|
for _, tagStr := range tags {
|
|
parts := strings.Split(tagStr, "=")
|
|
if len(parts) != 2 {
|
|
continue
|
|
}
|
|
res[parts[0]] = parts[1]
|
|
}
|
|
return res
|
|
}
|