2024-01-17 14:26:33 +00:00
package generate
import (
2024-11-20 12:53:25 +00:00
"errors"
2024-01-17 14:26:33 +00:00
"fmt"
2024-11-20 12:53:25 +00:00
"io/fs"
2024-01-17 14:26:33 +00:00
"os"
"path/filepath"
"github.com/databricks/cli/bundle/config/generate"
"github.com/databricks/cli/cmd/root"
"github.com/databricks/cli/libs/cmdio"
"github.com/databricks/cli/libs/dyn"
"github.com/databricks/cli/libs/dyn/yamlsaver"
"github.com/databricks/cli/libs/textutil"
"github.com/databricks/databricks-sdk-go/service/jobs"
"github.com/spf13/cobra"
2024-02-15 15:03:19 +00:00
"gopkg.in/yaml.v3"
2024-01-17 14:26:33 +00:00
)
func NewGenerateJobCommand ( ) * cobra . Command {
var configDir string
var sourceDir string
var jobId int64
var force bool
cmd := & cobra . Command {
2024-03-28 10:32:34 +00:00
Use : "job" ,
Short : "Generate bundle configuration for a job" ,
2024-01-17 14:26:33 +00:00
}
cmd . Flags ( ) . Int64Var ( & jobId , "existing-job-id" , 0 , ` Job ID of the job to generate config for ` )
cmd . MarkFlagRequired ( "existing-job-id" )
wd , err := os . Getwd ( )
if err != nil {
wd = "."
}
cmd . Flags ( ) . StringVarP ( & configDir , "config-dir" , "d" , filepath . Join ( wd , "resources" ) , ` Dir path where the output config will be stored ` )
cmd . Flags ( ) . StringVarP ( & sourceDir , "source-dir" , "s" , filepath . Join ( wd , "src" ) , ` Dir path where the downloaded files will be stored ` )
cmd . Flags ( ) . BoolVarP ( & force , "force" , "f" , false , ` Force overwrite existing files in the output directory ` )
cmd . RunE = func ( cmd * cobra . Command , args [ ] string ) error {
ctx := cmd . Context ( )
2024-03-28 10:32:34 +00:00
b , diags := root . MustConfigureBundle ( cmd )
if err := diags . Error ( ) ; err != nil {
return diags . Error ( )
}
2024-01-17 14:26:33 +00:00
2024-03-28 10:32:34 +00:00
w := b . WorkspaceClient ( )
2024-01-17 14:26:33 +00:00
job , err := w . Jobs . Get ( ctx , jobs . GetJobRequest { JobId : jobId } )
if err != nil {
return err
}
2024-01-25 11:35:14 +00:00
downloader := newDownloader ( w , sourceDir , configDir )
2024-01-17 14:26:33 +00:00
for _ , task := range job . Settings . Tasks {
2024-01-25 11:35:14 +00:00
err := downloader . MarkTaskForDownload ( ctx , & task )
2024-01-17 14:26:33 +00:00
if err != nil {
return err
}
}
v , err := generate . ConvertJobToValue ( job )
if err != nil {
return err
}
2024-01-31 10:23:35 +00:00
jobKey := cmd . Flag ( "key" ) . Value . String ( )
if jobKey == "" {
jobKey = textutil . NormalizeString ( job . Settings . Name )
}
2024-01-17 14:26:33 +00:00
result := map [ string ] dyn . Value {
"resources" : dyn . V ( map [ string ] dyn . Value {
"jobs" : dyn . V ( map [ string ] dyn . Value {
jobKey : v ,
} ) ,
} ) ,
}
err = downloader . FlushToDisk ( ctx , force )
if err != nil {
return err
}
2024-11-20 12:53:25 +00:00
oldFilename := filepath . Join ( configDir , fmt . Sprintf ( "%s.yml" , jobKey ) )
filename := filepath . Join ( configDir , fmt . Sprintf ( "%s.job.yml" , jobKey ) )
// User might continuously run generate command to update their bundle jobs with any changes made in Databricks UI.
// Due to changing in the generated file names, we need to first rename existing resource file to the new name.
// Otherwise users can end up with duplicated resources.
err = os . Rename ( oldFilename , filename )
if err != nil && ! errors . Is ( err , fs . ErrNotExist ) {
return fmt . Errorf ( "failed to rename file %s. DABs uses the resource type as a sub-extension for generated content, please rename it to %s, err: %w" , oldFilename , filename , err )
}
2024-02-15 15:03:19 +00:00
saver := yamlsaver . NewSaverWithStyle ( map [ string ] yaml . Style {
// Including all JobSettings and nested fields which are map[string]string type
"spark_conf" : yaml . DoubleQuotedStyle ,
"custom_tags" : yaml . DoubleQuotedStyle ,
"tags" : yaml . DoubleQuotedStyle ,
} )
err = saver . SaveAsYAML ( result , filename , force )
2024-01-17 14:26:33 +00:00
if err != nil {
return err
}
cmdio . LogString ( ctx , fmt . Sprintf ( "Job configuration successfully saved to %s" , filename ) )
return nil
}
return cmd
}