Skip to content

Commit c4f88e0

Browse files
Merge branch 'main' into feature/show-estimated-cost-for-data-diff
2 parents 0921a05 + f15d8e5 commit c4f88e0

8 files changed

Lines changed: 457 additions & 475 deletions

File tree

cmd/render.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/bruin-data/bruin/pkg/query"
3030
"github.com/bruin-data/bruin/pkg/snowflake"
3131
"github.com/bruin-data/bruin/pkg/synapse"
32+
"github.com/muesli/termenv"
3233
"github.com/pkg/errors"
3334
"github.com/spf13/afero"
3435
"github.com/urfave/cli/v3"
@@ -392,8 +393,13 @@ func highlightCode(code string, language string) string {
392393
if (o.Mode() & os.ModeCharDevice) != os.ModeCharDevice {
393394
return code
394395
}
396+
style := "monokai"
397+
if !termenv.HasDarkBackground() {
398+
style = "github"
399+
}
400+
395401
b := new(strings.Builder)
396-
err = quick.Highlight(b, code, language, "terminal16m", "monokai")
402+
err = quick.Highlight(b, code, language, "terminal16m", style)
397403
if err != nil {
398404
errorPrinter.Printf("Failed to highlight the query: %v\n", err.Error())
399405
return code

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ require (
5050
github.com/kluctl/go-embed-python v0.0.0-3.13.1-20241219-1
5151
github.com/manifoldco/promptui v0.9.0
5252
github.com/microsoft/go-mssqldb v1.8.2
53+
github.com/muesli/termenv v0.16.0
5354
github.com/nikolalohinski/gonja/v2 v2.3.4
5455
github.com/pashagolub/pgxmock/v3 v3.4.0
5556
github.com/pkg/errors v0.9.1
@@ -294,7 +295,6 @@ require (
294295
github.com/mtibben/percent v0.2.1 // indirect
295296
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
296297
github.com/muesli/cancelreader v0.2.2 // indirect
297-
github.com/muesli/termenv v0.16.0 // indirect
298298
github.com/nakabonne/nestif v0.3.1 // indirect
299299
github.com/nishanths/exhaustive v0.12.0 // indirect
300300
github.com/nishanths/predeclared v0.2.2 // indirect

pkg/ansisql/operator.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ func (o *QuerySensor) RunTask(ctx context.Context, p *pipeline.Pipeline, t *pipe
8181
}); ok {
8282
res, err := querier.Select(ctx, qry[0])
8383
if err != nil {
84+
if printerExists {
85+
fmt.Fprintln(printer, "Error: Sensor query failed:", err)
86+
}
8487
return err
8588
}
8689
intRes, err := helpers.CastResultToInteger(res, true)
@@ -189,6 +192,9 @@ func (ts *TableSensor) RunTask(ctx context.Context, p *pipeline.Pipeline, t *pip
189192
default:
190193
res, err := tableChecker.Select(ctx, extractedQuery)
191194
if err != nil {
195+
if printerExists {
196+
fmt.Fprintln(printer, "Error: Sensor query failed:", err)
197+
}
192198
return err
193199
}
194200
intRes, err := helpers.CastResultToInteger(res, true)

pkg/config/lakehouse.go

Lines changed: 66 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package config
33
import (
44
"errors"
55
"fmt"
6+
"slices"
67
)
78

89
type LakehouseFormat string
@@ -36,20 +37,18 @@ type CatalogAuth struct {
3637
Password string `yaml:"password,omitempty" json:"password,omitempty" mapstructure:"password"`
3738
}
3839

39-
func (auth *CatalogAuth) IsAWS() bool {
40-
if auth == nil {
41-
return false
42-
}
40+
func (auth CatalogAuth) IsAWS() bool {
4341
return auth.AccessKey != "" && auth.SecretKey != ""
4442
}
4543

46-
func (auth *CatalogAuth) IsPostgres() bool {
47-
if auth == nil {
48-
return false
49-
}
44+
func (auth CatalogAuth) IsPostgres() bool {
5045
return auth.Username != "" && auth.Password != ""
5146
}
5247

48+
func (auth CatalogAuth) IsZero() bool {
49+
return auth == (CatalogAuth{})
50+
}
51+
5352
type CatalogConfig struct {
5453
Type CatalogType `yaml:"type" json:"type" mapstructure:"type"`
5554

@@ -66,7 +65,18 @@ type CatalogConfig struct {
6665
Database string `yaml:"database,omitempty" json:"database,omitempty" mapstructure:"database"`
6766

6867
// Authentication
69-
Auth *CatalogAuth `yaml:"auth,omitempty" json:"auth,omitempty" mapstructure:"auth"`
68+
Auth CatalogAuth `yaml:"auth,omitempty" json:"auth,omitempty" mapstructure:"auth"`
69+
}
70+
71+
func (c CatalogConfig) IsZero() bool {
72+
return c.Type == "" &&
73+
c.CatalogID == "" &&
74+
c.Region == "" &&
75+
c.Path == "" &&
76+
c.Host == "" &&
77+
c.Port == 0 &&
78+
c.Database == "" &&
79+
c.Auth.IsZero()
7080
}
7181

7282
type StorageType string
@@ -76,72 +86,83 @@ const (
7686
// Future: StorageTypeGCS, StorageTypeLocal.
7787
)
7888

89+
var (
90+
supportedCatalogTypes = []CatalogType{
91+
CatalogTypeGlue,
92+
CatalogTypePostgres,
93+
CatalogTypeDuckDB,
94+
CatalogTypeSQLite,
95+
}
96+
supportedStorageTypes = []StorageType{
97+
StorageTypeS3,
98+
}
99+
)
100+
79101
type StorageAuth struct {
80102
// AWS S3 credentials
81103
AccessKey string `yaml:"access_key,omitempty" json:"access_key,omitempty" mapstructure:"access_key"`
82104
SecretKey string `yaml:"secret_key,omitempty" json:"secret_key,omitempty" mapstructure:"secret_key"`
83105
SessionToken string `yaml:"session_token,omitempty" json:"session_token,omitempty" mapstructure:"session_token"`
84106
}
85107

86-
func (a *StorageAuth) IsS3() bool {
87-
if a == nil {
88-
return false
89-
}
108+
func (a StorageAuth) IsS3() bool {
90109
return a.AccessKey != "" && a.SecretKey != ""
91110
}
92111

112+
func (a StorageAuth) IsZero() bool {
113+
return a == (StorageAuth{})
114+
}
115+
93116
type StorageConfig struct {
94-
Type StorageType `yaml:"type" json:"type" mapstructure:"type"`
95-
Path string `yaml:"path,omitempty" json:"path,omitempty" mapstructure:"path"`
96-
Region string `yaml:"region,omitempty" json:"region,omitempty" mapstructure:"region"`
97-
Auth *StorageAuth `yaml:"auth,omitempty" json:"auth,omitempty" mapstructure:"auth"`
117+
Type StorageType `yaml:"type" json:"type" mapstructure:"type"`
118+
Path string `yaml:"path,omitempty" json:"path,omitempty" mapstructure:"path"`
119+
Region string `yaml:"region,omitempty" json:"region,omitempty" mapstructure:"region"`
120+
Auth StorageAuth `yaml:"auth,omitempty" json:"auth,omitempty" mapstructure:"auth"`
121+
}
122+
123+
func (s StorageConfig) IsZero() bool {
124+
return s.Type == "" &&
125+
s.Path == "" &&
126+
s.Region == "" &&
127+
s.Auth.IsZero()
98128
}
99129

100130
type LakehouseConfig struct {
101131
Format LakehouseFormat `yaml:"format" json:"format" mapstructure:"format"`
102-
Catalog *CatalogConfig `yaml:"catalog,omitempty" json:"catalog,omitempty" mapstructure:"catalog"`
103-
Storage *StorageConfig `yaml:"storage,omitempty" json:"storage,omitempty" mapstructure:"storage"`
132+
Catalog CatalogConfig `yaml:"catalog,omitempty" json:"catalog,omitempty" mapstructure:"catalog"`
133+
Storage StorageConfig `yaml:"storage,omitempty" json:"storage,omitempty" mapstructure:"storage"`
134+
}
135+
136+
func (lh *LakehouseConfig) IsZero() bool {
137+
if lh == nil {
138+
return true
139+
}
140+
141+
return lh.Format == "" && lh.Catalog.IsZero() && lh.Storage.IsZero()
104142
}
105143

106144
// Validate performs basic structural validation of the LakehouseConfig (engine-agnostic).
107145
func (lh *LakehouseConfig) Validate() error {
146+
if lh == nil {
147+
return nil
148+
}
149+
108150
if lh.Format == "" {
109151
return errors.New("lakehouse format is required")
110152
}
111153

112-
switch lh.Format {
113-
case LakehouseFormatIceberg:
114-
// valid format
115-
case LakehouseFormatDuckLake:
116-
// valid format
117-
default:
154+
if !slices.Contains([]LakehouseFormat{LakehouseFormatIceberg, LakehouseFormatDuckLake}, lh.Format) {
118155
return fmt.Errorf("unsupported lakehouse format: %s (supported: iceberg, ducklake)", lh.Format)
119156
}
120157

121158
// Validate catalog type if specified
122-
if lh.Catalog != nil && lh.Catalog.Type != "" {
123-
switch lh.Catalog.Type {
124-
case CatalogTypeGlue:
125-
// valid catalog type
126-
case CatalogTypePostgres:
127-
// valid catalog type
128-
case CatalogTypeDuckDB:
129-
// valid catalog type
130-
case CatalogTypeSQLite:
131-
// valid catalog type
132-
default:
133-
return fmt.Errorf("unsupported catalog type: %s (supported: glue, postgres, duckdb, sqlite)", lh.Catalog.Type)
134-
}
159+
if lh.Catalog.Type == "" || !slices.Contains(supportedCatalogTypes, lh.Catalog.Type) {
160+
return errors.New("empty or unsupported catalog type: (supported: glue, postgres, duckdb, sqlite)")
135161
}
136162

137163
// Validate storage type if specified
138-
if lh.Storage != nil && lh.Storage.Type != "" {
139-
switch lh.Storage.Type {
140-
case StorageTypeS3:
141-
// valid storage type
142-
default:
143-
return fmt.Errorf("unsupported storage type: %s (supported: s3)", lh.Storage.Type)
144-
}
164+
if lh.Storage.Type == "" || !slices.Contains(supportedStorageTypes, lh.Storage.Type) {
165+
return errors.New("empty or unsupported storage type: (supported: s3)")
145166
}
146167

147168
return nil

0 commit comments

Comments
 (0)