github.com/TBD54566975/ftl@v0.219.0/internal/modulecontext/from_secrets.go (about)

     1  package modulecontext
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strings"
     7  )
     8  
     9  // DatabasesFromSecrets finds DSNs in secrets and creates a map of databases.
    10  //
    11  // Secret keys should be in the format FTL_DSN_<MODULENAME>_<DBNAME>
    12  func DatabasesFromSecrets(ctx context.Context, module string, secrets map[string][]byte) (map[string]Database, error) {
    13  	databases := map[string]Database{}
    14  	for sName, maybeDSN := range secrets {
    15  		if !strings.HasPrefix(sName, "FTL_DSN_") {
    16  			continue
    17  		}
    18  		// FTL_DSN_<MODULE>_<DBNAME>
    19  		parts := strings.Split(sName, "_")
    20  		if len(parts) != 4 {
    21  			return nil, fmt.Errorf("invalid DSN secret key %q should have format FTL_DSN_<MODULE>_<DBNAME>", sName)
    22  		}
    23  		moduleName := strings.ToLower(parts[2])
    24  		dbName := strings.ToLower(parts[3])
    25  		if !strings.EqualFold(moduleName, module) {
    26  			continue
    27  		}
    28  		dsnStr := string(maybeDSN)
    29  		dsn := dsnStr[1 : len(dsnStr)-1] // chop leading + trailing quotes
    30  		db, err := NewDatabase(DBTypePostgres, dsn)
    31  		if err != nil {
    32  			return nil, fmt.Errorf("could not create database %q with DSN %q: %w", dbName, maybeDSN, err)
    33  		}
    34  		databases[dbName] = db
    35  	}
    36  	return databases, nil
    37  }
    38  
    39  // DSNSecretKey returns the key for the secret that is expected to hold the DSN for a database.
    40  //
    41  // The format is FTL_DSN_<MODULE>_<DBNAME>
    42  func DSNSecretKey(module, name string) string {
    43  	return fmt.Sprintf("FTL_DSN_%s_%s", strings.ToUpper(module), strings.ToUpper(name))
    44  }
    45  
    46  // GetDSNFromSecret returns the DSN for a database from the relevant secret
    47  func GetDSNFromSecret(module, name string, secrets map[string][]byte) (string, error) {
    48  	key := DSNSecretKey(module, name)
    49  	dsn, ok := secrets[key]
    50  	if !ok {
    51  		return "", fmt.Errorf("secrets map %v is missing DSN with key %q", secrets, key)
    52  	}
    53  	dsnStr := string(dsn)
    54  	return dsnStr[1 : len(dsnStr)-1], nil // chop leading + trailing quotes
    55  }