Skip to content
This repository has been archived by the owner on Oct 29, 2023. It is now read-only.

Commit

Permalink
Improved config file. Better docs
Browse files Browse the repository at this point in the history
- Added ability of handling environment variables in configuration file.
  $HOME and $PWD are expanded to actual values.
- Added hidden command "tree" that can generate the full dbdeployer API.
  Using this feature, from now on we can compare API changes automatically.
- Fixed visualization of sandboxes from catalog
- Fixed minor code issues.
- Added tests for environment variable replacement
  • Loading branch information
datacharmer committed Mar 31, 2018
1 parent 3f87321 commit 76a68c6
Show file tree
Hide file tree
Showing 15 changed files with 856 additions and 21 deletions.
10 changes: 10 additions & 0 deletions Changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
1.1.0 30-Mar-2018
- Added ability of handling environment variables
in configuration file. $HOME and $PWD are expanded
to actual values.
- Added hidden command "tree" that can generate the
full dbdeployer API. Using this feature, from now on
we can compare API changes automatically.
- Fixed visualization of sandboxes from catalog
- Fixed minor code issues.
- Added tests for environment variable replacement
1.0.1 28-Mar-2018
- Fixed Issue #5 "Single deployment doesn't show the location of the
sandbox"
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ For example:
The program doesn't have any dependencies. Everything is included in the binary. Calling *dbdeployer* without arguments or with '--help' will show the main help screen.

$ dbdeployer --version
dbdeployer version 1.0.1
dbdeployer version 1.1.0


$ dbdeployer -h
Expand Down Expand Up @@ -335,7 +335,7 @@ Here's how:
$ dbdeployer defaults show
# Internal values:
{
"version": "1.0.0",
"version": "1.1.0",
"sandbox-home": "$HOME/sandboxes",
"sandbox-binary": "$HOME/opt/mysql",
"use-sandbox-catalog": true,
Expand Down Expand Up @@ -365,7 +365,7 @@ Here's how:
# Updated master-slave-base-port -> "15000"
# Configuration file: $HOME/.dbdeployer/config.json
{
"version": "1.0.0",
"version": "1.1.0",
"sandbox-home": "$HOME/sandboxes",
"sandbox-binary": "$HOME/opt/mysql",
"use-sandbox-catalog": true,
Expand Down
4 changes: 2 additions & 2 deletions cmd/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func UnpreserveSandbox(sandbox_dir, sandbox_name string) {
is_multiple = false
}
if !common.ExecExists(clear) {
fmt.Println("Executable '%s' not found\n", clear)
fmt.Printf("Executable '%s' not found\n", clear)
os.Exit(1)
}
no_clear := full_path + "/no_clear"
Expand Down Expand Up @@ -87,7 +87,7 @@ func PreserveSandbox(sandbox_dir, sandbox_name string) {
is_multiple = false
}
if !common.ExecExists(clear) {
fmt.Println("Executable '%s' not found\n", clear)
fmt.Printf("Executable '%s' not found\n", clear)
os.Exit(1)
}
no_clear := full_path + "/no_clear"
Expand Down
4 changes: 2 additions & 2 deletions cmd/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func RemoveSandbox(sandbox_dir, sandbox string, run_concurrently bool) (exec_lis
stop = full_path + "/stop"
}
if !common.ExecExists(stop) {
fmt.Println("Executable '%s' not found\n", stop)
fmt.Printf("Executable '%s' not found\n", stop)
os.Exit(1)
}

Expand Down Expand Up @@ -117,7 +117,7 @@ func DeleteSandbox(cmd *cobra.Command, args []string) {
return
}
if len(deletion_list) > 60 && run_concurrently {
fmt.Println("# Concurrency disabled. Can't run more than 60 concurrent operations\n")
fmt.Println("# Concurrency disabled. Can't run more than 60 concurrent operations")
run_concurrently = false
}
fmt.Printf("List of deployed sandboxes:\n")
Expand Down
2 changes: 1 addition & 1 deletion cmd/sandboxes.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func ShowSandboxesFromCatalog(current_sandbox_home string, header bool) {
if len(sandbox_list) == 0 {
return
}
template := "%-25s %-10s %-15s %5v %-25s %s \n"
template := "%-25s %-10s %-20s %5v %-25s %s \n"
if header {
fmt.Printf( template, "name", "version", "type", "nodes", "ports", "")
fmt.Printf( template, "----", "-------", "-----", "-----", "-----", "")
Expand Down
3 changes: 3 additions & 0 deletions cmd/single.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,17 +183,20 @@ Use the "unpack" command to get the tarball into the right directory.
var (
hiddenSingleCmd = &cobra.Command{
Use: "single",
Short: "REMOVED: use 'deploy single' instead",
Hidden: true,
Run: ReplacedCmd,
}
hiddenReplicationCmd = &cobra.Command{
Use: "replication",
Short: "REMOVED: use 'deploy replication' instead",
Hidden: true,
Run: ReplacedCmd,
}

hiddenMultipleCmd = &cobra.Command{
Use: "multiple",
Short: "REMOVED: use 'deploy multiple' instead",
Hidden: true,
Run: ReplacedCmd,
}
Expand Down
80 changes: 80 additions & 0 deletions cmd/tree.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// DBDeployer - The MySQL Sandbox
// Copyright © 2006-2018 Giuseppe Maxia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"fmt"
"strings"
"github.com/spf13/cobra"
)

func ShowTree(cmd *cobra.Command, args []string) {
flags := cmd.Flags()
api, _ := flags.GetBool("api")
show_hidden, _ := flags.GetBool("show-hidden")
if api {
fmt.Println("This is the list of commands and modifiers available for dbdeployer")
fmt.Println("")
fmt.Println("{{dbdeployer --version}}")
fmt.Println("# main")
fmt.Println("{{dbdeployer -h }}")
fmt.Println("")
fmt.Println("{{dbdeployer tree }}")
}
traverse(rootCmd, "", 0, api, show_hidden)
}

func traverse(cmd *cobra.Command, parent string, level int, api, show_hidden bool) {
subcommands := cmd.Commands()
indent := strings.Repeat(" ", level*4) + "-"
for _, c := range subcommands {
hidden_flag := ""
if c.Hidden || c.Name() == "help" {
if show_hidden {
hidden_flag = " (HIDDEN) "
} else {
continue
}
}
size := len(c.Commands())
if api {
if size > 0 || level == 0 {
fmt.Printf("\n##%s%s\n", parent + " " + c.Name(), hidden_flag)
}
fmt.Printf("{{dbdeployer%s %s -h}}\n", parent, c.Name())
} else {
fmt.Printf("%s %-20s%s\n", indent, c.Name(), hidden_flag)
}
if size > 0 {
traverse(c, parent + " " + c.Name(), level + 1, api, show_hidden)
}
}
}

var treeCmd = &cobra.Command{
Use: "tree",
Short: "shows command tree",
Long: `This command is only used to create API documentation.
You can, however, use it to show the command structure at a glance.`,
Hidden : true,
Run: ShowTree,
}

func init() {
rootCmd.AddCommand(treeCmd)
treeCmd.PersistentFlags().Bool("api", false, "Writes API template")
treeCmd.PersistentFlags().Bool("show-hidden", false, "Shows also hidden commands")
}
26 changes: 20 additions & 6 deletions common/strutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,31 @@ import (
// returns a string where the literal value for $HOME
// is replaced by the string "$HOME"
func ReplaceLiteralHome( path string) string {
home := os.Getenv("HOME")
re := regexp.MustCompile(`^` + home)
return re.ReplaceAllString(path, "$$HOME")
// home := os.Getenv("HOME")
// re := regexp.MustCompile(`^` + home)
// return re.ReplaceAllString(path, "$$HOME")
return ReplaceLiteralEnvVar(path, "HOME")
}

func ReplaceLiteralEnvVar(name string, env_var string) string {
value := os.Getenv(env_var)
re := regexp.MustCompile(value)
return re.ReplaceAllString(name, "$$" + env_var)
}

func ReplaceEnvVar(name string, env_var string) string {
value := os.Getenv(env_var)
re := regexp.MustCompile(`\$` + env_var+ `\b`)
return re.ReplaceAllString(name, value)
}

// Given a path with the variable "$HOME" at the start,
// returns a string with the value of HOME expanded
func ReplaceHomeVar(path string) string {
home := os.Getenv("HOME")
re := regexp.MustCompile(`^\$HOME\b`)
return re.ReplaceAllString(path, home)
// home := os.Getenv("HOME")
// re := regexp.MustCompile(`^\$HOME\b`)
//return re.ReplaceAllString(path, home)
return ReplaceEnvVar(path, "HOME")
}

func MakeCustomizedUuid(port , node_num int ) string {
Expand Down
63 changes: 63 additions & 0 deletions common/strutils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// DBDeployer - The MySQL Sandbox
// Copyright © 2006-2018 Giuseppe Maxia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package common

import (
"os"
"testing"
)

type path_info struct {
value string
env_var string
expected string
}

func TestReplaceLiteralHome(t *testing.T) {
os.Setenv("HOME", "/home/Groucho")
os.Setenv("PWD", "/var/lib/MarxBrothers")
var paths = []path_info{
{"/home/Groucho/", "HOME", "$HOME/"},
{"/home/Groucho/path1/path2", "HOME", "$HOME/path1/path2"},
{"/home/Harpo/path1/path2", "HOME", "/home/Harpo/path1/path2"},
{"/var/lib/MarxBrothers/path1/path2", "PWD", "$PWD/path1/path2"},
{"/var/lib/MarxCousins/path1/path2", "PWD", "/var/lib/MarxCousins/path1/path2"},
}
for _, p := range paths {
value := p.value
env_var := p.env_var
expected := p.expected
canary := ReplaceLiteralEnvVar(value, env_var)
if expected == canary {
t.Logf("ok %-35s %-10s =--> %-25s\n", value, "(" + env_var + ")", expected)
} else {
t.Logf("NOT OK %-35s %-10s =--> %-25s\n", value, "(" + env_var + ")", expected)
t.Fail()
}
}
for _, p := range paths {
value := p.expected
env_var := p.env_var
expected := p.value
canary := ReplaceEnvVar(value, env_var)
if expected == canary {
t.Logf("ok %-35s %-10s --=> %-25s\n", value, "(" + env_var + ")", expected)
} else {
t.Logf("NOT OK %-35s %-10s --=> %-25s\n", value, "(" + env_var + ")", expected)
t.Fail()
}
}
}
4 changes: 2 additions & 2 deletions common/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@

package common

var VersionDef string = "1.0.1" // 2018-03-28
var VersionDef string = "1.1.0" // 2018-03-29

// Compatible version is the version used to mark compatible archives (templates, configuration).
// It is usually major.minor.0, except when we are at version 0.x, when
// every revision may bring incompatibility
var CompatibleVersion string = "1.0.0" // 2018-03-26
var CompatibleVersion string = "1.1.0" // 2018-03-29
2 changes: 1 addition & 1 deletion defaults/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (

type SandboxItem struct {
Origin string `json:"origin"`
SBType string `json:"type"` // single multi master-slave group
SBType string `json:"type"` // single multi master-slave group all-masters fan-in
Version string `json:"version"`
Port []int `json:"port"`
Nodes []string `json:"nodes"`
Expand Down
22 changes: 20 additions & 2 deletions defaults/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ var (
Version: common.CompatibleVersion,
SandboxHome: home_dir + "/sandboxes",
SandboxBinary: home_dir + "/opt/mysql",

UseSandboxCatalog: true,
//UseConcurrency : true,
MasterSlaveBasePort: 11000,
Expand Down Expand Up @@ -107,8 +108,6 @@ var (
// NdbPrefix: "ndb_msb_",
// PxcPrefix: "pxc_msb_",
}
// TODO : allow for environmengt variables such as $HOME and $PWD to be
// recognized and handled in the configuration file.
currentDefaults DbdeployerDefaults
)

Expand All @@ -124,6 +123,7 @@ func Defaults() DbdeployerDefaults {
}

func ShowDefaults(defaults DbdeployerDefaults) {
defaults = replace_literal_env_values(defaults)
if common.FileExists(ConfigurationFile) {
fmt.Printf("# Configuration file: %s\n", ConfigurationFile)
} else {
Expand All @@ -138,6 +138,7 @@ func ShowDefaults(defaults DbdeployerDefaults) {
}

func WriteDefaultsFile(filename string, defaults DbdeployerDefaults) {
defaults = replace_literal_env_values(defaults)
defaults_dir := common.DirName(filename)
if !common.DirExists(defaults_dir) {
common.Mkdir(defaults_dir)
Expand All @@ -151,6 +152,22 @@ func WriteDefaultsFile(filename string, defaults DbdeployerDefaults) {
common.WriteString(json_string, filename)
}

func expand_environment_variables(defaults DbdeployerDefaults) DbdeployerDefaults {
defaults.SandboxHome = common.ReplaceEnvVar(defaults.SandboxHome, "HOME")
defaults.SandboxHome = common.ReplaceEnvVar(defaults.SandboxHome, "PWD")
defaults.SandboxBinary = common.ReplaceEnvVar(defaults.SandboxBinary, "HOME")
defaults.SandboxBinary = common.ReplaceEnvVar(defaults.SandboxBinary, "PWD")
return defaults
}

func replace_literal_env_values(defaults DbdeployerDefaults) DbdeployerDefaults {
defaults.SandboxHome = common.ReplaceLiteralEnvVar(defaults.SandboxHome, "HOME")
defaults.SandboxHome = common.ReplaceLiteralEnvVar(defaults.SandboxHome, "PWD")
defaults.SandboxBinary = common.ReplaceLiteralEnvVar(defaults.SandboxBinary, "HOME")
defaults.SandboxBinary = common.ReplaceLiteralEnvVar(defaults.SandboxBinary, "PWD")
return defaults
}

func ReadDefaultsFile(filename string) (defaults DbdeployerDefaults) {
defaults_blob := common.SlurpAsBytes(filename)

Expand All @@ -159,6 +176,7 @@ func ReadDefaultsFile(filename string) (defaults DbdeployerDefaults) {
fmt.Println("error decoding defaults: ", err)
os.Exit(1)
}
defaults = expand_environment_variables(defaults)
return
}

Expand Down
Loading

0 comments on commit 76a68c6

Please sign in to comment.