Skip to content

Commit

Permalink
Merge pull request #1 from blendle/new-charts-yaml
Browse files Browse the repository at this point in the history
New charts.yml format
  • Loading branch information
JeanMertz authored May 12, 2017
2 parents df5fbb5 + c724479 commit 5f47728
Show file tree
Hide file tree
Showing 14 changed files with 873 additions and 219 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/_dist
/bin
/kubecrt
/vendor
/bin
/_dist
57 changes: 37 additions & 20 deletions parser/chart.go → chart/parser.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package parser
package chart

import (
"fmt"
Expand All @@ -7,34 +7,39 @@ import (
"path/filepath"
"strings"

"github.com/blendle/kubecrt/helm"

yaml "gopkg.in/yaml.v2"
"k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/downloader"
"k8s.io/helm/pkg/engine"
"k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/helm/environment"
"k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/proto/hapi/chart"
"k8s.io/helm/pkg/timeconv"
)

// ParseCharts ...
func (cc *ChartsConfiguration) ParseCharts() ([]byte, error) {
var out []byte
// Chart ...
type Chart struct {
Version string `yaml:"version"`
Repo string `yaml:"repo"`
Values interface{} `yaml:"values"`
Location string
}

// ParseChart ...
func (c *Chart) ParseChart(name, namespace string) ([]byte, error) {
s := strings.Split(c.Location, "/")

for _, c := range cc.Charts {
resources, err := c.ToResources(cc.Name, cc.Namespace)
if len(s) == 2 && c.Repo != "" {
err := helm.AddRepository(s[0], c.Repo)
if err != nil {
return nil, err
}

out = append(out, resources...)
}

return out, nil
}

// ToResources ...
func (c *Chart) ToResources(name, namespace string) ([]byte, error) {
d, err := yaml.Marshal(c.Config)
d, err := yaml.Marshal(c.Values)
if err != nil {
return nil, err
}
Expand All @@ -53,23 +58,23 @@ func (c *Chart) ToResources(name, namespace string) ([]byte, error) {
return nil, err
}

resources, err := chartToResources(c.Location, c.Version, name, namespace, tmpfile.Name())
resources, err := c.compile(name, namespace, tmpfile.Name())
if err != nil {
return nil, err
}

return resources, nil
}

func chartToResources(location, version, releaseName, namespace, values string) ([]byte, error) {
func (c *Chart) compile(releaseName, namespace, values string) ([]byte, error) {
var output string

location, err := locateChartPath(location, version)
location, err := locateChartPath(c.Location, c.Version)
if err != nil {
return nil, err
}

c, err := chartutil.Load(location)
cr, err := chartutil.Load(location)
if err != nil {
return nil, err
}
Expand All @@ -89,12 +94,12 @@ func chartToResources(location, version, releaseName, namespace, values string)

renderer := engine.New()

vals, err := chartutil.ToRenderValues(c, config, options)
vals, err := chartutil.ToRenderValues(cr, config, options)
if err != nil {
return nil, err
}

out, err := renderer.Render(c, vals)
out, err := renderer.Render(cr, vals)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -165,16 +170,28 @@ func locateChartPath(name, version string) (string, error) {
return filepath.Abs(crepo)
}

settings := environment.EnvSettings{
Home: helmpath.Home(environment.DefaultHelmHome()),
}

settings.PlugDirs = settings.Home.Plugins()

dl := downloader.ChartDownloader{
HelmHome: helmpath.Home(homepath),
Out: os.Stdout,
Getters: getter.All(settings),
}

err := os.MkdirAll(filepath.Dir(crepo), 0755)
if err != nil {
return "", fmt.Errorf("Failed to untar (mkdir): %s", err)
}

version, err = helm.GetAcceptableVersion(name, version)
if err != nil {
return "", fmt.Errorf("Failed to find chart versions: %s", err)
}

filename, _, err := dl.DownloadTo(name, version, filepath.Dir(crepo))
if err != nil {
return "", err
Expand Down
104 changes: 104 additions & 0 deletions chartsconfig/parser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package chartsconfig

import (
"errors"

"github.com/Masterminds/semver"
"github.com/blendle/epp/epp"
"github.com/blendle/kubecrt/chart"
yaml "gopkg.in/yaml.v2"
)

// ChartsConfiguration ...
type ChartsConfiguration struct {
APIVersion string `yaml:"apiVersion"`
Name string `yaml:"name"`
Namespace string `yaml:"namespace"`
ChartsMap []map[string]*chart.Chart `yaml:"charts"`
ChartsList []*chart.Chart
}

// NewChartsConfiguration initialises a new ChartsConfiguration.
func NewChartsConfiguration(input []byte) (*ChartsConfiguration, error) {
m := &ChartsConfiguration{}

out, err := parseEpp(input)
if err != nil {
return nil, err
}

if err = yaml.Unmarshal(out, m); err != nil {
return nil, err
}

for _, a := range m.ChartsMap {
for loc, c := range a {
c.Location = loc
m.ChartsList = append(m.ChartsList, c)
}
}

return m, nil
}

// ParseCharts loops through all charts, and returns the parsed resources.
func (cc *ChartsConfiguration) ParseCharts() ([]byte, error) {
var out []byte

for _, c := range cc.ChartsList {
resources, err := c.ParseChart(cc.Name, cc.Namespace)
if err != nil {
return nil, err
}

out = append(out, resources...)
}

return out, nil
}

// Validate makes sure the charts configuration is configured as expected.
func (cc *ChartsConfiguration) Validate() error {
if cc.APIVersion == "" {
return errors.New("Missing API version, please add \"apiVersion: v1\"")
}

if cc.APIVersion != "v1" {
return errors.New("Unknown API version, please set apiVersion to \"v1\"")
}

if cc.Name == "" {
return errors.New("Missing name, please add \"name: my-app-name\" or pass \"--name=my-app-name\"")
}

if cc.Namespace == "" {
return errors.New("Missing namespace, please add \"namespace: my-namespace\" or pass \"--namespace=my-namespace\"")
}

if len(cc.ChartsList) == 0 {
return errors.New("Missing charts, you need to define at least one chart")
}

for _, c := range cc.ChartsList {
if c.Location == "" {
return errors.New("Invalid or missing chart name")
}

if c.Version != "" {
if _, err := semver.NewConstraint(c.Version); err != nil {
return errors.New(c.Version + ": " + err.Error())
}
}
}

return nil
}

func parseEpp(input []byte) ([]byte, error) {
out, err := epp.Parse(input)
if err != nil {
return nil, err
}

return out, nil
}
11 changes: 6 additions & 5 deletions config/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,11 @@ charts:
# repository, all other repositories require the "repo" configuration (see
# below).
- stable/factorio:
# config is a map of key/value pairs used when compiling the chart. This
# values is a map of key/value pairs used when compiling the chart. This
# uses the same format as in regular chart "values.yaml" files.
#
# see: https://git.io/v9Tyr
config:
values:
resources:
requests:
memory: 1024Mi
Expand All @@ -108,22 +108,23 @@ charts:
# using the "sprig" library.
#
# see: https://masterminds.github.io/sprig/
name: {{ env "MY_SERVER_NAME" | default "hello world!" }}
name: >
{{ env "MY_SERVER_NAME" | default "hello world!" }}
- stable/minecraft:
# version is a semantic version constraint.
#
# see: https://github.com/Masterminds/semver#basic-comparisons
version: ~> 0.1.0
config:
values:
minecraftServer:
difficulty: hard
- opsgoodness/prometheus-operator:
# repo is the location of a repositry, if other than "stable". This is
# the URL you would normally add using "helm repo add NAME URL".
repo: http://charts.opsgoodness.com
config:
values:
sendAnalytics: false
# For the above charts, see here for the default configurations:
Expand Down
17 changes: 9 additions & 8 deletions config/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@ package config

import "errors"

// CLIOptions ...
// CLIOptions contains all the options set through the CLI arguments
type CLIOptions struct {
ChartsConfigPath string
ChartsConfigOptions *ChartsConfigOptions
ChartsConfigurationPath string
ChartsConfigurationOptions *ChartsConfigurationOptions
}

// ChartsConfigOptions ...
type ChartsConfigOptions struct {
// ChartsConfigurationOptions contains the CLI options relevant for the charts
// configuration.
type ChartsConfigurationOptions struct {
Name string
Namespace string
}

// NewCLIOptions ...
// NewCLIOptions takes CLI arguments, and returns a CLIOptions struct.
func NewCLIOptions(cli map[string]interface{}) (*CLIOptions, error) {
path, ok := cli["CHARTS_CONFIG"].(string)
if !ok {
Expand All @@ -25,8 +26,8 @@ func NewCLIOptions(cli map[string]interface{}) (*CLIOptions, error) {
namespace, _ := cli["--namespace"].(string)

c := &CLIOptions{
ChartsConfigPath: path,
ChartsConfigOptions: &ChartsConfigOptions{
ChartsConfigurationPath: path,
ChartsConfigurationOptions: &ChartsConfigurationOptions{
Name: name,
Namespace: namespace,
},
Expand Down
Loading

0 comments on commit 5f47728

Please sign in to comment.