- 
                Notifications
    
You must be signed in to change notification settings  - Fork 1
 
fix: Run exec agent #11
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
base: main
Are you sure you want to change the base?
Changes from 2 commits
8223bd0
              01bc449
              e1a6568
              2d98dd4
              2d395fb
              f01a216
              eae19f1
              df80fe2
              a29b566
              ab92d45
              6d1fda9
              6e6e77c
              840e166
              3660019
              f51d8d4
              5160555
              c6fdca4
              09ccdc6
              33ea1ad
              File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| 
          
            
          
           | 
    @@ -3,29 +3,60 @@ package exec | |
| import ( | ||
| "fmt" | ||
| 
     | 
||
| "github.com/MakeNowJust/heredoc/v2" | ||
| "github.com/charmbracelet/log" | ||
| "github.com/ctrlplanedev/cli/internal/api" | ||
| "github.com/ctrlplanedev/cli/pkg/jobagent" | ||
| "github.com/spf13/cobra" | ||
| "github.com/spf13/viper" | ||
| ) | ||
| 
     | 
||
| type JobAgentType string | ||
| 
     | 
||
| const ( | ||
| JobAgentTypeLinux JobAgentType = "exec-linux" | ||
| JobAgentTypeWindows JobAgentType = "exec-windows" | ||
| ) | ||
| 
     | 
||
| func NewRunExecCmd() *cobra.Command { | ||
| return &cobra.Command{ | ||
| var name string | ||
| var jobAgentType string | ||
| 
     | 
||
| cmd := &cobra.Command{ | ||
| Use: "exec", | ||
| Short: "Execute commands directly when a job is received", | ||
| Example: heredoc.Doc(` | ||
| $ ctrlc run exec --name "my-script-agent" --workspace 123e4567-e89b-12d3-a456-426614174000 | ||
| $ ctrlc run exec --name "my-script-agent" --workspace 123e4567-e89b-12d3-a456-426614174000 --type windows | ||
                
      
                  zacharyblasczyk marked this conversation as resolved.
               
              
                Outdated
          
            Show resolved
            Hide resolved
                
      
                  zacharyblasczyk marked this conversation as resolved.
               
              
                Outdated
          
            Show resolved
            Hide resolved
         | 
||
| `), | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| apiURL := viper.GetString("url") | ||
| apiKey := viper.GetString("api-key") | ||
| workspaceId := viper.GetString("workspace") | ||
| client, err := api.NewAPIKeyClientWithResponses(apiURL, apiKey) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to create API client: %w", err) | ||
| } | ||
| if name == "" { | ||
| 
         There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could move input validation above the client creation?  | 
||
| return fmt.Errorf("name is required") | ||
| } | ||
| if workspaceId == "" { | ||
| return fmt.Errorf("workspace is required") | ||
| } | ||
| validTypes := map[string]bool{ | ||
| string(JobAgentTypeLinux): true, | ||
| string(JobAgentTypeWindows): true, | ||
| } | ||
| if !validTypes[jobAgentType] { | ||
| return fmt.Errorf("invalid type: %s. Must be one of: linux, windows", jobAgentType) | ||
| } | ||
                
      
                  zacharyblasczyk marked this conversation as resolved.
               
              
                Outdated
          
            Show resolved
            Hide resolved
         | 
||
| 
     | 
||
| ja, err := jobagent.NewJobAgent( | ||
| client, | ||
| api.UpsertJobAgentJSONRequestBody{ | ||
| Name: "exec", | ||
| Type: "exec", | ||
| Name: name, | ||
| Type: jobAgentType, | ||
| WorkspaceId: workspaceId, | ||
| }, | ||
| &ExecRunner{}, | ||
| ) | ||
| 
        
          
        
         | 
    @@ -41,4 +72,9 @@ func NewRunExecCmd() *cobra.Command { | |
| return nil | ||
| }, | ||
| } | ||
| 
     | 
||
| cmd.Flags().StringVar(&name, "name", "", "Name of the job agent") | ||
| cmd.MarkFlagRequired("name") | ||
| cmd.Flags().StringVar(&jobAgentType, "type", "exec-linux", "Type of the job agent, defaults to linux") | ||
| return cmd | ||
| } | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| 
          
            
          
           | 
    @@ -2,6 +2,7 @@ package exec | |
| 
     | 
||
| import ( | ||
| "bytes" | ||
| "context" | ||
| "encoding/json" | ||
| "fmt" | ||
| "html/template" | ||
| 
        
          
        
         | 
    @@ -13,6 +14,7 @@ import ( | |
| 
     | 
||
| "github.com/ctrlplanedev/cli/internal/api" | ||
| "github.com/ctrlplanedev/cli/pkg/jobagent" | ||
| "github.com/spf13/viper" | ||
| ) | ||
| 
     | 
||
| var _ jobagent.Runner = &ExecRunner{} | ||
| 
        
          
        
         | 
    @@ -25,6 +27,10 @@ type ExecConfig struct { | |
| } | ||
| 
     | 
||
| func (r *ExecRunner) Status(job api.Job) (api.JobStatus, string) { | ||
                
       | 
||
| if job.ExternalId == nil { | ||
| return api.JobStatusExternalRunNotFound, fmt.Sprintf("external ID is nil: %v", job.ExternalId) | ||
| } | ||
| 
     | 
||
| externalId, err := strconv.Atoi(*job.ExternalId) | ||
| if err != nil { | ||
| return api.JobStatusExternalRunNotFound, fmt.Sprintf("invalid process id: %v", err) | ||
| 
          
            
          
           | 
    @@ -67,13 +73,34 @@ func (r *ExecRunner) Start(job api.Job) (string, error) { | |
| return "", fmt.Errorf("failed to unmarshal job agent config: %w", err) | ||
| } | ||
| 
     | 
||
| client, err := api.NewAPIKeyClientWithResponses( | ||
| viper.GetString("url"), | ||
| viper.GetString("api-key"), | ||
| ) | ||
                
      
                  zacharyblasczyk marked this conversation as resolved.
               
              
                Outdated
          
            Show resolved
            Hide resolved
         | 
||
| if err != nil { | ||
| return "", fmt.Errorf("failed to create API client for job details: %w", err) | ||
| } | ||
| 
     | 
||
| resp, err := client.GetJobWithResponse(context.Background(), job.Id.String()) | ||
| if err != nil { | ||
| return "", fmt.Errorf("failed to get job details: %w", err) | ||
| } | ||
| 
     | 
||
| if resp.JSON200 == nil { | ||
| return "", fmt.Errorf("received empty response from job details API") | ||
| } | ||
| 
     | 
||
| var jobDetails map[string]interface{} | ||
| detailsBytes, _ := json.Marshal(resp.JSON200) | ||
| json.Unmarshal(detailsBytes, &jobDetails) | ||
| 
     | 
||
                
      
                  coderabbitai[bot] marked this conversation as resolved.
               
              
                Outdated
          
            Show resolved
            Hide resolved
         | 
||
| templatedScript, err := template.New("script").Parse(config.Script) | ||
| if err != nil { | ||
| return "", fmt.Errorf("failed to parse script template: %w", err) | ||
| } | ||
| 
     | 
||
| buf := new(bytes.Buffer) | ||
| if err := templatedScript.Execute(buf, job); err != nil { | ||
| if err := templatedScript.Execute(buf, jobDetails); err != nil { | ||
                
       | 
||
| return "", fmt.Errorf("failed to execute script template: %w", err) | ||
| } | ||
| script := buf.String() | ||
| 
          
            
          
           | 
    ||
Uh oh!
There was an error while loading. Please reload this page.