Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Temp provide autoconf defaults #650

Merged
merged 6 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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