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

Adds the ability to create ConfigMaps from files #62

Merged
merged 8 commits into from
Feb 26, 2022
Merged
Show file tree
Hide file tree
Changes from 5 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
15 changes: 10 additions & 5 deletions cmd/hope/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,19 @@ var deployCmd = &cobra.Command{
return err
}

parameters, err := utils.RenderParameters(resource.Parameters, resource.FileParameters)
if err != nil {
return err
}

switch resourceType {
case hope.ResourceTypeFile:
if len(resource.Parameters) != 0 {
if len(parameters) != 0 {
if info, err := os.Stat(resource.File); err != nil {
return err
} else if info.IsDir() {
log.Trace("Deploying directory with parameters; creating copy for parameter substitution.")
tempDir, err := hope.ReplaceParametersInDirectoryCopy(resource.File, resource.Parameters)
tempDir, err := hope.ReplaceParametersInDirectoryCopy(resource.File, parameters)
if err != nil {
return err
}
Expand All @@ -117,7 +122,7 @@ var deployCmd = &cobra.Command{
return err
}
} else {
content, err := hope.ReplaceParametersInFile(resource.File, resource.Parameters)
content, err := hope.ReplaceParametersInFile(resource.File, parameters)
if err != nil {
return err
}
Expand All @@ -139,8 +144,8 @@ var deployCmd = &cobra.Command{
// are likely being populated.
log.Trace(inline)

if len(resource.Parameters) != 0 {
inline, err = hope.ReplaceParametersInString(inline, resource.Parameters)
if len(parameters) != 0 {
inline, err = hope.ReplaceParametersInString(inline, parameters)
if err != nil {
return err
}
Expand Down
15 changes: 10 additions & 5 deletions cmd/hope/remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,22 @@ var removeCmd = &cobra.Command{
return err
}

parameters, err := utils.RenderParameters(resource.Parameters, resource.FileParameters)
if err != nil {
return err
}

// It is possible that names of resources are created using
// templated values, so still do the environment substitution
// process.
switch resourceType {
case hope.ResourceTypeFile:
if len(resource.Parameters) != 0 {
if len(parameters) != 0 {
if info, err := os.Stat(resource.File); err != nil {
return err
} else if info.IsDir() {
log.Trace("Deleting directory with parameters; creating copy for parameter substitution.")
tempDir, err := hope.ReplaceParametersInDirectoryCopy(resource.File, resource.Parameters)
tempDir, err := hope.ReplaceParametersInDirectoryCopy(resource.File, parameters)
if err != nil {
return err
}
Expand All @@ -77,7 +82,7 @@ var removeCmd = &cobra.Command{
return err
}
} else {
content, err := hope.ReplaceParametersInFile(resource.File, resource.Parameters)
content, err := hope.ReplaceParametersInFile(resource.File, parameters)
if err != nil {
return err
}
Expand All @@ -99,8 +104,8 @@ var removeCmd = &cobra.Command{
// are likely being populated.
log.Trace(inline)

if len(resource.Parameters) != 0 {
inline, err = hope.ReplaceParametersInString(inline, resource.Parameters)
if len(parameters) != 0 {
inline, err = hope.ReplaceParametersInString(inline, parameters)
if err != nil {
return err
}
Expand Down
41 changes: 39 additions & 2 deletions cmd/hope/utils/resources.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package utils

import (
"encoding/base64"
"fmt"
"io/ioutil"
"os"
"strings"
)

import (
log "github.com/sirupsen/logrus"
"github.com/spf13/viper"
)

Expand All @@ -21,7 +25,7 @@ func GetResources() (*[]hope.Resource, error) {
nameMap := map[string]bool{}
for _, resource := range resources {
if _, ok := nameMap[resource.Name]; ok {
return nil, fmt.Errorf("Multiple resources found in configuration file named: %s", resource.Name)
return nil, fmt.Errorf("multiple resources found in configuration file named: %s", resource.Name)
}
nameMap[resource.Name] = true
}
Expand Down Expand Up @@ -66,8 +70,41 @@ func GetIdentifiableResources(names *[]string, tags *[]string) (*[]hope.Resource

// If any name wasn't found, error out.
if len(nameMap) != 0 {
return nil, fmt.Errorf("Failed to find resources with names: %s", strings.Join(*maputil.MapStringBoolKeys(&nameMap), ","))
return nil, fmt.Errorf("failed to find resources with names: %s", strings.Join(*maputil.MapStringBoolKeys(&nameMap), ","))
}

return &returnSlice, nil
}

// For each parameter from a file, load the file and populate the base64
// values of the files into the properties.
// Does nothing to deduplicate keys.
// All plain parameters will exist in the list before file parameters.
func RenderParameters(directParameters, fileParameters []string) ([]string, error) {
rv := directParameters

for _, param := range fileParameters {
paramComponents := strings.SplitAfterN(param, "=", 2)
paramName := strings.TrimRight(paramComponents[0], "=")
paramPath := paramComponents[1]

if stat, err := os.Stat(paramPath); err != nil {
return nil, err
} else if stat.IsDir() {
return nil, fmt.Errorf("cannot resolve parameter contents from directory: %s", paramPath)
}

srcFile, err := ioutil.ReadFile(paramPath)
if err != nil {
return nil, err
}

log.Tracef("Writing base64ed contents of file %s to parameter %s", paramPath, paramName)
b64Content := base64.StdEncoding.EncodeToString(srcFile)

expandedParam := fmt.Sprintf("%s=%s", paramName, b64Content)
rv = append(rv, expandedParam)
}

return rv, nil
}
29 changes: 29 additions & 0 deletions cmd/hope/utils/resources_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ var testResources []hope.Resource = []hope.Resource{
},
Tags: []string{"database"},
},
{
Name: "configmap-with-file-keys",
Inline: "apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: file-keys\nbinaryData:\n script.sh: ${SCRIPT_SH_FILE}\ndata:\n something_else: ${SOME_OTHER_KEY}\n",
Parameters: []string{"SOME_OTHER_KEY=abc"},
FileParameters: []string{"SCRIPT_SH_FILE=test/script.sh"},
Tags: []string{"another-tag"},
},
}

// Basically a smoke test, don't want to define a ton of yaml blocks to test
Expand Down Expand Up @@ -111,3 +118,25 @@ func TestGetIdentifiableResources(t *testing.T) {
})
}
}

func TestRenderParameters(t *testing.T) {
var tests = []struct {
name string
params []string
fileParams []string
expected []string
}{
{"Nothing", []string{}, []string{}, []string{}},
{"Only param", []string{"A=B"}, []string{}, []string{"A=B"}},
{"Only file", []string{}, []string{"A=../../../test/small"}, []string{"A=Q29udGVudAo="}},
{"Both", []string{"A=B"}, []string{"B=../../../test/small"}, []string{"A=B", "B=Q29udGVudAo="}},
{"Duplicate Keys", []string{"A=B"}, []string{"A=../../../test/small"}, []string{"A=B", "A=Q29udGVudAo="}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
parameters, err := RenderParameters(tt.params, tt.fileParams)
assert.Nil(t, err)
assert.Equal(t, tt.expected, parameters)
})
}
}
19 changes: 19 additions & 0 deletions hope.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,25 @@ resources:
- -e
- select * from abc;
tags: [database]
# Sometimes, ConfigMaps contain keys that are really not fun to embed in a
# yaml file using multi-line strings
# This parameter substitution mechanism lets you pull base64 data out of a
# file.
- name: configmap-with-file-keys
inline: |
apiVersion: v1
kind: ConfigMap
metadata:
name: file-keys
binaryData:
script.sh: ${SCRIPT_SH_FILE}
data:
something_else: ${SOME_OTHER_KEY}
parameters:
- SOME_OTHER_KEY=abc
fileParameters:
- SCRIPT_SH_FILE=test/script.sh
tags: [another-tag]
# Jobs contains a collection of specifications of templated jobs that can be
# run on demand in the cluster.
# These jobs shouldn't be associated to the deployment of any particular
Expand Down
17 changes: 9 additions & 8 deletions pkg/hope/entities.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,15 @@ type ExecSpec struct {
// There may be a better way of doing this, but with a pretty generic list of
// items appearing in a yaml file, maybe not.
type Resource struct {
Name string
File string
Inline string
Parameters []string
Build BuildSpec
Job string
Exec ExecSpec
Tags []string
Name string
File string
Inline string
Parameters []string
FileParameters []string
Build BuildSpec
Job string
Exec ExecSpec
Tags []string
}

// Job - Properties that can appear in any ephemeral job definition.
Expand Down
11 changes: 11 additions & 0 deletions test/script.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env sh
#
echo >&2 "I'm a cool script, and I'm going to do something useful."

sleep 10

echo >&2 "Still working on that thing boss."

sleep 10

echo >&2 "Lol jk, I'm actually just a test file."
1 change: 1 addition & 0 deletions test/small
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Content