Skip to content

Commit

Permalink
fix: promotion for helmfile and multi-cluster
Browse files Browse the repository at this point in the history
so that we handle the public chart museum URL and include it into the `jx-apps.yml` file in the pull request

Signed-off-by: James Strachan <[email protected]>
  • Loading branch information
jstrachan committed Feb 1, 2020
1 parent 7e11732 commit da1ea5a
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 8 deletions.
11 changes: 10 additions & 1 deletion pkg/cmd/opts/environments.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,14 @@ func (o *CommonOptions) ResolveChartMuseumURL() (string, error) {
if err != nil {
return "", err
}
return services.FindServiceURL(kubeClient, ns, kube.ServiceChartMuseum)
answer, err := services.FindServiceURL(kubeClient, ns, kube.ServiceChartMuseum)
if err != nil {
// lets try find a `chartmusem` ingress
var err2 error
answer, err2 = services.FindIngressURL(kubeClient, ns, "chartmuseum")
if err2 == nil {
return answer, nil
}
}
return answer, err
}
25 changes: 22 additions & 3 deletions pkg/cmd/promote/promote.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/jenkins-x/jx/pkg/builds"
"github.com/jenkins-x/jx/pkg/config"
"github.com/jenkins-x/jx/pkg/envctx"

"github.com/jenkins-x/jx/pkg/cmd/helper"
"github.com/jenkins-x/jx/pkg/kube/naming"
Expand Down Expand Up @@ -83,7 +84,8 @@ type PromoteOptions struct {
prow bool

// Used for testing
CloneDir string
CloneDir string
envContext *envctx.EnvironmentContext
}

type ReleaseInfo struct {
Expand Down Expand Up @@ -252,7 +254,13 @@ func (o *PromoteOptions) EnsureApplicationNameIsDefined(sf searchForChartFn, df

// Run implements this command
func (o *PromoteOptions) Run() error {
err := o.EnsureApplicationNameIsDefined(o.SearchForChart, o.DiscoverAppName)
var err error
o.envContext, err = o.EnvironmentContext(".", false)
if err != nil {
return err
}

err = o.EnsureApplicationNameIsDefined(o.SearchForChart, o.DiscoverAppName)
if err != nil {
return err
}
Expand Down Expand Up @@ -568,6 +576,17 @@ func (o *PromoteOptions) PromoteViaPullRequest(env *v1.Environment, releaseInfo
return err
}
}
chartMuseumURL, err := o.ResolveChartMuseumURL()
if err != nil {
return errors.Wrap(err, "failed to resolve chart museum URL")
}

details, err := o.envContext.ChartDetails(app, chartMuseumURL)
if err != nil {
return err
}
details.DefaultPrefix(appsConfig, "dev")

for i := range appsConfig.Apps {
appConfig := &appsConfig.Apps[i]
if appConfig.Name == app {
Expand All @@ -576,7 +595,7 @@ func (o *PromoteOptions) PromoteViaPullRequest(env *v1.Environment, releaseInfo
}
}
appsConfig.Apps = append(appsConfig.Apps, config.App{
Name: app,
Name: details.Name,
Version: version,
})
return nil
Expand Down
13 changes: 13 additions & 0 deletions pkg/cmd/step/create/helmfile/create_helmfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,19 @@ func (o *CreateHelmfileOptions) generateHelmFile(ec *envctx.EnvironmentContext,

}

for _, ar := range apps.Repositories {
found := false
for _, r := range repositories {
if r.URL == ar.URL {
found = true
break
}
}
if !found {
repositories = append(repositories, ar)
}
}

var releases []helmfile2.ReleaseSpec
for i := range applications {
app := &applications[i]
Expand Down
18 changes: 14 additions & 4 deletions pkg/cmd/step/verify/step_verify_preinstall.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,9 @@ func (o *StepVerifyPreInstallOptions) Run() error {
}

if requirements.Helmfile {
// lets make sure we have the secrets defined as an env var
secretsYaml := os.Getenv("JX_SECRETS_YAML")
if secretsYaml == "" {
return fmt.Errorf("no $JX_SECRETS_YAML environment variable defined.\nPlease point this at your 'secrets.yaml' file.\nSee https://github.com/jenkins-x/enhancements/blob/master/proposals/2/docs/getting-started.md#setting-up-your-secrets\n")
err = o.validateSecretsYAML()
if err != nil {
return err
}
}

Expand Down Expand Up @@ -1056,3 +1055,14 @@ func (o *StepVerifyPreInstallOptions) showProvideFeedbackMessage() (bool, error)
log.Logger().Info("Running in Batch Mode, execution will continue")
return true, nil
}

func (o *StepVerifyPreInstallOptions) validateSecretsYAML() error {
// lets make sure we have the secrets defined as an env var
secretsYaml := os.Getenv("JX_SECRETS_YAML")
if secretsYaml == "" {
return fmt.Errorf("no $JX_SECRETS_YAML environment variable defined.\nPlease point this at your 'secrets.yaml' file.\nSee https://github.com/jenkins-x/enhancements/blob/master/proposals/2/docs/getting-started.md#setting-up-your-secrets\n")
}

// TODO lets validate the contents and populate them?
return nil
}
3 changes: 3 additions & 0 deletions pkg/config/apps.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"path/filepath"
"strings"

"github.com/jenkins-x/jx/pkg/helmfile"
"github.com/jenkins-x/jx/pkg/util"
"github.com/pkg/errors"
"sigs.k8s.io/yaml"
Expand All @@ -27,6 +28,8 @@ var PhaseValues = []string{"system", "apps"}
type AppConfig struct {
// Apps of applications
Apps []App `json:"apps"`
// Repositories list of helm repositories
Repositories []helmfile.RepositorySpec `json:"repositories,omitempty"`
// DefaultNamespace the default namespace to install applications into
DefaultNamespace string `json:"defaultNamespace,omitempty"`
}
Expand Down
55 changes: 55 additions & 0 deletions pkg/envctx/env_context.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package envctx

import (
"fmt"
"path/filepath"
"strings"

v1 "github.com/jenkins-x/jx/pkg/apis/jenkins.io/v1"
"github.com/jenkins-x/jx/pkg/config"
"github.com/jenkins-x/jx/pkg/helmfile"
"github.com/jenkins-x/jx/pkg/kube"
"github.com/jenkins-x/jx/pkg/util"
"github.com/jenkins-x/jx/pkg/versionstream"
Expand Down Expand Up @@ -99,6 +101,59 @@ func (c *EnvironmentContext) ChartDetails(chartName string, repo string) (*Chart
}, nil
}

// DefaultPrefix if the chart has no prefix lets default it based on the apps config
// for helmfile by finding the appConfig.repository entry. If this is a new repository
// lets add it into the appsConfig.repository using the given default prefix.
func (d *ChartDetails) DefaultPrefix(appsConfig *config.AppConfig, defaultPrefix string) {
if d.Prefix != "" {
return
}
found := false
prefixes := map[string]string{}
urls := map[string]string{}
for _, r := range appsConfig.Repositories {
if r.URL == d.Repository {
found = true
}
if r.Name != "" {
urls[r.URL] = r.Name
prefixes[r.Name] = r.URL
}
}

prefix := urls[d.Repository]
if prefix == "" {
if prefixes[defaultPrefix] == "" {
prefix = defaultPrefix
} else {
// the defaultPrefix exists and maps to another URL
// so lets create another similar prefix name as an alias for this repo URL
i := 2
for {
prefix = fmt.Sprintf("%s%d", defaultPrefix, i)
if prefixes[prefix] == "" {
break
}
i++
}
}
}
if !found {
appsConfig.Repositories = append(appsConfig.Repositories, helmfile.RepositorySpec{
Name: prefix,
URL: d.Repository,
})

}
d.SetPrefix(prefix)
}

// SetPrefix sets the prefix and updates the associated name
func (d *ChartDetails) SetPrefix(value string) {
d.Prefix = value
d.Name = d.Prefix + "/" + d.Name
}

// ResolveApplicationDefaults resolves the application defaults in the version stream if there are any
func (c *EnvironmentContext) ResolveApplicationDefaults(chartName string) (*config.AppDefaultsConfig, []string, error) {
valueFiles := []string{}
Expand Down
44 changes: 44 additions & 0 deletions pkg/envctx/env_context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"path"
"testing"

"github.com/jenkins-x/jx/pkg/config"
"github.com/jenkins-x/jx/pkg/envctx"
"github.com/jenkins-x/jx/pkg/versionstream"
"github.com/stretchr/testify/assert"
Expand All @@ -17,11 +18,14 @@ func TestEnvironmentContextResolveChartDetails(t *testing.T) {

ec := createTestEnvironmentContext(t)

appsConfig := &config.AppConfig{}

type testData struct {
Test string
Name string
Repository string
Expected envctx.ChartDetails
AppsConfig *config.AppConfig
}
tests := []testData{
{
Expand Down Expand Up @@ -69,6 +73,32 @@ func TestEnvironmentContextResolveChartDetails(t *testing.T) {
Repository: "",
},
},
{
Test: "findPrefixFromAppsConfig",
Name: "mydemo",
// lets try use an alias
Repository: "http://chartmuseum-jx.myinstall.com",
AppsConfig: appsConfig,
Expected: envctx.ChartDetails{
Name: "dev/mydemo",
Prefix: "dev",
LocalName: "mydemo",
Repository: "http://chartmuseum-jx.myinstall.com",
},
},
{
Test: "findPrefixFromAppsConfigWithDifferentChartMusem",
Name: "mydemo",
// lets try use an alias
Repository: "http://chartmuseum-anotherteam.myinstall.com",
AppsConfig: appsConfig,
Expected: envctx.ChartDetails{
Name: "dev2/mydemo",
Prefix: "dev2",
LocalName: "mydemo",
Repository: "http://chartmuseum-anotherteam.myinstall.com",
},
},
}

for _, test := range tests {
Expand All @@ -78,11 +108,25 @@ func TestEnvironmentContextResolveChartDetails(t *testing.T) {
actual, err := ec.ChartDetails(name, repo)
require.NoError(t, err, "failed to find chart details for %s and %s", name, repo)

if test.AppsConfig != nil {
actual.DefaultPrefix(test.AppsConfig, "dev")
}
assert.Equal(t, expected.Name, actual.Name, "chartDetails.Name for test %s", test.Test)
assert.Equal(t, expected.LocalName, actual.LocalName, "chartDetails.LocalName for test %s", test.Test)
assert.Equal(t, expected.Prefix, actual.Prefix, "chartDetails.Prefix for test %s", test.Test)
assert.Equal(t, expected.Repository, actual.Repository, "chartDetails.Repository for test %s", test.Test)

if test.AppsConfig != nil {
found := false
for _, r := range test.AppsConfig.Repositories {
if r.URL == repo {
t.Logf("the repository %s has been added to the appsConfig.repositories", repo)
found = true
break
}
}
assert.Equal(t, true, found, "could not find repository %s in the appsConfig.repositories", repo)
}
}
}

Expand Down

0 comments on commit da1ea5a

Please sign in to comment.