Skip to content

Commit

Permalink
Temp provide autoconf defaults (#650)
Browse files Browse the repository at this point in the history
Allow beta sub-commands to run without repo config file
  • Loading branch information
sourishkrout authored Aug 15, 2024
1 parent 7d3243d commit c186a13
Show file tree
Hide file tree
Showing 22 changed files with 2,097 additions and 471 deletions.
2 changes: 1 addition & 1 deletion experimental/runme.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ runtime:

server:
# Also unix:///path/to/file.sock is supported.
address: localhost:7890
address: localhost:7998
tls:
enabled: true
# If not specified, default paths will be used.
Expand Down
1 change: 0 additions & 1 deletion internal/cmd/beta/beta_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ All commands use the runme.yaml configuration file.`,

return nil
})

// print the error to stderr but don't return it because error modes
// are neither fully baked yet nor ready for users to consume
if err != nil {
Expand Down
20 changes: 12 additions & 8 deletions internal/config/autoconfig/autoconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,22 +210,26 @@ func getProjectFilters(c *config.Config) ([]project.Filter, error) {
}

func getRootConfig(cfgLoader *config.Loader, userCfgDir UserConfigDir) (*config.Config, error) {
var cfg *config.Config

content, err := cfgLoader.RootConfig()
if err != nil {
switch err {
case nil:
if cfg, err = config.ParseYAML(content); err != nil {
return nil, err
}
case config.ErrRootConfigNotFound:
cfg = config.Defaults()
default:
return nil, errors.WithMessage(err, "failed to load root configuration")
}

cfg, err := config.ParseYAML(content)
if err != nil {
return nil, err
}

if cfg.ServerTLSEnabled {
if cfg.ServerTLSCertFile == "" {
cfg.ServerTLSCertFile = filepath.Join(string(userCfgDir), "cert.pem")
cfg.ServerTLSCertFile = filepath.Join(string(userCfgDir), "runme", "tls", "cert.pem")
}
if cfg.ServerTLSKeyFile == "" {
cfg.ServerTLSKeyFile = filepath.Join(string(userCfgDir), "key.pem")
cfg.ServerTLSKeyFile = filepath.Join(string(userCfgDir), "runme", "tls", "key.pem")
}
}

Expand Down
74 changes: 50 additions & 24 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"os"
"path/filepath"
"reflect"
"strings"

"github.com/bufbuild/protovalidate-go"
Expand Down Expand Up @@ -42,6 +43,26 @@ type Config struct {
LogVerbose bool
}

func (c *Config) Clone() *Config {
clone := *c
clone.ProjectIgnorePaths = make([]string, len(c.ProjectIgnorePaths))
copy(clone.ProjectIgnorePaths, c.ProjectIgnorePaths)
clone.ProjectEnvSources = make([]string, len(c.ProjectEnvSources))
copy(clone.ProjectEnvSources, c.ProjectEnvSources)
clone.ProjectFilters = make([]*Filter, len(c.ProjectFilters))
for i, f := range c.ProjectFilters {
clone.ProjectFilters[i] = &Filter{
Type: f.Type,
Condition: f.Condition,
}
}
return &clone
}

func Defaults() *Config {
return defaults.Clone()
}

func ParseYAML(data []byte) (*Config, error) {
version, err := parseVersionFromYAML(data)
if err != nil {
Expand Down Expand Up @@ -125,34 +146,39 @@ func configV1alpha1ToConfig(c *configv1alpha1.Config) (*Config, error) {
})
}

cfg := &Config{
ProjectRoot: project.GetRoot(),
ProjectFilename: project.GetFilename(),
ProjectFindRepoUpward: project.GetFindRepoUpward(),
ProjectIgnorePaths: project.GetIgnorePaths(),
ProjectDisableGitignore: project.GetDisableGitignore(),
ProjectEnvUseSystemEnv: project.GetEnv().GetUseSystemEnv(),
ProjectEnvSources: project.GetEnv().GetSources(),
ProjectFilters: filters,

RuntimeDockerEnabled: runtime.GetDocker().GetEnabled(),
RuntimeDockerImage: runtime.GetDocker().GetImage(),
RuntimeDockerBuildContext: runtime.GetDocker().GetBuild().GetContext(),
RuntimeDockerBuildDockerfile: runtime.GetDocker().GetBuild().GetDockerfile(),

ServerAddress: server.GetAddress(),
ServerTLSEnabled: server.GetTls().GetEnabled(),
ServerTLSCertFile: server.GetTls().GetCertFile(),
ServerTLSKeyFile: server.GetTls().GetKeyFile(),

LogEnabled: log.GetEnabled(),
LogPath: log.GetPath(),
LogVerbose: log.GetVerbose(),
}
cfg := Defaults()
cfg.ProjectRoot = project.GetRoot()
cfg.ProjectFilename = project.GetFilename()
setIfHasValue(&cfg.ProjectFindRepoUpward, project.GetFindRepoUpward())
cfg.ProjectIgnorePaths = project.GetIgnorePaths()
setIfHasValue(&cfg.ProjectDisableGitignore, project.GetDisableGitignore())
setIfHasValue(&cfg.ProjectEnvUseSystemEnv, project.GetEnv().GetUseSystemEnv())
cfg.ProjectEnvSources = project.GetEnv().GetSources()
cfg.ProjectFilters = filters

setIfHasValue(&cfg.RuntimeDockerEnabled, runtime.GetDocker().GetEnabled())
cfg.RuntimeDockerImage = runtime.GetDocker().GetImage()
cfg.RuntimeDockerBuildContext = runtime.GetDocker().GetBuild().GetContext()
cfg.RuntimeDockerBuildDockerfile = runtime.GetDocker().GetBuild().GetDockerfile()

cfg.ServerAddress = server.GetAddress()
setIfHasValue(&cfg.ServerTLSEnabled, server.GetTls().GetEnabled())
cfg.ServerTLSCertFile = server.GetTls().GetCertFile()
cfg.ServerTLSKeyFile = server.GetTls().GetKeyFile()

setIfHasValue(&cfg.LogEnabled, log.GetEnabled())
cfg.LogPath = log.GetPath()
setIfHasValue(&cfg.LogVerbose, log.GetVerbose())

return cfg, nil
}

func setIfHasValue[T any](prop *T, val interface{ GetValue() T }) {
if val != nil && !reflect.ValueOf(val).IsNil() {
*prop = val.GetValue()
}
}

func validateConfig(cfg *Config) error {
cwd, err := os.Getwd()
if err != nil {
Expand Down
77 changes: 77 additions & 0 deletions internal/config/config_defaults.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package config

var defaults Config

func init() {
// todo(sebastian): use inline file for easier editing
yaml := []byte(`version: v1alpha1
# Settings that apply on at the project level.
project:
# Indicate the root of the runme project. "." means that
# the project root directory will be used.
root: "."
# If true, the project root will be searched upwards starting from "dir".
# If found, the repo root will be used as the project root.
find_repo_upward: true
ignore:
- "node_modules"
- ".venv"
disable_gitignore: false
# It's possible to point the project at a single file.
# filename: "README.md"
# List of dotenv files to load.
env:
use_system_env: false
sources:
- ".env"
- ".env.local"
# The list of filters to apply to blocks.
# "condition" must return a boolean value.
# You can learn about the syntax at https://expr-lang.org/docs/language-definition.
# Available fields are defined in [config.FilterDocumentEnv] and [config.FilterBlockEnv].
# filters:
# # Do not allow unnamed code blocks.
# # - type: "FILTER_TYPE_BLOCK"
# # condition: "is_named"
# # Do not allow code blocks without a language.
# - type: "FILTER_TYPE_BLOCK"
# condition: "language != ''"
# # Do not allow code blocks starting with "test".
# - type: "FILTER_TYPE_BLOCK"
# condition: "!hasPrefix(name, 'test')"
runtime:
# Optional Docker configuration to run code blocks in a container.
docker:
enabled: false
image: runme-runtime:latest
build:
context: ./experimental/docker
dockerfile: Dockerfile
server:
# Also unix:///path/to/file.sock is supported.
address: localhost:7998
tls:
enabled: true
# If not specified, default paths will be used.
# cert_file: "/path/to/cert.pem"
# key_file: "/path/to/key.pem"
log:
enabled: false
path: "/tmp/runme.log"
verbose: false
`)

cfg, err := ParseYAML(yaml)
if err != nil {
panic(err)
}

defaults = *cfg
}
23 changes: 21 additions & 2 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func TestParseYAML(t *testing.T) {
project:
filename: REAEDME.md
`,
expectedConfig: &Config{ProjectFilename: "REAEDME.md"},
expectedConfig: &Config{ProjectFilename: "REAEDME.md", ProjectFindRepoUpward: true, ServerTLSEnabled: true},
},
{
name: "root and filename",
Expand All @@ -35,7 +35,7 @@ project:
root: "."
filename: README.md
`,
expectedConfig: &Config{ProjectRoot: ".", ProjectFilename: "README.md"},
expectedConfig: &Config{ProjectRoot: ".", ProjectFilename: "README.md", ProjectFindRepoUpward: true, ServerTLSEnabled: true},
},
{
name: "validate filter type",
Expand Down Expand Up @@ -144,5 +144,24 @@ log:
LogEnabled: true,
LogPath: "/var/tmp/runme.log",
LogVerbose: true,

ServerTLSEnabled: true,
}
)

func TestCloneConfig(t *testing.T) {
original := defaults
clone := original.Clone()

opts := cmpopts.EquateEmpty()
require.True(
t,
cmp.Equal(&original, clone, opts),
"%s",
cmp.Diff(&original, clone, opts),
)
require.False(t, &original == clone)
require.False(t, &original.ProjectIgnorePaths == &clone.ProjectIgnorePaths)
require.False(t, &original.ProjectEnvSources == &clone.ProjectEnvSources)
require.False(t, &original.ProjectFilters == &clone.ProjectFilters)
}
15 changes: 13 additions & 2 deletions internal/tls/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func generateCertificate(certFile, keyFile string) (*tls.Config, error) {
return nil, errors.WithStack(err)
}

if err := os.WriteFile(certFile, caPEM.Bytes(), tlsFileMode); err != nil {
if err := writeFileWithDir(certFile, caPEM.Bytes(), tlsFileMode); err != nil {
return nil, errors.Wrap(err, "failed to write CA")
}

Expand All @@ -181,7 +181,7 @@ func generateCertificate(certFile, keyFile string) (*tls.Config, error) {
return nil, errors.WithStack(err)
}

if err := os.WriteFile(keyFile, privKeyPEM.Bytes(), tlsFileMode); err != nil {
if err := writeFileWithDir(keyFile, privKeyPEM.Bytes(), tlsFileMode); err != nil {
return nil, errors.Wrap(err, "failed to write private key")
}

Expand All @@ -208,6 +208,17 @@ func generateCertificate(certFile, keyFile string) (*tls.Config, error) {
return tlsConfig, nil
}

func writeFileWithDir(nameWithPath string, data []byte, perm fs.FileMode) error {
if _, err := os.Stat(filepath.Dir(nameWithPath)); errors.Is(err, fs.ErrNotExist) {
if err := os.MkdirAll(filepath.Dir(nameWithPath), tlsDirMode); err != nil {
return errors.Wrap(err, "failed to create TLS directory")
}
}

err := os.WriteFile(nameWithPath, data, perm)
return errors.Wrap(err, "failed to write file")
}

func validateTLSConfig(config *tls.Config) (ttl time.Duration, _ error) {
if len(config.Certificates) < 1 || len(config.Certificates[0].Certificate) < 1 {
return ttl, errors.New("invalid TLS certificate")
Expand Down
25 changes: 18 additions & 7 deletions pkg/api/gen/proto/go/runme/ai/v1alpha1/ai_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit c186a13

Please sign in to comment.