Skip to content

Commit

Permalink
Improve configuration
Browse files Browse the repository at this point in the history
This commit allows configuration to be saved on disk (e.g after runtime
fixes, or after upcoming live configuration changes) and modifies
configuration structures directly when needed
Also added few utilities while I'm here
  • Loading branch information
mikroskeem committed Jul 4, 2019
1 parent 4319aec commit 8a69de4
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 16 deletions.
65 changes: 65 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package main

import (
"io"

"github.com/BurntSushi/toml"
)

type tomlConfig struct {
// Depot contains configuration for the application itself
Depot depotConfig `toml:"depot"`
Expand All @@ -17,6 +23,9 @@ type depotConfig struct {

// Whether JSON REST API queries are allowed or not
APIEnabled bool `toml:"api_enabled"`

// Whether to save configuration changes done on runtime on Depot exit or not
SaveConfigChanges bool `toml:"save_config_changes"`
}

type repositoryInfo struct {
Expand All @@ -38,3 +47,59 @@ type repositoryInfo struct {
// MaxArtifactSize defines maximum deployable file size in bytes. By default it's 32 megabytes
MaxArtifactSize uint64 `toml:"max_artifact_size"`
}

// Validates configuration
func (t *tomlConfig) Validate() error {
// Validate listen address
if len(t.Depot.ListenAddress) == 0 {
t.Depot.ListenAddress = ":5000"
}

ensureCopy := func(m **repositoryInfo, source *repositoryInfo) {
if *m == nil {
*m = &repositoryInfo{}
**m = *source
}
}

// Validate repository information
for n, info := range t.Repositories {
modified := (*repositoryInfo)(nil)

// Need to copy structs here, maps don't work like I expected :(
if info.MaxArtifactSize == 0 {
ensureCopy(&modified, &info)
modified.MaxArtifactSize = 32 << 20
}

// Work around toml library not encoding nil arrays
if info.Credentials == nil || len(info.Credentials) == 0 {
ensureCopy(&modified, &info)
modified.Credentials = []string{}
}

if info.DeployCredentials == nil || len(info.DeployCredentials) == 0 {
ensureCopy(&modified, &info)
modified.DeployCredentials = []string{}
}

// If entry is modified, replace
if modified != nil {
t.Repositories[n] = *modified
}
}

return nil
}

// Dumps configuration
func (t *tomlConfig) Dump(writer io.Writer) error {
w := toml.NewEncoder(writer)
w.Indent = " "
return w.Encode(t)
}

// Returns whether given repository is public or not
func (i *repositoryInfo) IsPublic() bool {
return len(i.Credentials) == 0
}
27 changes: 20 additions & 7 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,14 @@ func main() {
panic(err)
}

var listenAddress string
if len(config.Depot.ListenAddress) > 0 {
listenAddress = config.Depot.ListenAddress
} else {
listenAddress = ":5000"
if err := config.Validate(); err != nil {
panic(err)
}

// Boot up the HTTP server
server := setupServer(listenAddress, config.Depot.RepositoryListing, config.Depot.APIEnabled, config.Repositories)
server := setupServer(config.Depot.ListenAddress, config.Depot.RepositoryListing, config.Depot.APIEnabled, config.Repositories)
go func() {
zap.L().Info("Starting HTTP server", zap.String("address", listenAddress))
zap.L().Info("Starting HTTP server", zap.String("address", config.Depot.ListenAddress))
if err := server.ListenAndServe(); err != http.ErrServerClosed {
zap.L().Error("Failed to serve", zap.Error(err))
}
Expand All @@ -80,6 +77,22 @@ func main() {

zap.L().Info("Shutting down")
<-ctx.Done()

if config.Depot.SaveConfigChanges {
zap.L().Info("Saving configuration")
var f *os.File
if f, err = os.OpenFile(configFile, os.O_CREATE|os.O_WRONLY, 0600); err != nil {
zap.L().Error("Failed to open config file for saving", zap.String("file", configFile), zap.Error(err))
goto End
}
defer f.Close()

if err := config.Dump(f); err != nil {
zap.L().Error("Failed to write configuration file", zap.String("file", configFile), zap.Error(err))
}
}

End:
zap.L().Info("Bye!")
}

Expand Down
9 changes: 2 additions & 7 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func repositoryHandler(name string, info repositoryInfo) (http.HandlerFunc, stri
username, password, credsSupplied := r.BasicAuth()

// Check user access
accessRequiresAuth := len(info.Credentials) > 0
accessRequiresAuth := !info.IsPublic()
deployRequiresAuth := len(info.DeployCredentials) > 0
canAccess := !accessRequiresAuth
canDeploy := !deployRequiresAuth
Expand Down Expand Up @@ -118,12 +118,7 @@ func repositoryHandler(name string, info repositoryInfo) (http.HandlerFunc, stri
}

// Open PUT body stream
var requestBody io.ReadCloser
if info.MaxArtifactSize > 0 {
requestBody = http.MaxBytesReader(w, r.Body, int64(info.MaxArtifactSize))
} else {
requestBody = http.MaxBytesReader(w, r.Body, 32<<20)
}
requestBody := http.MaxBytesReader(w, r.Body, int64(info.MaxArtifactSize))

// Set up directories
filePath := filepath.Join(info.Path, file)
Expand Down
4 changes: 2 additions & 2 deletions server_jsonapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ func setupJSONRoute(mux *http.ServeMux, repositories map[string]repositoryInfo)
w.WriteHeader(http.StatusOK)

repos := make([]publicRepositoryInfo, 0, len(repositories))
for n := range repositories {
for n, info := range repositories {
repos = append(repos, publicRepositoryInfo{
Name: n,
Public: len(repositories[n].Credentials) == 0,
Public: info.IsPublic(),
})
}

Expand Down

0 comments on commit 8a69de4

Please sign in to comment.