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

update query list to query api #68

Merged
merged 2 commits into from
Nov 5, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions cmd/queryList.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ import (
"github.com/spf13/cobra"
)

var outputFlag string

var SavedQueryList = &cobra.Command{
Use: "list",
Example: "pb query list [-o | --output]",
Expand Down
146 changes: 97 additions & 49 deletions pkg/model/savedQueries.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"fmt"
"io"
"net/http"
"os/exec"
"strings"
"time"

Expand Down Expand Up @@ -180,6 +179,7 @@ type modelSavedQueries struct {
list list.Model
commandOutput string
viewport viewport.Model
queryExecuted bool // New field to track query execution
}

func (m modelSavedQueries) Init() tea.Cmd {
Expand All @@ -189,93 +189,93 @@ func (m modelSavedQueries) Init() tea.Cmd {
// Define a message type for command results
type commandResultMsg string

// RunCommand executes a command based on the selected item
func RunCommand(item Item) (string, error) {
// Clean the description by removing any backslashes
cleaned := strings.ReplaceAll(item.desc, "\\", "") // Remove any backslashes
cleaned = strings.TrimSpace(cleaned) // Trim any leading/trailing whitespace
cleanedStr := strings.ReplaceAll(cleaned, `"`, "")
func (m modelSavedQueries) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "ctrl+c":
return m, tea.Quit

// Prepare the command with the cleaned SQL query
fmt.Printf("Executing command: pb query run %s\n", cleanedStr) // Log the command for debugging
case "a", "enter":
// Only execute if a query hasn't already been run
if m.queryExecuted {
return m, nil // Skip execution if already executed
}
selectedQueryApply := m.list.SelectedItem().(Item)
m.queryExecuted = true // Mark as executed

if item.StartTime() != "" && item.EndTime() != "" {
cleanedStr = cleanedStr + " --from=" + item.StartTime() + " --to=" + item.EndTime()
}
cmd := exec.Command("pb", "query", "run", cleanedStr) // Directly pass cleaned
cmd := func() tea.Msg {
// Load user profile configuration
userConfig, err := config.ReadConfigFromFile()
if err != nil {
return commandResultMsg(fmt.Sprintf("Error: %s", err))
}

// Set up pipes to capture stdout and stderr
var output bytes.Buffer
cmd.Stdout = &output
cmd.Stderr = &output // Capture both stdout and stderr in the same buffer
profile, profileExists := userConfig.Profiles[userConfig.DefaultProfile]
if !profileExists {
return commandResultMsg("Error: Profile not found")
}

// Run the command
err := cmd.Run()
if err != nil {
return "", fmt.Errorf("error executing command: %v, output: %s", err, output.String())
}
// Clean the query string
cleanedQuery := strings.TrimSpace(strings.ReplaceAll(selectedQueryApply.desc, `\`, ""))
cleanedQuery = strings.ReplaceAll(cleanedQuery, `"`, "")

// Log the raw output for debugging
fmt.Printf("Raw output: %s\n", output.String())
// Log the command for debugging
fmt.Printf("Executing command: pb query run %s\n", cleanedQuery)

// Format the output as pretty-printed JSON
var jsonResponse interface{}
if err := json.Unmarshal(output.Bytes(), &jsonResponse); err != nil {
return "", fmt.Errorf("invalid JSON output: %s, error: %v", output.String(), err)
}
// Prepare HTTP client
client := &http.Client{Timeout: 60 * time.Second}

prettyOutput, err := json.MarshalIndent(jsonResponse, "", " ")
if err != nil {
return "", fmt.Errorf("error formatting JSON output: %v", err)
}
// Determine query time range
startTime := selectedQueryApply.StartTime()
endTime := selectedQueryApply.EndTime()

// Return the output as a string
return string(prettyOutput), nil
}
// If start and end times are not set, use a default range
if startTime == "" && endTime == "" {
startTime = "10m"
endTime = "now"
}

func (m modelSavedQueries) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "ctrl+c":
return m, tea.Quit
case "a", "enter":
// Apply the selected query
selectedQueryApply = m.list.SelectedItem().(Item)
cmd := func() tea.Msg {
output, err := RunCommand(selectedQueryApply)
// Run the query
data, err := RunQuery(client, &profile, cleanedQuery, startTime, endTime)
if err != nil {
return commandResultMsg(fmt.Sprintf("Error: %s", err))
}
return commandResultMsg(output)
return commandResultMsg(data)
}
return m, cmd

case "b": // 'b' to go back to the saved query list
m.commandOutput = "" // Clear the command output
m.viewport.SetContent("") // Clear viewport content
m.viewport.GotoTop() // Reset viewport to the top
m.queryExecuted = false // Reset the execution flag to allow a new query
return m, nil

case "down", "j":
m.viewport.LineDown(1) // Scroll down in the viewport

case "up", "k":
m.viewport.LineUp(1) // Scroll up in the viewport
}

case tea.WindowSizeMsg:
h, v := docStyle.GetFrameSize()
m.list.SetSize(msg.Width-h, msg.Height-v)
m.viewport.Width = msg.Width - h
m.viewport.Height = msg.Height - v

case commandResultMsg:
m.commandOutput = string(msg)
m.viewport.SetContent(m.commandOutput) // Update viewport content with command output
return m, nil
}

// Update the list and return
var cmd tea.Cmd
m.list, cmd = m.list.Update(msg)
return m, cmd
}

func (m modelSavedQueries) View() string {
if m.commandOutput != "" {
return m.viewport.View()
Expand Down Expand Up @@ -367,3 +367,51 @@ func QueryToApply() Item {
func QueryToDelete() Item {
return selectedQueryDelete
}

func RunQuery(client *http.Client, profile *config.Profile, query string, startTime string, endTime string) (string, error) {
queryTemplate := `{
"query": "%s",
"startTime": "%s",
"endTime": "%s"
}`

finalQuery := fmt.Sprintf(queryTemplate, query, startTime, endTime)

endpoint := fmt.Sprintf("%s/%s", profile.URL, "api/v1/query")
req, err := http.NewRequest("POST", endpoint, bytes.NewBuffer([]byte(finalQuery)))
if err != nil {
return "", err
}
req.SetBasicAuth(profile.Username, profile.Password)
req.Header.Add("Content-Type", "application/json")

resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()

if resp.StatusCode == http.StatusOK {
var jsonResponse []map[string]interface{}

// Read and parse the JSON response
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}

// Decode JSON into a map
if err := json.Unmarshal(body, &jsonResponse); err != nil {
return "", err
}

// Pretty-print the JSON response
jsonData, err := json.MarshalIndent(jsonResponse, "", " ")
if err != nil {
return "", err
}
return string(jsonData), nil
}

return "", fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}
Loading