databricks-cli/libs/databrickscfg/loader.go

100 lines
2.4 KiB
Go

package databrickscfg
import (
"context"
"fmt"
"os"
"strings"
"github.com/databricks/bricks/libs/log"
"github.com/databricks/databricks-sdk-go/config"
"gopkg.in/ini.v1"
)
var ResolveProfileFromHost = profileFromHostLoader{}
type profileFromHostLoader struct{}
func (l profileFromHostLoader) Name() string {
return "resolve-profile-from-host"
}
func (l profileFromHostLoader) Configure(cfg *config.Config) error {
// Skip an attempt to resolve a profile from the host if any authentication
// is already configured (either directly, through environment variables, or
// if a profile was specified).
if cfg.Host == "" || l.isAnyAuthConfigured(cfg) {
return nil
}
configFile, err := config.LoadFile(cfg.ConfigFile)
if err != nil {
if os.IsNotExist(err) {
return nil
}
return fmt.Errorf("cannot parse config file: %w", err)
}
// Normalized version of the configured host.
host := normalizeHost(cfg.Host)
// Look for sections in the configuration file that match the configured host.
var matching []*ini.Section
for _, section := range configFile.Sections() {
key, err := section.GetKey("host")
if err != nil {
log.Tracef(context.Background(), "section %s: %s", section.Name(), err)
continue
}
// Ignore this section if the normalized host doesn't match.
if normalizeHost(key.Value()) != host {
continue
}
matching = append(matching, section)
}
// If there are no matching sections, we don't do anything.
if len(matching) == 0 {
return nil
}
// If there are multiple matching sections, let the user know it is impossible
// to unambiguously select a profile to use.
if len(matching) > 1 {
var names []string
for _, section := range matching {
names = append(names, section.Name())
}
return fmt.Errorf(
"multiple profiles for host %s (%s): please set DATABRICKS_CONFIG_PROFILE to specify one",
host,
strings.Join(names, ", "),
)
}
match := matching[0]
log.Debugf(context.Background(), "Loading profile %s because of host match", match.Name())
err = config.ConfigAttributes.ResolveFromStringMap(cfg, match.KeysHash())
if err != nil {
return fmt.Errorf("%s %s profile: %w", configFile.Path(), match.Name(), err)
}
return nil
}
func (l profileFromHostLoader) isAnyAuthConfigured(cfg *config.Config) bool {
for _, a := range config.ConfigAttributes {
if a.Auth == "" {
continue
}
if !a.IsZero(cfg) {
return true
}
}
return false
}