This is an automated email from the ASF dual-hosted git repository. lburgazzoli pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit 645e1d399aec41c9d93aee68454a8a913e298ae3 Author: lburgazzoli <lburgazz...@gmail.com> AuthorDate: Fri May 31 14:45:55 2019 +0200 Allow to provide custom settings.xml #715 --- README.adoc | 56 ++++- pkg/apis/camel/v1alpha1/build_types.go | 1 - pkg/apis/camel/v1alpha1/common_types.go | 14 ++ .../camel/v1alpha1/integrationplatform_types.go | 2 +- pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go | 55 ++++- pkg/builder/builder_steps.go | 96 ++++---- pkg/builder/builder_steps_test.go | 243 +++++++++++---------- pkg/builder/builder_types.go | 7 +- pkg/builder/builder_utils.go | 42 +--- pkg/builder/builder_utils_test.go | 8 +- pkg/builder/kaniko/kaniko.go | 2 + pkg/builder/s2i/s2i.go | 2 + pkg/cmd/install.go | 178 +++++++++++---- pkg/cmd/install_test.go | 69 ++++++ pkg/controller/integrationcontext/build.go | 12 +- pkg/controller/integrationplatform/initialize.go | 8 - pkg/trait/builder_test.go | 4 +- pkg/trait/rest-dsl.go | 86 +++----- pkg/util/kubernetes/util.go | 44 ++++ pkg/util/maven/maven.go | 84 ++++--- pkg/util/maven/maven_project.go | 39 ++++ .../maven/{maven_test.go => maven_project_test.go} | 88 ++++---- .../kaniko.go => util/maven/maven_settings.go} | 44 +--- pkg/util/maven/maven_settings_test.go | 86 ++++++++ .../{maven_project_types.go => maven_types.go} | 173 +++++++++++---- pkg/util/util.go | 75 ++++--- 26 files changed, 1003 insertions(+), 515 deletions(-) diff --git a/README.adoc b/README.adoc index 0ab236a..7783f7d 100644 --- a/README.adoc +++ b/README.adoc @@ -156,14 +156,58 @@ As example if you want to change the queue size of the seda component, you can u camel.component.seda.queueSize = 10 ``` -==== Configure additional maven repositories +==== Configure Maven settings -Additional maven repositories can be defined at platform installation time or at integration/context build time: +Maven settings can be configured by providing a custom settings.xml through a ConfigMap or secret. +The source for maven settings can be configured using either the `kamel` CLI at installation time or by editing Camel K's IntegrationPlatform: + +- cli: ++ +.Syntax +[source] +---- +kamel install --maven-settings=configmap|secret:name[/key] +---- ++ +.Example +[source] +---- +kamel cmd --maven-settings=configmap:maven-settings/settings.xml +---- + +- IntegrationPlatform: ++ +[source,yaml] +---- +apiVersion: camel.apache.org/v1alpha1 +kind: IntegrationPlatform +metadata: + labels: + app: camel-k + name: camel-k +spec: + build: + maven: + settings: + configMapKeyRef: + key: settings.xml + name: maven-settings +---- + +To quickly create a config map you can use the following command: + +[source] +---- +kubectl create configmap maven-settings --from-file=settings.xml +---- + + +As an installation shortcut, additional maven repositories can be alternatively added using the `--maven-repository` option [source] ---- -kamel cmd --repository http://repo1.my-company.com --repository http://repo2.my-company.com +kamel cmd --maven-repository http://repo1.my-company.com --maven-repository http://repo2.my-company.com ---- A repository url follow conventions used to configure additional repositories in https://karaf.apache.org[_Apache Karaf_] so it can be appended with zero or more of the following flags: @@ -174,7 +218,7 @@ A repository url follow conventions used to configure additional repositories in [source] ---- -kamel install --repository http://repository.apache.org/content/groups/snapshots-group@id=apache@snapshots@noreleases +kamel install --maven-repository http://repository.apache.org/content/groups/snapshots-group@id=apache@snapshots@noreleases ---- This results in: @@ -195,9 +239,9 @@ This results in: </repositories> ---- -[NOTE] +IMPORTANT ==== -The final repositories list is the sum of the repositories defined on the resource (integration/context) and the platform ones +the options `--maven-settings` and `--maven-repository` are mutually exclusive ==== ==== Configure Integration Volumes diff --git a/pkg/apis/camel/v1alpha1/build_types.go b/pkg/apis/camel/v1alpha1/build_types.go index f06f1ca..7a511d5 100644 --- a/pkg/apis/camel/v1alpha1/build_types.go +++ b/pkg/apis/camel/v1alpha1/build_types.go @@ -20,7 +20,6 @@ type BuildSpec struct { Sources []SourceSpec `json:"sources,omitempty"` Resources []ResourceSpec `json:"resources,omitempty"` Dependencies []string `json:"dependencies,omitempty"` - Repositories []string `json:"repositories,omitempty"` BuildDir string `json:"buildDir,omitempty"` } diff --git a/pkg/apis/camel/v1alpha1/common_types.go b/pkg/apis/camel/v1alpha1/common_types.go index c16aca6..4a927dd 100644 --- a/pkg/apis/camel/v1alpha1/common_types.go +++ b/pkg/apis/camel/v1alpha1/common_types.go @@ -18,6 +18,7 @@ limitations under the License. package v1alpha1 import ( + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -71,3 +72,16 @@ type TraitSpec struct { type Configurable interface { Configurations() []ConfigurationSpec } + +// MavenSpec -- +type MavenSpec struct { + Settings ValueSource `json:"settings,omitempty"` +} + +// ValueSource -- +type ValueSource struct { + // Selects a key of a ConfigMap. + ConfigMapKeyRef *corev1.ConfigMapKeySelector `json:"configMapKeyRef,omitempty"` + // Selects a key of a secret. + SecretKeyRef *corev1.SecretKeySelector `json:"secretKeyRef,omitempty" ` +} diff --git a/pkg/apis/camel/v1alpha1/integrationplatform_types.go b/pkg/apis/camel/v1alpha1/integrationplatform_types.go index a07b69e..653a63d 100644 --- a/pkg/apis/camel/v1alpha1/integrationplatform_types.go +++ b/pkg/apis/camel/v1alpha1/integrationplatform_types.go @@ -80,10 +80,10 @@ type IntegrationPlatformBuildSpec struct { BaseImage string `json:"baseImage,omitempty"` Properties map[string]string `json:"properties,omitempty"` LocalRepository string `json:"localRepository,omitempty"` - Repositories []string `json:"repositories,omitempty"` Registry IntegrationPlatformRegistrySpec `json:"registry,omitempty"` Timeout metav1.Duration `json:"timeout,omitempty"` PersistentVolumeClaim string `json:"persistentVolumeClaim,omitempty"` + Maven MavenSpec `json:"maven,omitempty"` } // IntegrationPlatformRegistrySpec -- diff --git a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go index 1233a9e..fab12d9 100644 --- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go @@ -5,6 +5,7 @@ package v1alpha1 import ( + v1 "k8s.io/api/core/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -110,11 +111,6 @@ func (in *BuildSpec) DeepCopyInto(out *BuildSpec) { *out = make([]string, len(*in)) copy(*out, *in) } - if in.Repositories != nil { - in, out := &in.Repositories, &out.Repositories - *out = make([]string, len(*in)) - copy(*out, *in) - } return } @@ -681,13 +677,9 @@ func (in *IntegrationPlatformBuildSpec) DeepCopyInto(out *IntegrationPlatformBui (*out)[key] = val } } - if in.Repositories != nil { - in, out := &in.Repositories, &out.Repositories - *out = make([]string, len(*in)) - copy(*out, *in) - } out.Registry = in.Registry out.Timeout = in.Timeout + in.Maven.DeepCopyInto(&out.Maven) return } @@ -907,6 +899,23 @@ func (in *IntegrationStatus) DeepCopy() *IntegrationStatus { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MavenSpec) DeepCopyInto(out *MavenSpec) { + *out = *in + in.Settings.DeepCopyInto(&out.Settings) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MavenSpec. +func (in *MavenSpec) DeepCopy() *MavenSpec { + if in == nil { + return nil + } + out := new(MavenSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ResourceSpec) DeepCopyInto(out *ResourceSpec) { *out = *in out.DataSpec = in.DataSpec @@ -978,3 +987,29 @@ func (in *TraitSpec) DeepCopy() *TraitSpec { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ValueSource) DeepCopyInto(out *ValueSource) { + *out = *in + if in.ConfigMapKeyRef != nil { + in, out := &in.ConfigMapKeyRef, &out.ConfigMapKeyRef + *out = new(v1.ConfigMapKeySelector) + (*in).DeepCopyInto(*out) + } + if in.SecretKeyRef != nil { + in, out := &in.SecretKeyRef, &out.SecretKeyRef + *out = new(v1.SecretKeySelector) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ValueSource. +func (in *ValueSource) DeepCopy() *ValueSource { + if in == nil { + return nil + } + out := new(ValueSource) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/builder/builder_steps.go b/pkg/builder/builder_steps.go index d9494ab..0b50b15 100644 --- a/pkg/builder/builder_steps.go +++ b/pkg/builder/builder_steps.go @@ -25,6 +25,8 @@ import ( "reflect" "strings" + "github.com/apache/camel-k/pkg/util/kubernetes" + k8sclient "sigs.k8s.io/controller-runtime/pkg/client" "github.com/scylladb/go-set/strset" @@ -45,25 +47,31 @@ func init() { } type steps struct { - GenerateProject Step - InjectDependencies Step - SanitizeDependencies Step - ComputeDependencies Step - StandardPackager Step - IncrementalPackager Step + GenerateProject Step + GenerateProjectSettings Step + InjectDependencies Step + SanitizeDependencies Step + ComputeDependencies Step + StandardPackager Step + IncrementalPackager Step } +// Steps -- var Steps = steps{ GenerateProject: NewStep( ProjectGenerationPhase, generateProject, ), - InjectDependencies: NewStep( + GenerateProjectSettings: NewStep( ProjectGenerationPhase+1, + generateProjectSettings, + ), + InjectDependencies: NewStep( + ProjectGenerationPhase+2, injectDependencies, ), SanitizeDependencies: NewStep( - ProjectGenerationPhase+2, + ProjectGenerationPhase+3, sanitizeDependencies, ), ComputeDependencies: NewStep( @@ -80,6 +88,7 @@ var Steps = steps{ ), } +// RegisterSteps -- func RegisterSteps(steps interface{}) { v := reflect.ValueOf(steps) t := reflect.TypeOf(steps) @@ -107,16 +116,16 @@ func registerStep(steps ...Step) { // generateProject -- func generateProject(ctx *Context) error { - p, err := NewProject(ctx) + p, err := NewMavenProject(ctx) if err != nil { return err } - ctx.Project = p + ctx.Maven.Project = p // // set-up dependencies // - ctx.Project.AddDependencyGAV("org.apache.camel.k", "camel-k-runtime-jvm", ctx.Build.RuntimeVersion) + ctx.Maven.Project.AddDependencyGAV("org.apache.camel.k", "camel-k-runtime-jvm", ctx.Build.RuntimeVersion) for _, d := range ctx.Build.Dependencies { switch { @@ -127,7 +136,7 @@ func generateProject(ctx *Context) error { artifactID = "camel-" + artifactID } - ctx.Project.AddDependencyGAV("org.apache.camel", artifactID, "") + ctx.Maven.Project.AddDependencyGAV("org.apache.camel", artifactID, "") case strings.HasPrefix(d, "camel-k:"): artifactID := strings.TrimPrefix(d, "camel-k:") @@ -135,16 +144,16 @@ func generateProject(ctx *Context) error { artifactID = "camel-" + artifactID } - ctx.Project.AddDependencyGAV("org.apache.camel.k", artifactID, ctx.Build.RuntimeVersion) + ctx.Maven.Project.AddDependencyGAV("org.apache.camel.k", artifactID, ctx.Build.RuntimeVersion) case strings.HasPrefix(d, "mvn:"): mid := strings.TrimPrefix(d, "mvn:") gav := strings.Replace(mid, "/", ":", -1) - ctx.Project.AddEncodedDependencyGAV(gav) + ctx.Maven.Project.AddEncodedDependencyGAV(gav) case strings.HasPrefix(d, "runtime:"): artifactID := strings.Replace(d, "runtime:", "camel-k-runtime-", 1) - ctx.Project.AddDependencyGAV("org.apache.camel.k", artifactID, ctx.Build.RuntimeVersion) + ctx.Maven.Project.AddDependencyGAV("org.apache.camel.k", artifactID, ctx.Build.RuntimeVersion) case strings.HasPrefix(d, "bom:"): // no-op default: @@ -153,7 +162,7 @@ func generateProject(ctx *Context) error { } // Add Log4j 2 SLF4J binding as default logging impl - ctx.Project.AddDependency(maven.Dependency{ + ctx.Maven.Project.AddDependency(maven.Dependency{ GroupID: "org.apache.logging.log4j", ArtifactID: "log4j-slf4j-impl", Version: "2.11.2", @@ -163,12 +172,25 @@ func generateProject(ctx *Context) error { return nil } +// generateProjectSettings -- +func generateProjectSettings(ctx *Context) error { + val, err := kubernetes.ResolveValueSource(ctx.C, ctx.Client, ctx.Namespace, &ctx.Build.Platform.Build.Maven.Settings) + if err != nil { + return err + } + if val != "" { + ctx.Maven.SettingsData = []byte(val) + } + + return nil +} + func injectDependencies(ctx *Context) error { // // Add dependencies from catalog // - deps := make([]maven.Dependency, len(ctx.Project.Dependencies)) - copy(deps, ctx.Project.Dependencies) + deps := make([]maven.Dependency, len(ctx.Maven.Project.Dependencies)) + copy(deps, ctx.Maven.Project.Dependencies) for _, d := range deps { if a, ok := ctx.Catalog.Artifacts[d.ArtifactID]; ok { @@ -178,7 +200,7 @@ func injectDependencies(ctx *Context) error { ArtifactID: dep.ArtifactID, } - ctx.Project.AddDependency(md) + ctx.Maven.Project.AddDependency(md) for _, e := range dep.Exclusions { me := maven.Exclusion{ @@ -186,7 +208,7 @@ func injectDependencies(ctx *Context) error { ArtifactID: e.ArtifactID, } - ctx.Project.AddDependencyExclusion(md, me) + ctx.Maven.Project.AddDependencyExclusion(md, me) } } } @@ -194,8 +216,8 @@ func injectDependencies(ctx *Context) error { // // post process dependencies // - deps = make([]maven.Dependency, len(ctx.Project.Dependencies)) - copy(deps, ctx.Project.Dependencies) + deps = make([]maven.Dependency, len(ctx.Maven.Project.Dependencies)) + copy(deps, ctx.Maven.Project.Dependencies) for _, d := range deps { if a, ok := ctx.Catalog.Artifacts[d.ArtifactID]; ok { @@ -210,7 +232,7 @@ func injectDependencies(ctx *Context) error { ArtifactID: e.ArtifactID, } - ctx.Project.AddDependencyExclusion(md, me) + ctx.Maven.Project.AddDependencyExclusion(md, me) } } } @@ -219,21 +241,21 @@ func injectDependencies(ctx *Context) error { } func sanitizeDependencies(ctx *Context) error { - for i := 0; i < len(ctx.Project.Dependencies); i++ { - dep := ctx.Project.Dependencies[i] + for i := 0; i < len(ctx.Maven.Project.Dependencies); i++ { + dep := ctx.Maven.Project.Dependencies[i] switch dep.GroupID { case "org.apache.camel": // // Remove the version so we force using the one configured by the bom // - ctx.Project.Dependencies[i].Version = "" + ctx.Maven.Project.Dependencies[i].Version = "" case "org.apache.camel.k": // // Force every runtime dependency to have the required version discardin // any version eventually set on the catalog // - ctx.Project.Dependencies[i].Version = ctx.Build.RuntimeVersion + ctx.Maven.Project.Dependencies[i].Version = ctx.Build.RuntimeVersion } } @@ -241,23 +263,17 @@ func sanitizeDependencies(ctx *Context) error { } func computeDependencies(ctx *Context) error { - p := path.Join(ctx.Path, "maven") - - err := maven.CreateStructure(p, ctx.Project) - if err != nil { - return err - } + mc := maven.NewContext(path.Join(ctx.Path, "maven"), ctx.Maven.Project) + mc.Settings = ctx.Maven.Settings + mc.SettingsData = ctx.Maven.SettingsData + mc.AddArguments(maven.ExtraOptions(ctx.Build.Platform.Build.LocalRepository)...) + mc.AddArgumentf("org.apache.camel.k:camel-k-maven-plugin:%s:generate-dependency-list", ctx.Build.RuntimeVersion) - opts := make([]string, 0, 2) - opts = append(opts, maven.ExtraOptions(ctx.Build.Platform.Build.LocalRepository)...) - opts = append(opts, fmt.Sprintf("org.apache.camel.k:camel-k-maven-plugin:%s:generate-dependency-list", ctx.Build.RuntimeVersion)) - - err = maven.Run(p, opts...) - if err != nil { + if err := maven.Run(mc); err != nil { return errors.Wrap(err, "failure while determining classpath") } - dependencies := path.Join(p, "target", "dependencies.yaml") + dependencies := path.Join(mc.Path, "target", "dependencies.yaml") content, err := ioutil.ReadFile(dependencies) if err != nil { return err diff --git a/pkg/builder/builder_steps_test.go b/pkg/builder/builder_steps_test.go index dcdfd12..b576f8d 100644 --- a/pkg/builder/builder_steps_test.go +++ b/pkg/builder/builder_steps_test.go @@ -20,6 +20,7 @@ package builder import ( "testing" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" @@ -50,7 +51,7 @@ func TestRegisterDuplicatedSteps(t *testing.T) { }) } -func TestMavenRepositories(t *testing.T) { +func TestGenerateJvmProject(t *testing.T) { catalog, err := test.DefaultCatalog() assert.Nil(t, err) @@ -66,10 +67,6 @@ func TestMavenRepositories(t *testing.T) { Dependencies: []string{ "runtime:jvm", }, - Repositories: []string{ - "https://repository.apache.org/content/repositories/snapshots@id=apache.snapshots@snapshots@noreleases", - "https://oss.sonatype.org/content/repositories/snapshots/@id=sonatype.snapshots@snapshots", - }, }, } @@ -78,90 +75,134 @@ func TestMavenRepositories(t *testing.T) { err = injectDependencies(&ctx) assert.Nil(t, err) - assert.Equal(t, 2, len(ctx.Project.Repositories)) - assert.Equal(t, 2, len(ctx.Project.PluginRepositories)) + assert.Equal(t, 1, len(ctx.Maven.Project.DependencyManagement.Dependencies)) + assert.Equal(t, "org.apache.camel", ctx.Maven.Project.DependencyManagement.Dependencies[0].GroupID) + assert.Equal(t, "camel-bom", ctx.Maven.Project.DependencyManagement.Dependencies[0].ArtifactID) + assert.Equal(t, catalog.Version, ctx.Maven.Project.DependencyManagement.Dependencies[0].Version) + assert.Equal(t, "pom", ctx.Maven.Project.DependencyManagement.Dependencies[0].Type) + assert.Equal(t, "import", ctx.Maven.Project.DependencyManagement.Dependencies[0].Scope) - assert.Contains(t, ctx.Project.Repositories, maven.Repository{ - ID: "apache.snapshots", - URL: "https://repository.apache.org/content/repositories/snapshots", - Snapshots: maven.RepositoryPolicy{Enabled: true}, - Releases: maven.RepositoryPolicy{Enabled: false}, + assert.Equal(t, 4, len(ctx.Maven.Project.Dependencies)) + assert.Contains(t, ctx.Maven.Project.Dependencies, maven.Dependency{ + GroupID: "org.apache.camel.k", + ArtifactID: "camel-k-runtime-jvm", + Version: defaults.RuntimeVersion, + Type: "jar", }) - - assert.Contains(t, ctx.Project.Repositories, maven.Repository{ - ID: "sonatype.snapshots", - URL: "https://oss.sonatype.org/content/repositories/snapshots/", - Snapshots: maven.RepositoryPolicy{Enabled: true}, - Releases: maven.RepositoryPolicy{Enabled: true}, + assert.Contains(t, ctx.Maven.Project.Dependencies, maven.Dependency{ + GroupID: "org.apache.camel", + ArtifactID: "camel-core", }) - - assert.Contains(t, ctx.Project.PluginRepositories, maven.Repository{ - ID: "apache.snapshots", - URL: "https://repository.apache.org/content/repositories/snapshots", - Snapshots: maven.RepositoryPolicy{Enabled: true}, - Releases: maven.RepositoryPolicy{Enabled: false}, + assert.Contains(t, ctx.Maven.Project.Dependencies, maven.Dependency{ + GroupID: "org.apache.camel.k", + ArtifactID: "camel-k-adapter-camel-2", }) - - assert.Contains(t, ctx.Project.PluginRepositories, maven.Repository{ - ID: "sonatype.snapshots", - URL: "https://oss.sonatype.org/content/repositories/snapshots/", - Snapshots: maven.RepositoryPolicy{Enabled: true}, - Releases: maven.RepositoryPolicy{Enabled: true}, + assert.Contains(t, ctx.Maven.Project.Dependencies, maven.Dependency{ + GroupID: "org.apache.logging.log4j", + ArtifactID: "log4j-slf4j-impl", + Version: "2.11.2", + Scope: "runtime", }) } -func TestGenerateJvmProject(t *testing.T) { +func TestMavenSettingsFromConfigMap(t *testing.T) { catalog, err := test.DefaultCatalog() assert.Nil(t, err) + c, err := test.NewFakeClient( + &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "ConfigMap", + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "ns", + Name: "maven-settings", + }, + Data: map[string]string{ + "settings.xml": "setting-data", + }, + }, + ) + ctx := Context{ - Catalog: catalog, + Catalog: catalog, + Client: c, + Namespace: "ns", Build: v1alpha1.BuildSpec{ RuntimeVersion: defaults.RuntimeVersion, Platform: v1alpha1.IntegrationPlatformSpec{ Build: v1alpha1.IntegrationPlatformBuildSpec{ CamelVersion: catalog.Version, + Maven: v1alpha1.MavenSpec{ + Settings: v1alpha1.ValueSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "maven-settings", + }, + Key: "settings.xml", + }, + }, + }, }, }, - Dependencies: []string{ - "runtime:jvm", - }, }, } - err = generateProject(&ctx) + err = generateProjectSettings(&ctx) assert.Nil(t, err) - err = injectDependencies(&ctx) + + assert.Equal(t, []byte("setting-data"), ctx.Maven.SettingsData) +} + +func TestMavenSettingsFromSecret(t *testing.T) { + catalog, err := test.DefaultCatalog() assert.Nil(t, err) - assert.Equal(t, 1, len(ctx.Project.DependencyManagement.Dependencies)) - assert.Equal(t, "org.apache.camel", ctx.Project.DependencyManagement.Dependencies[0].GroupID) - assert.Equal(t, "camel-bom", ctx.Project.DependencyManagement.Dependencies[0].ArtifactID) - assert.Equal(t, catalog.Version, ctx.Project.DependencyManagement.Dependencies[0].Version) - assert.Equal(t, "pom", ctx.Project.DependencyManagement.Dependencies[0].Type) - assert.Equal(t, "import", ctx.Project.DependencyManagement.Dependencies[0].Scope) + c, err := test.NewFakeClient( + &corev1.Secret{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "Secret", + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "ns", + Name: "maven-settings", + }, + Data: map[string][]byte{ + "settings.xml": []byte("setting-data"), + }, + }, + ) - assert.Equal(t, 4, len(ctx.Project.Dependencies)) - assert.Contains(t, ctx.Project.Dependencies, maven.Dependency{ - GroupID: "org.apache.camel.k", - ArtifactID: "camel-k-runtime-jvm", - Version: defaults.RuntimeVersion, - Type: "jar", - }) - assert.Contains(t, ctx.Project.Dependencies, maven.Dependency{ - GroupID: "org.apache.camel", - ArtifactID: "camel-core", - }) - assert.Contains(t, ctx.Project.Dependencies, maven.Dependency{ - GroupID: "org.apache.camel.k", - ArtifactID: "camel-k-adapter-camel-2", - }) - assert.Contains(t, ctx.Project.Dependencies, maven.Dependency{ - GroupID: "org.apache.logging.log4j", - ArtifactID: "log4j-slf4j-impl", - Version: "2.11.2", - Scope: "runtime", - }) + ctx := Context{ + Catalog: catalog, + Client: c, + Namespace: "ns", + Build: v1alpha1.BuildSpec{ + RuntimeVersion: defaults.RuntimeVersion, + Platform: v1alpha1.IntegrationPlatformSpec{ + Build: v1alpha1.IntegrationPlatformBuildSpec{ + CamelVersion: catalog.Version, + Maven: v1alpha1.MavenSpec{ + Settings: v1alpha1.ValueSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "maven-settings", + }, + Key: "settings.xml", + }, + }, + }, + }, + }, + }, + } + + err = generateProjectSettings(&ctx) + assert.Nil(t, err) + + assert.Equal(t, []byte("setting-data"), ctx.Maven.SettingsData) } func TestGenerateGroovyProject(t *testing.T) { @@ -188,40 +229,40 @@ func TestGenerateGroovyProject(t *testing.T) { err = injectDependencies(&ctx) assert.Nil(t, err) - assert.Equal(t, 1, len(ctx.Project.DependencyManagement.Dependencies)) - assert.Equal(t, "org.apache.camel", ctx.Project.DependencyManagement.Dependencies[0].GroupID) - assert.Equal(t, "camel-bom", ctx.Project.DependencyManagement.Dependencies[0].ArtifactID) - assert.Equal(t, catalog.Version, ctx.Project.DependencyManagement.Dependencies[0].Version) - assert.Equal(t, "pom", ctx.Project.DependencyManagement.Dependencies[0].Type) - assert.Equal(t, "import", ctx.Project.DependencyManagement.Dependencies[0].Scope) + assert.Equal(t, 1, len(ctx.Maven.Project.DependencyManagement.Dependencies)) + assert.Equal(t, "org.apache.camel", ctx.Maven.Project.DependencyManagement.Dependencies[0].GroupID) + assert.Equal(t, "camel-bom", ctx.Maven.Project.DependencyManagement.Dependencies[0].ArtifactID) + assert.Equal(t, catalog.Version, ctx.Maven.Project.DependencyManagement.Dependencies[0].Version) + assert.Equal(t, "pom", ctx.Maven.Project.DependencyManagement.Dependencies[0].Type) + assert.Equal(t, "import", ctx.Maven.Project.DependencyManagement.Dependencies[0].Scope) - assert.Equal(t, 6, len(ctx.Project.Dependencies)) + assert.Equal(t, 6, len(ctx.Maven.Project.Dependencies)) - assert.Contains(t, ctx.Project.Dependencies, maven.Dependency{ + assert.Contains(t, ctx.Maven.Project.Dependencies, maven.Dependency{ GroupID: "org.apache.camel.k", ArtifactID: "camel-k-runtime-jvm", Version: defaults.RuntimeVersion, Type: "jar", }) - assert.Contains(t, ctx.Project.Dependencies, maven.Dependency{ + assert.Contains(t, ctx.Maven.Project.Dependencies, maven.Dependency{ GroupID: "org.apache.camel.k", ArtifactID: "camel-k-runtime-groovy", Version: defaults.RuntimeVersion, Type: "jar", }) - assert.Contains(t, ctx.Project.Dependencies, maven.Dependency{ + assert.Contains(t, ctx.Maven.Project.Dependencies, maven.Dependency{ GroupID: "org.apache.camel", ArtifactID: "camel-core", }) - assert.Contains(t, ctx.Project.Dependencies, maven.Dependency{ + assert.Contains(t, ctx.Maven.Project.Dependencies, maven.Dependency{ GroupID: "org.apache.camel.k", ArtifactID: "camel-k-adapter-camel-2", }) - assert.Contains(t, ctx.Project.Dependencies, maven.Dependency{ + assert.Contains(t, ctx.Maven.Project.Dependencies, maven.Dependency{ GroupID: "org.apache.camel", ArtifactID: "camel-groovy", }) - assert.Contains(t, ctx.Project.Dependencies, maven.Dependency{ + assert.Contains(t, ctx.Maven.Project.Dependencies, maven.Dependency{ GroupID: "org.apache.logging.log4j", ArtifactID: "log4j-slf4j-impl", Version: "2.11.2", @@ -229,46 +270,6 @@ func TestGenerateGroovyProject(t *testing.T) { }) } -func TestGenerateProjectWithRepositories(t *testing.T) { - catalog, err := test.DefaultCatalog() - assert.Nil(t, err) - - ctx := Context{ - Catalog: catalog, - Build: v1alpha1.BuildSpec{ - Platform: v1alpha1.IntegrationPlatformSpec{ - Build: v1alpha1.IntegrationPlatformBuildSpec{ - CamelVersion: catalog.Version, - }, - }, - Repositories: []string{ - "https://repository.apache.org/content/groups/snapshots-group@id=apache-snapshots@snapshots@noreleases", - "https://oss.sonatype.org/content/repositories/ops4j-snapshots@id=ops4j-snapshots@snapshots@noreleases", - }, - }, - } - - err = generateProject(&ctx) - assert.Nil(t, err) - err = injectDependencies(&ctx) - assert.Nil(t, err) - - assert.Equal(t, 1, len(ctx.Project.DependencyManagement.Dependencies)) - assert.Equal(t, "org.apache.camel", ctx.Project.DependencyManagement.Dependencies[0].GroupID) - assert.Equal(t, "camel-bom", ctx.Project.DependencyManagement.Dependencies[0].ArtifactID) - assert.Equal(t, catalog.Version, ctx.Project.DependencyManagement.Dependencies[0].Version) - assert.Equal(t, "pom", ctx.Project.DependencyManagement.Dependencies[0].Type) - assert.Equal(t, "import", ctx.Project.DependencyManagement.Dependencies[0].Scope) - - assert.Equal(t, 2, len(ctx.Project.Repositories)) - assert.Equal(t, "apache-snapshots", ctx.Project.Repositories[0].ID) - assert.False(t, ctx.Project.Repositories[0].Releases.Enabled) - assert.True(t, ctx.Project.Repositories[0].Snapshots.Enabled) - assert.Equal(t, "ops4j-snapshots", ctx.Project.Repositories[1].ID) - assert.False(t, ctx.Project.Repositories[1].Releases.Enabled) - assert.True(t, ctx.Project.Repositories[1].Snapshots.Enabled) -} - func TestSanitizeDependencies(t *testing.T) { catalog, err := test.DefaultCatalog() assert.Nil(t, err) @@ -298,23 +299,23 @@ func TestSanitizeDependencies(t *testing.T) { err = sanitizeDependencies(&ctx) assert.Nil(t, err) - assert.Contains(t, ctx.Project.Dependencies, maven.Dependency{ + assert.Contains(t, ctx.Maven.Project.Dependencies, maven.Dependency{ GroupID: "org.apache.camel.k", ArtifactID: "camel-k-runtime-jvm", Version: defaults.RuntimeVersion, Type: "jar", }) - assert.Contains(t, ctx.Project.Dependencies, maven.Dependency{ + assert.Contains(t, ctx.Maven.Project.Dependencies, maven.Dependency{ GroupID: "org.apache.camel", ArtifactID: "camel-core", Type: "jar", }) - assert.Contains(t, ctx.Project.Dependencies, maven.Dependency{ + assert.Contains(t, ctx.Maven.Project.Dependencies, maven.Dependency{ GroupID: "org.apache.camel", ArtifactID: "camel-undertow", Type: "jar", }) - assert.Contains(t, ctx.Project.Dependencies, maven.Dependency{ + assert.Contains(t, ctx.Maven.Project.Dependencies, maven.Dependency{ GroupID: "com.mycompany", ArtifactID: "my-dep", Version: "1.2.3", diff --git a/pkg/builder/builder_types.go b/pkg/builder/builder_types.go index 9cf17d1..549e9aa 100644 --- a/pkg/builder/builder_types.go +++ b/pkg/builder/builder_types.go @@ -107,13 +107,18 @@ type Context struct { PublicImage string Error error Namespace string - Project maven.Project Path string Artifacts []v1alpha1.Artifact SelectedArtifacts []v1alpha1.Artifact Archive string ContextFilter func(integrationContext *v1alpha1.IntegrationContext) bool Resources []Resource + + Maven struct { + Project maven.Project + Settings *maven.Settings + SettingsData []byte + } } // HasRequiredImage -- diff --git a/pkg/builder/builder_utils.go b/pkg/builder/builder_utils.go index 2093566..571bece 100644 --- a/pkg/builder/builder_utils.go +++ b/pkg/builder/builder_utils.go @@ -18,8 +18,6 @@ limitations under the License. package builder import ( - "encoding/xml" - "fmt" "strings" "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" @@ -28,6 +26,7 @@ import ( "github.com/apache/camel-k/pkg/util/maven" ) +// StepIDsFor -- func StepIDsFor(steps ...Step) []string { IDs := make([]string, 0) for _, step := range steps { @@ -46,8 +45,8 @@ func artifactIDs(artifacts []v1alpha1.Artifact) []string { return result } -// NewProject -- -func NewProject(ctx *Context) (maven.Project, error) { +// NewMavenProject -- +func NewMavenProject(ctx *Context) (maven.Project, error) { // // Catalog // @@ -60,19 +59,11 @@ func NewProject(ctx *Context) (maven.Project, error) { ctx.Catalog = c } - p := maven.Project{ - XMLName: xml.Name{Local: "project"}, - XMLNs: "http://maven.apache.org/POM/4.0.0", - XMLNsXsi: "http://www.w3.org/2001/XMLSchema-instance", - XsiSchemaLocation: "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd", - ModelVersion: "4.0.0", - GroupID: "org.apache.camel.k.integration", - ArtifactID: "camel-k-integration", - Version: defaults.Version, - Properties: ctx.Build.Platform.Build.Properties, - DependencyManagement: maven.DependencyManagement{Dependencies: make([]maven.Dependency, 0)}, - Dependencies: make([]maven.Dependency, 0), - } + p := maven.NewProjectWithGAV("org.apache.camel.k.integration", "camel-k-integration", defaults.Version) + p.Properties = ctx.Build.Platform.Build.Properties + p.DependencyManagement = maven.DependencyManagement{Dependencies: make([]maven.Dependency, 0)} + p.Dependencies = make([]maven.Dependency, 0) + // // DependencyManagement // @@ -103,23 +94,6 @@ func NewProject(ctx *Context) (maven.Project, error) { }) } } - //p.DependencyManagement.Dependencies = dm - - // - // Repositories - // - p.Repositories = make([]maven.Repository, 0, len(ctx.Build.Repositories)) - p.PluginRepositories = make([]maven.Repository, 0, len(ctx.Build.Repositories)) - - for i, r := range ctx.Build.Repositories { - repo := maven.NewRepository(r) - if repo.ID == "" { - repo.ID = fmt.Sprintf("repo-%03d", i) - } - - p.Repositories = append(p.Repositories, repo) - p.PluginRepositories = append(p.PluginRepositories, repo) - } return p, nil } diff --git a/pkg/builder/builder_utils_test.go b/pkg/builder/builder_utils_test.go index 1491d51..5bd0075 100644 --- a/pkg/builder/builder_utils_test.go +++ b/pkg/builder/builder_utils_test.go @@ -52,22 +52,22 @@ func TestNewProject(t *testing.T) { err = generateProject(&ctx) assert.Nil(t, err) - assert.Len(t, ctx.Project.DependencyManagement.Dependencies, 3) - assert.Contains(t, ctx.Project.DependencyManagement.Dependencies, maven.Dependency{ + assert.Len(t, ctx.Maven.Project.DependencyManagement.Dependencies, 3) + assert.Contains(t, ctx.Maven.Project.DependencyManagement.Dependencies, maven.Dependency{ GroupID: "org.apache.camel", ArtifactID: "camel-bom", Version: ctx.Catalog.Version, Type: "pom", Scope: "import", }) - assert.Contains(t, ctx.Project.DependencyManagement.Dependencies, maven.Dependency{ + assert.Contains(t, ctx.Maven.Project.DependencyManagement.Dependencies, maven.Dependency{ GroupID: "my.company", ArtifactID: "my-artifact-1", Version: "1.0.0", Type: "pom", Scope: "import", }) - assert.Contains(t, ctx.Project.DependencyManagement.Dependencies, maven.Dependency{ + assert.Contains(t, ctx.Maven.Project.DependencyManagement.Dependencies, maven.Dependency{ GroupID: "my.company", ArtifactID: "my-artifact-2", Version: "2.0.0", diff --git a/pkg/builder/kaniko/kaniko.go b/pkg/builder/kaniko/kaniko.go index 858799e..f5e53cb 100644 --- a/pkg/builder/kaniko/kaniko.go +++ b/pkg/builder/kaniko/kaniko.go @@ -29,6 +29,7 @@ type steps struct { Publisher builder.Step } +// Steps -- var Steps = steps{ Publisher: builder.NewStep( builder.ApplicationPublishPhase, @@ -39,6 +40,7 @@ var Steps = steps{ // DefaultSteps -- var DefaultSteps = []builder.Step{ builder.Steps.GenerateProject, + builder.Steps.GenerateProjectSettings, builder.Steps.InjectDependencies, builder.Steps.SanitizeDependencies, builder.Steps.ComputeDependencies, diff --git a/pkg/builder/s2i/s2i.go b/pkg/builder/s2i/s2i.go index 3089a21..d323233 100644 --- a/pkg/builder/s2i/s2i.go +++ b/pkg/builder/s2i/s2i.go @@ -30,6 +30,7 @@ type steps struct { ReplaceHost builder.Step } +// Steps -- var Steps = steps{ Publisher: builder.NewStep( builder.ApplicationPublishPhase, @@ -44,6 +45,7 @@ var Steps = steps{ // DefaultSteps -- var DefaultSteps = []builder.Step{ builder.Steps.GenerateProject, + builder.Steps.GenerateProjectSettings, builder.Steps.InjectDependencies, builder.Steps.SanitizeDependencies, builder.Steps.ComputeDependencies, diff --git a/pkg/cmd/install.go b/pkg/cmd/install.go index 1a9a9fe..bb93c09 100644 --- a/pkg/cmd/install.go +++ b/pkg/cmd/install.go @@ -19,9 +19,14 @@ package cmd import ( "fmt" + "regexp" "strings" "time" + "github.com/apache/camel-k/pkg/util" + + "github.com/apache/camel-k/pkg/util/maven" + "github.com/apache/camel-k/deploy" "github.com/apache/camel-k/pkg/apis" "go.uber.org/multierr" @@ -36,7 +41,9 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" + corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func newCmdInstall(rootCmdOptions *RootCmdOptions) *cobra.Command { @@ -61,9 +68,6 @@ func newCmdInstall(rootCmdOptions *RootCmdOptions) *cobra.Command { cmd.Flags().StringVar(&impl.registry.Address, "registry", "", "A Docker registry that can be used to publish images") cmd.Flags().StringVar(&impl.registry.Secret, "registry-secret", "", "A secret used to push/pull images to the Docker registry") cmd.Flags().BoolVar(&impl.registry.Insecure, "registry-insecure", false, "Configure to configure registry access in insecure mode or not") - cmd.Flags().StringSliceVar(&impl.repositories, "repository", nil, "Add a maven repository") - cmd.Flags().BoolVar(&impl.snapshotRepositories, "snapshot-repositories", false, "Automatically include known snapshot repositories") - cmd.Flags().StringVar(&impl.localRepository, "local-repository", "", "Location of the local maven repository") cmd.Flags().StringSliceVarP(&impl.properties, "property", "p", nil, "Add a camel property") cmd.Flags().StringVar(&impl.camelVersion, "camel-version", "", "Set the camel version") cmd.Flags().StringVar(&impl.runtimeVersion, "runtime-version", "", "Set the camel-k runtime version") @@ -73,6 +77,11 @@ func newCmdInstall(rootCmdOptions *RootCmdOptions) *cobra.Command { cmd.Flags().StringVar(&impl.buildStrategy, "build-strategy", "", "Set the build strategy") cmd.Flags().StringVar(&impl.buildTimeout, "build-timeout", "", "Set how long the build process can last") + // maven settings + cmd.Flags().StringVar(&impl.localRepository, "local-repository", "", "Location of the local maven repository") + cmd.Flags().StringVar(&impl.mavenSettings, "maven-settings", "", "Configure the source of the maven settings (configmap|secret:name[/key])") + cmd.Flags().StringSliceVar(&impl.mavenRpositories, "maven-repository", nil, "Add a maven repository") + // completion support configureBashAnnotationForFlag( &cmd, @@ -87,23 +96,23 @@ func newCmdInstall(rootCmdOptions *RootCmdOptions) *cobra.Command { type installCmdOptions struct { *RootCmdOptions - wait bool - clusterSetupOnly bool - skipClusterSetup bool - exampleSetup bool - snapshotRepositories bool - outputFormat string - camelVersion string - runtimeVersion string - baseImage string - operatorImage string - localRepository string - buildStrategy string - buildTimeout string - repositories []string - properties []string - contexts []string - registry v1alpha1.IntegrationPlatformRegistrySpec + wait bool + clusterSetupOnly bool + skipClusterSetup bool + exampleSetup bool + outputFormat string + camelVersion string + runtimeVersion string + baseImage string + operatorImage string + localRepository string + buildStrategy string + buildTimeout string + mavenRpositories []string + mavenSettings string + properties []string + contexts []string + registry v1alpha1.IntegrationPlatformRegistrySpec } // nolint: gocyclo @@ -164,23 +173,6 @@ func (o *installCmdOptions) install(_ *cobra.Command, _ []string) error { if o.localRepository != "" { platform.Spec.Build.LocalRepository = o.localRepository } - if len(o.repositories) > 0 { - platform.Spec.Build.Repositories = o.repositories - } - if o.snapshotRepositories { - if platform.Spec.Build.Repositories == nil { - platform.Spec.Build.Repositories = make([]string, 0) - } - - platform.Spec.Build.Repositories = append( - platform.Spec.Build.Repositories, - "https://repository.apache.org/content/repositories/snapshots@id=apache.snapshots@snapshots", - ) - platform.Spec.Build.Repositories = append( - platform.Spec.Build.Repositories, - "https://oss.sonatype.org/content/repositories/snapshots/@id=sonatype.snapshots@snapshots", - ) - } if o.camelVersion != "" { platform.Spec.Build.CamelVersion = o.camelVersion } @@ -209,6 +201,68 @@ func (o *installCmdOptions) install(_ *cobra.Command, _ []string) error { platform.Spec.Build.Timeout.Duration = d } + if len(o.mavenRpositories) > 0 { + o.mavenSettings = fmt.Sprintf("configmap:%s-maven-settings/settings.xml", platform.Name) + + settings := maven.NewSettings() + repositories := make([]maven.Repository, 0, len(o.mavenRpositories)) + + for i, r := range o.mavenRpositories { + repository := maven.NewRepository(r) + if repository.ID == "" { + repository.ID = fmt.Sprintf("repository-%03d", i) + } + + repositories = append(repositories, repository) + } + + settings.Profiles = []maven.Profile{ + { + ID: "maven-settings", + Activation: maven.Activation{ + ActiveByDefault: true, + }, + Repositories: repositories, + }, + } + + data, err := util.EncodeXML(settings) + if err != nil { + return err + } + + cm := corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: platform.Name + "-maven-settings", + Namespace: namespace, + Labels: map[string]string{ + "app": "camel-k", + }, + }, + Data: map[string]string{ + "settings.xml": string(data), + }, + } + + err = install.RuntimeObjectOrCollect(o.Context, c, namespace, collection, &cm) + if err != nil { + return err + } + } + + if o.mavenSettings != "" { + mavenSettings, err := decodeMavenSettings(o.mavenSettings) + if err != nil { + return err + } + + platform.Spec.Build.Maven.Settings = mavenSettings + } + platform.Spec.Resources.Contexts = o.contexts err = install.RuntimeObjectOrCollect(o.Context, c, namespace, collection, platform) @@ -301,6 +355,11 @@ func (o *installCmdOptions) validate(_ *cobra.Command, _ []string) error { err := errorIfContextIsNotAvailable(schema, context) result = multierr.Append(result, err) } + + if len(o.mavenRpositories) > 0 && o.mavenSettings != "" { + result = fmt.Errorf("incompatible options combinations: you canno set both mavenRpository and mavenSettings") + } + return result } @@ -322,3 +381,48 @@ func errorIfContextIsNotAvailable(schema *runtime.Scheme, context string) error } return errors.Errorf("Unknown context '%s'", context) } + +func decodeMavenSettings(mavenSettings string) (v1alpha1.ValueSource, error) { + sub := make([]string, 0) + rex := regexp.MustCompile(`^(configmap|secret):([a-zA-Z0-9][a-zA-Z0-9-]*)(/([a-zA-Z0-9].*))?$`) + hits := rex.FindAllStringSubmatch(mavenSettings, -1) + + for _, hit := range hits { + if len(hit) > 1 { + for _, match := range hit[1:] { + sub = append(sub, match) + } + } + } + + if len(sub) >= 2 { + key := "settings.xml" + + if len(sub) == 4 { + key = sub[3] + } + + if sub[0] == "configmap" { + return v1alpha1.ValueSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: sub[1], + }, + Key: key, + }, + }, nil + } + if sub[0] == "secret" { + return v1alpha1.ValueSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: sub[1], + }, + Key: key, + }, + }, nil + } + } + + return v1alpha1.ValueSource{}, fmt.Errorf("illegal maven setting definition, syntax: configmap|secret:resource-name[/settings path]") +} diff --git a/pkg/cmd/install_test.go b/pkg/cmd/install_test.go new file mode 100644 index 0000000..27a8473 --- /dev/null +++ b/pkg/cmd/install_test.go @@ -0,0 +1,69 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You 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 ( + "testing" + + "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" + + "github.com/stretchr/testify/assert" +) + +func TestDecodeMavenSettings(t *testing.T) { + var err error + var val v1alpha1.ValueSource + + // + // ConfigMap + // + val, err = decodeMavenSettings("configmap:maven-settings/s.xml") + assert.Nil(t, err) + assert.Nil(t, val.SecretKeyRef) + assert.Equal(t, "maven-settings", val.ConfigMapKeyRef.Name) + assert.Equal(t, "s.xml", val.ConfigMapKeyRef.Key) + + val, err = decodeMavenSettings("configmap:maven-settings") + assert.Nil(t, err) + assert.Nil(t, val.SecretKeyRef) + assert.Equal(t, "maven-settings", val.ConfigMapKeyRef.Name) + assert.Empty(t, val.ConfigMapKeyRef.Key) + + // + // Secrets + // + val, err = decodeMavenSettings("secret:maven-settings-secret/s.xml") + assert.Nil(t, err) + assert.Nil(t, val.ConfigMapKeyRef) + assert.Equal(t, "maven-settings-secret", val.SecretKeyRef.Name) + assert.Equal(t, "s.xml", val.SecretKeyRef.Key) + + val, err = decodeMavenSettings("secret:maven-settings-secret") + assert.Nil(t, err) + assert.Nil(t, val.ConfigMapKeyRef) + assert.Equal(t, "maven-settings-secret", val.SecretKeyRef.Name) + assert.Empty(t, val.SecretKeyRef.Key) + + // + // Errors + // + _, err = decodeMavenSettings("something:maven-settings-secret/s.xml") + assert.NotNil(t, err) + _, err = decodeMavenSettings("secret") + assert.NotNil(t, err) +} diff --git a/pkg/controller/integrationcontext/build.go b/pkg/controller/integrationcontext/build.go index 37051bd..65d3b36 100644 --- a/pkg/controller/integrationcontext/build.go +++ b/pkg/controller/integrationcontext/build.go @@ -32,7 +32,6 @@ import ( "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" "github.com/apache/camel-k/pkg/builder" - "github.com/apache/camel-k/pkg/platform" "github.com/apache/camel-k/pkg/trait" ) @@ -75,20 +74,12 @@ func (action *buildAction) handleBuildSubmitted(ctx context.Context, ictx *v1alp build.Status.Phase == v1alpha1.BuildPhaseError || build.Status.Phase == v1alpha1.BuildPhaseInterrupted || build.Status.Phase == v1alpha1.BuildPhaseSucceeded { - p, err := platform.GetCurrentPlatform(ctx, action.client, ictx.Namespace) - if err != nil { - return err - } + env, err := trait.Apply(ctx, action.client, nil, ictx) if err != nil { return err } - // assume there's no duplication nor conflict for now - repositories := make([]string, 0, len(ictx.Spec.Repositories)+len(p.Spec.Build.Repositories)) - repositories = append(repositories, ictx.Spec.Repositories...) - repositories = append(repositories, p.Spec.Build.Repositories...) - if env.CamelCatalog == nil { return errors.New("undefined camel catalog") } @@ -108,7 +99,6 @@ func (action *buildAction) handleBuildSubmitted(ctx context.Context, ictx *v1alp RuntimeVersion: env.RuntimeVersion, Platform: env.Platform.Spec, Dependencies: ictx.Spec.Dependencies, - Repositories: repositories, Steps: builder.StepIDsFor(env.Steps...), BuildDir: env.BuildDir, }, diff --git a/pkg/controller/integrationplatform/initialize.go b/pkg/controller/integrationplatform/initialize.go index 4c93551..f8c2f9b 100644 --- a/pkg/controller/integrationplatform/initialize.go +++ b/pkg/controller/integrationplatform/initialize.go @@ -133,14 +133,6 @@ func (action *initializeAction) Handle(ctx context.Context, ip *v1alpha1.Integra action.L.Infof("LocalRepository set to %s", target.Spec.Build.LocalRepository) action.L.Infof("Timeout set to %s", target.Spec.Build.Timeout) - for i, r := range target.Spec.Build.Repositories { - if i == 0 { - action.L.Info("Repositories:") - } - - action.L.Infof("%d - %s", i, r) - } - err = action.client.Update(ctx, target) if err != nil { return err diff --git a/pkg/trait/builder_test.go b/pkg/trait/builder_test.go index 9f62dca..52bf4ab 100644 --- a/pkg/trait/builder_test.go +++ b/pkg/trait/builder_test.go @@ -87,7 +87,7 @@ func TestS2IBuilderTrait(t *testing.T) { assert.NotEmpty(t, env.ExecutedTraits) assert.NotNil(t, env.GetTrait(ID("builder"))) assert.NotEmpty(t, env.Steps) - assert.Len(t, env.Steps, 6) + assert.Len(t, env.Steps, 7) assert.Condition(t, func() bool { for _, s := range env.Steps { if s == s2i.Steps.Publisher && s.Phase() == builder.ApplicationPublishPhase { @@ -107,7 +107,7 @@ func TestKanikoBuilderTrait(t *testing.T) { assert.NotEmpty(t, env.ExecutedTraits) assert.NotNil(t, env.GetTrait(ID("builder"))) assert.NotEmpty(t, env.Steps) - assert.Len(t, env.Steps, 6) + assert.Len(t, env.Steps, 7) assert.Condition(t, func() bool { for _, s := range env.Steps { if s == kaniko.Steps.Publisher && s.Phase() == builder.ApplicationPublishPhase { diff --git a/pkg/trait/rest-dsl.go b/pkg/trait/rest-dsl.go index 41a32bb..71cd6b7 100644 --- a/pkg/trait/rest-dsl.go +++ b/pkg/trait/rest-dsl.go @@ -18,7 +18,6 @@ limitations under the License. package trait import ( - "encoding/xml" "errors" "fmt" "io/ioutil" @@ -28,6 +27,8 @@ import ( "strconv" "strings" + "github.com/apache/camel-k/pkg/util/kubernetes" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -106,22 +107,25 @@ func (t *restDslTrait) Apply(e *Environment) error { return err } - opts := make([]string, 0, 4) - opts = append(opts, maven.ExtraOptions(e.Platform.Spec.Build.LocalRepository)...) - opts = append(opts, "-Dopenapi.spec="+in) - opts = append(opts, "-Ddsl.out="+out) - - project, err := t.generateProject(e) + project, err := t.generateMavenProject(e) if err != nil { return err } - err = maven.CreateStructure(tmpDir, project) + mc := maven.NewContext(tmpDir, project) + mc.AddArguments(maven.ExtraOptions(e.Platform.Spec.Build.LocalRepository)...) + mc.AddArgument("-Dopenapi.spec=" + in) + mc.AddArgument("-Ddsl.out=" + out) + + settings, err := kubernetes.ResolveValueSource(e.C, e.Client, e.Integration.Namespace, &e.Platform.Spec.Build.Maven.Settings) if err != nil { return err } + if settings != "" { + mc.SettingsData = []byte(settings) + } - err = maven.Run(tmpDir, opts...) + err = maven.Run(mc) if err != nil { return err } @@ -202,61 +206,35 @@ func (t *restDslTrait) Apply(e *Environment) error { return nil } -func (t *restDslTrait) generateProject(e *Environment) (maven.Project, error) { +func (t *restDslTrait) generateMavenProject(e *Environment) (maven.Project, error) { if e.CamelCatalog == nil { return maven.Project{}, errors.New("unknown camel catalog") } - p := maven.Project{ - XMLName: xml.Name{Local: "project"}, - XMLNs: "http://maven.apache.org/POM/4.0.0", - XMLNsXsi: "http://www.w3.org/2001/XMLSchema-instance", - XsiSchemaLocation: "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd", - ModelVersion: "4.0.0", - GroupID: "org.apache.camel.k.integration", - ArtifactID: "camel-k-red-dsl-generator", - Version: defaults.Version, - Build: maven.Build{ - DefaultGoal: "generate-resources", - Plugins: []maven.Plugin{ + p := maven.NewProjectWithGAV("org.apache.camel.k.integration", "camel-k-rest-dsl-generator", defaults.Version) + p.Build.DefaultGoal = "generate-resources" + p.Build.Plugins = []maven.Plugin{ + { + GroupID: "org.apache.camel.k", + ArtifactID: "camel-k-maven-plugin", + Version: e.RuntimeVersion, + Executions: []maven.Execution{ { - GroupID: "org.apache.camel.k", - ArtifactID: "camel-k-maven-plugin", - Version: e.RuntimeVersion, - Executions: []maven.Execution{ - { - Phase: "generate-resources", - Goals: []string{ - "generate-rest-xml", - }, - }, - }, - Dependencies: []maven.Dependency{ - { - GroupID: "org.apache.camel", - ArtifactID: "camel-swagger-rest-dsl-generator", - Version: e.CamelCatalog.Version, - }, + Phase: "generate-resources", + Goals: []string{ + "generate-rest-xml", }, }, }, + Dependencies: []maven.Dependency{ + { + GroupID: "org.apache.camel", + ArtifactID: "camel-swagger-rest-dsl-generator", + Version: e.CamelCatalog.Version, + }, + }, }, } - // - // Repositories - // - - p.Repositories = make([]maven.Repository, 0, len(e.Platform.Spec.Build.Repositories)) - - for i, r := range e.Platform.Spec.Build.Repositories { - repo := maven.NewRepository(r) - if repo.ID == "" { - repo.ID = fmt.Sprintf("repo-%03d", i) - } - - p.Repositories = append(p.Repositories, repo) - } - return p, nil } diff --git a/pkg/util/kubernetes/util.go b/pkg/util/kubernetes/util.go index 2ecb761..45b8a59 100644 --- a/pkg/util/kubernetes/util.go +++ b/pkg/util/kubernetes/util.go @@ -237,3 +237,47 @@ func LookUpResources(ctx context.Context, client client.Client, namespace string } return res, nil } + +// GetSecretRefValue returns the value of a secret in the supplied namespace -- +func GetSecretRefValue(ctx context.Context, client client.Client, namespace string, selector *corev1.SecretKeySelector) (string, error) { + secret, err := GetSecret(ctx, client, selector.Name, namespace) + if err != nil { + return "", err + } + + if data, ok := secret.Data[selector.Key]; ok { + return string(data), nil + } + + return "", fmt.Errorf("key %s not found in secret %s", selector.Key, selector.Name) + +} + +// GetConfigMapRefValue returns the value of a configmap in the supplied namespace +func GetConfigMapRefValue(ctx context.Context, client client.Client, namespace string, selector *corev1.ConfigMapKeySelector) (string, error) { + cm, err := GetConfigMap(ctx, client, selector.Name, namespace) + if err != nil { + return "", err + } + + if data, ok := cm.Data[selector.Key]; ok { + return data, nil + } + + return "", fmt.Errorf("key %s not found in config map %s", selector.Key, selector.Name) +} + +// ResolveValueSource -- +func ResolveValueSource(ctx context.Context, client client.Client, namespace string, valueSource *v1alpha1.ValueSource) (string, error) { + if valueSource.ConfigMapKeyRef != nil && valueSource.SecretKeyRef != nil { + return "", fmt.Errorf("value source has bot config map and secret configuired") + } + if valueSource.ConfigMapKeyRef != nil { + return GetConfigMapRefValue(ctx, client, namespace, valueSource.ConfigMapKeyRef) + } + if valueSource.SecretKeyRef != nil { + return GetSecretRefValue(ctx, client, namespace, valueSource.SecretKeyRef) + } + + return "", nil +} diff --git a/pkg/util/maven/maven.go b/pkg/util/maven/maven.go index 485d074..3e28d18 100644 --- a/pkg/util/maven/maven.go +++ b/pkg/util/maven/maven.go @@ -18,11 +18,12 @@ limitations under the License. package maven import ( - "bytes" - "encoding/xml" "fmt" + "io" + "io/ioutil" "os" "os/exec" + "path" "regexp" "strings" @@ -35,50 +36,75 @@ import ( // Log -- var Log = log.WithName("maven") -// GeneratePomContent generate a pom.xml file from the given project definition -func GeneratePomContent(project Project) (string, error) { - w := &bytes.Buffer{} - w.WriteString(xml.Header) - - e := xml.NewEncoder(w) - e.Indent("", " ") - - err := e.Encode(project) - if err != nil { - return "", err +// GenerateProjectStructure -- +func GenerateProjectStructure(context Context) error { + if err := util.WriteFileWithBytesMarshallerContent(context.Path, "pom.xml", context.Project); err != nil { + return err } - return w.String(), nil -} - -// CreateStructure -- -func CreateStructure(buildDir string, project Project) error { - Log.Infof("write project: %+v", project) - - pom, err := GeneratePomContent(project) - if err != nil { - return err + if context.SettingsData != nil { + if err := util.WriteFileWithContent(context.Path, "settings.xml", context.SettingsData); err != nil { + return err + } + } else if context.Settings != nil { + if err := util.WriteFileWithBytesMarshallerContent(context.Path, "settings.xml", context.Settings); err != nil { + return err + } } - err = util.WriteFileWithContent(buildDir, "pom.xml", pom) - if err != nil { - return err + for k, v := range context.AdditionalEntries { + var bytes []byte + var err error + + if dc, ok := v.([]byte); ok { + bytes = dc + } else if dc, ok := v.(io.Reader); ok { + bytes, err = ioutil.ReadAll(dc) + if err != nil { + return err + } + } else { + return fmt.Errorf("unknown content type: name=%s, content=%+v", k, v) + } + + if len(bytes) > 0 { + Log.Infof("write entry: %s (%d bytes)", k, len(bytes)) + + err = util.WriteFileWithContent(context.Path, k, bytes) + if err != nil { + return err + } + } } return nil } // Run -- -func Run(buildDir string, args ...string) error { +func Run(context Context) error { + if err := GenerateProjectStructure(context); err != nil { + return err + } + mvnCmd := "mvn" if c, ok := os.LookupEnv("MAVEN_CMD"); ok { mvnCmd = c } - args = append(args, "--batch-mode") + args := append(context.AdditionalArguments, "--batch-mode") + + settingsPath := path.Join(context.Path, "settings.xml") + settingsExists, err := util.FileExists(settingsPath) + if err != nil { + return err + } + + if settingsExists { + args = append(args, "--settings", settingsPath) + } cmd := exec.Command(mvnCmd, args...) - cmd.Dir = buildDir + cmd.Dir = context.Path cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/pkg/util/maven/maven_project.go b/pkg/util/maven/maven_project.go index 7c536cb..541414f 100644 --- a/pkg/util/maven/maven_project.go +++ b/pkg/util/maven/maven_project.go @@ -18,9 +18,48 @@ limitations under the License. package maven import ( + "bytes" + "encoding/xml" "strings" ) +// NewProject -- +func NewProject() Project { + return Project{ + XMLName: xml.Name{Local: "project"}, + XMLNs: "http://maven.apache.org/POM/4.0.0", + XMLNsXsi: "http://www.w3.org/2001/XMLSchema-instance", + XsiSchemaLocation: "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd", + ModelVersion: "4.0.0", + } +} + +// NewProjectWithGAV -- +func NewProjectWithGAV(group string, artifact string, version string) Project { + p := NewProject() + p.GroupID = group + p.ArtifactID = artifact + p.Version = version + + return p +} + +// MarshalBytes -- +func (p Project) MarshalBytes() ([]byte, error) { + w := &bytes.Buffer{} + w.WriteString(xml.Header) + + e := xml.NewEncoder(w) + e.Indent("", " ") + + err := e.Encode(p) + if err != nil { + return []byte{}, err + } + + return w.Bytes(), nil +} + // LookupDependency -- func (p *Project) LookupDependency(dep Dependency) *Dependency { for i := range p.Dependencies { diff --git a/pkg/util/maven/maven_test.go b/pkg/util/maven/maven_project_test.go similarity index 78% rename from pkg/util/maven/maven_test.go rename to pkg/util/maven/maven_project_test.go index 3115f9e..cbb7daa 100644 --- a/pkg/util/maven/maven_test.go +++ b/pkg/util/maven/maven_project_test.go @@ -18,9 +18,10 @@ limitations under the License. package maven import ( - "encoding/xml" "testing" + "github.com/apache/camel-k/pkg/util" + "github.com/stretchr/testify/assert" ) @@ -81,67 +82,58 @@ const expectedPom = `<?xml version="1.0" encoding="UTF-8"?> </project>` func TestPomGeneration(t *testing.T) { - project := Project{ - XMLName: xml.Name{Local: "project"}, - XMLNs: "http://maven.apache.org/POM/4.0.0", - XMLNsXsi: "http://www.w3.org/2001/XMLSchema-instance", - XsiSchemaLocation: "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd", - ModelVersion: "4.0.0", - GroupID: "org.apache.camel.k.integration", - ArtifactID: "camel-k-integration", - Version: "1.0.0", - DependencyManagement: DependencyManagement{ - Dependencies: []Dependency{ - { - GroupID: "org.apache.camel", - ArtifactID: "camel-bom", - Version: "2.22.1", - Type: "pom", - Scope: "import", - }, - }, - }, + project := NewProjectWithGAV("org.apache.camel.k.integration", "camel-k-integration", "1.0.0") + project.DependencyManagement = DependencyManagement{ Dependencies: []Dependency{ { - GroupID: "org.apache.camel.k", - ArtifactID: "camel-k-runtime-jvm", - Version: "1.0.0", + GroupID: "org.apache.camel", + ArtifactID: "camel-bom", + Version: "2.22.1", + Type: "pom", + Scope: "import", }, }, - Repositories: []Repository{ - { - ID: "central", - URL: "https://repo.maven.apache.org/maven2", - Snapshots: RepositoryPolicy{ - Enabled: false, - }, - Releases: RepositoryPolicy{ - Enabled: true, - UpdatePolicy: "never", - }, + } + project.Dependencies = []Dependency{ + { + GroupID: "org.apache.camel.k", + ArtifactID: "camel-k-runtime-jvm", + Version: "1.0.0", + }, + } + project.Repositories = []Repository{ + { + ID: "central", + URL: "https://repo.maven.apache.org/maven2", + Snapshots: RepositoryPolicy{ + Enabled: false, + }, + Releases: RepositoryPolicy{ + Enabled: true, + UpdatePolicy: "never", }, }, - PluginRepositories: []Repository{ - { - ID: "central", - URL: "https://repo.maven.apache.org/maven2", - Snapshots: RepositoryPolicy{ - Enabled: false, - }, - Releases: RepositoryPolicy{ - Enabled: true, - UpdatePolicy: "never", - }, + } + project.PluginRepositories = []Repository{ + { + ID: "central", + URL: "https://repo.maven.apache.org/maven2", + Snapshots: RepositoryPolicy{ + Enabled: false, + }, + Releases: RepositoryPolicy{ + Enabled: true, + UpdatePolicy: "never", }, }, } - pom, err := GeneratePomContent(project) + pom, err := util.EncodeXML(project) assert.Nil(t, err) assert.NotNil(t, pom) - assert.Equal(t, expectedPom, pom) + assert.Equal(t, expectedPom, string(pom)) } func TestParseSimpleGAV(t *testing.T) { diff --git a/pkg/builder/kaniko/kaniko.go b/pkg/util/maven/maven_settings.go similarity index 55% copy from pkg/builder/kaniko/kaniko.go copy to pkg/util/maven/maven_settings.go index 858799e..16f96b7 100644 --- a/pkg/builder/kaniko/kaniko.go +++ b/pkg/util/maven/maven_settings.go @@ -15,36 +15,16 @@ See the License for the specific language governing permissions and limitations under the License. */ -package kaniko - -import ( - "github.com/apache/camel-k/pkg/builder" -) - -func init() { - builder.RegisterSteps(Steps) +package maven + +import "encoding/xml" + +// NewSettings -- +func NewSettings() Settings { + return Settings{ + XMLName: xml.Name{Local: "settings"}, + XMLNs: "http://maven.apache.org/SETTINGS/1.0.0", + XMLNsXsi: "http://www.w3.org/2001/XMLSchema-instance", + XsiSchemaLocation: "http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd", + } } - -type steps struct { - Publisher builder.Step -} - -var Steps = steps{ - Publisher: builder.NewStep( - builder.ApplicationPublishPhase, - publisher, - ), -} - -// DefaultSteps -- -var DefaultSteps = []builder.Step{ - builder.Steps.GenerateProject, - builder.Steps.InjectDependencies, - builder.Steps.SanitizeDependencies, - builder.Steps.ComputeDependencies, - builder.Steps.IncrementalPackager, - Steps.Publisher, -} - -// BuildDir is the directory where to build artifacts (shared with the Kaniko pod) -var BuildDir = "/workspace" diff --git a/pkg/util/maven/maven_settings_test.go b/pkg/util/maven/maven_settings_test.go new file mode 100644 index 0000000..8bd25a3 --- /dev/null +++ b/pkg/util/maven/maven_settings_test.go @@ -0,0 +1,86 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You 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 maven + +import ( + "testing" + + "github.com/apache/camel-k/pkg/util" + "github.com/stretchr/testify/assert" +) + +const expectedSettings = `<?xml version="1.0" encoding="UTF-8"?> +<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ` + + `xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd"> + <localRepository>/tmp/artifacts/m2</localRepository> + <profiles> + <profile> + <id>my-profile</id> + <activation> + <activeByDefault>true</activeByDefault> + </activation> + <repositories> + <repository> + <id>central</id> + <url>https://repo.maven.apache.org/maven2</url> + <snapshots> + <enabled>false</enabled> + </snapshots> + <releases> + <enabled>true</enabled> + <updatePolicy>never</updatePolicy> + </releases> + </repository> + </repositories> + <pluginRepositories></pluginRepositories> + </profile> + </profiles> +</settings>` + +func TestSettingsGeneration(t *testing.T) { + settings := NewSettings() + settings.LocalRepository = "/tmp/artifacts/m2" + settings.Profiles = []Profile{ + { + ID: "my-profile", + Activation: Activation{ + ActiveByDefault: true, + }, + Repositories: []Repository{ + { + ID: "central", + URL: "https://repo.maven.apache.org/maven2", + Snapshots: RepositoryPolicy{ + Enabled: false, + }, + Releases: RepositoryPolicy{ + Enabled: true, + UpdatePolicy: "never", + }, + }, + }, + }, + } + + content, err := util.EncodeXML(settings) + + assert.Nil(t, err) + assert.NotNil(t, settings) + + assert.Equal(t, expectedSettings, string(content)) +} diff --git a/pkg/util/maven/maven_project_types.go b/pkg/util/maven/maven_types.go similarity index 63% rename from pkg/util/maven/maven_project_types.go rename to pkg/util/maven/maven_types.go index e95b484..24ff0a3 100644 --- a/pkg/util/maven/maven_project_types.go +++ b/pkg/util/maven/maven_types.go @@ -18,49 +18,11 @@ limitations under the License. package maven import ( + "bytes" "encoding/xml" + "fmt" ) -// Project represent a maven project -type Project struct { - XMLName xml.Name - XMLNs string `xml:"xmlns,attr"` - XMLNsXsi string `xml:"xmlns:xsi,attr"` - XsiSchemaLocation string `xml:"xsi:schemaLocation,attr"` - ModelVersion string `xml:"modelVersion"` - GroupID string `xml:"groupId"` - ArtifactID string `xml:"artifactId"` - Version string `xml:"version"` - Properties Properties `xml:"properties,omitempty"` - DependencyManagement DependencyManagement `xml:"dependencyManagement"` - Dependencies []Dependency `xml:"dependencies>dependency,omitempty"` - Repositories []Repository `xml:"repositories>repository,omitempty"` - PluginRepositories []Repository `xml:"pluginRepositories>pluginRepository,omitempty"` - Build Build `xml:"build,omitempty"` -} - -// Exclusion represent a maven's dependency exlucsion -type Exclusion struct { - GroupID string `xml:"groupId" yaml:"groupId"` - ArtifactID string `xml:"artifactId" yaml:"artifactId"` -} - -// DependencyManagement represent maven's dependency management block -type DependencyManagement struct { - Dependencies []Dependency `xml:"dependencies>dependency,omitempty"` -} - -// Dependency represent a maven's dependency -type Dependency struct { - GroupID string `xml:"groupId" yaml:"groupId"` - ArtifactID string `xml:"artifactId" yaml:"artifactId"` - Version string `xml:"version,omitempty" yaml:"version,omitempty"` - Type string `xml:"type,omitempty" yaml:"type,omitempty"` - Classifier string `xml:"classifier,omitempty" yaml:"classifier,omitempty"` - Scope string `xml:"scope,omitempty" yaml:"scope,omitempty"` - Exclusions *[]Exclusion `xml:"exclusions>exclusion,omitempty" yaml:"exclusions,omitempty"` -} - // Repository -- type Repository struct { ID string `xml:"id"` @@ -125,3 +87,134 @@ func (m Properties) MarshalXML(e *xml.Encoder, start xml.StartElement) error { return e.EncodeToken(start.End()) } + +// NewContext -- +func NewContext(buildDir string, project Project) Context { + return Context{ + Path: buildDir, + Project: project, + AdditionalArguments: make([]string, 0), + AdditionalEntries: make(map[string]interface{}), + } +} + +// Context -- +type Context struct { + Path string + Project Project + Settings *Settings + SettingsData []byte + AdditionalArguments []string + AdditionalEntries map[string]interface{} +} + +// AddEntry -- +func (c *Context) AddEntry(id string, entry interface{}) { + if c.AdditionalEntries == nil { + c.AdditionalEntries = make(map[string]interface{}) + } + + c.AdditionalEntries[id] = entry +} + +// AddArgument -- +func (c *Context) AddArgument(argument string) { + c.AdditionalArguments = append(c.AdditionalArguments, argument) +} + +// AddArgumentf -- +func (c *Context) AddArgumentf(format string, args ...interface{}) { + c.AdditionalArguments = append(c.AdditionalArguments, fmt.Sprintf(format, args...)) +} + +// AddArguments -- +func (c *Context) AddArguments(arguments ...string) { + c.AdditionalArguments = append(c.AdditionalArguments, arguments...) +} + +// Settings represent a maven settings +type Settings struct { + XMLName xml.Name + XMLNs string `xml:"xmlns,attr"` + XMLNsXsi string `xml:"xmlns:xsi,attr"` + XsiSchemaLocation string `xml:"xsi:schemaLocation,attr"` + LocalRepository string `xml:"localRepository"` + Profiles []Profile `xml:"profiles>profile,omitempty"` +} + +// MarshalBytes -- +func (s Settings) MarshalBytes() ([]byte, error) { + w := &bytes.Buffer{} + w.WriteString(xml.Header) + + e := xml.NewEncoder(w) + e.Indent("", " ") + + err := e.Encode(s) + if err != nil { + return []byte{}, err + } + + return w.Bytes(), nil +} + +// Project represent a maven project +type Project struct { + XMLName xml.Name + XMLNs string `xml:"xmlns,attr"` + XMLNsXsi string `xml:"xmlns:xsi,attr"` + XsiSchemaLocation string `xml:"xsi:schemaLocation,attr"` + ModelVersion string `xml:"modelVersion"` + GroupID string `xml:"groupId"` + ArtifactID string `xml:"artifactId"` + Version string `xml:"version"` + Properties Properties `xml:"properties,omitempty"` + DependencyManagement DependencyManagement `xml:"dependencyManagement"` + Dependencies []Dependency `xml:"dependencies>dependency,omitempty"` + Repositories []Repository `xml:"repositories>repository,omitempty"` + PluginRepositories []Repository `xml:"pluginRepositories>pluginRepository,omitempty"` + Build Build `xml:"build,omitempty"` +} + +// Exclusion represent a maven's dependency exlucsion +type Exclusion struct { + GroupID string `xml:"groupId" yaml:"groupId"` + ArtifactID string `xml:"artifactId" yaml:"artifactId"` +} + +// DependencyManagement represent maven's dependency management block +type DependencyManagement struct { + Dependencies []Dependency `xml:"dependencies>dependency,omitempty"` +} + +// Dependency represent a maven's dependency +type Dependency struct { + GroupID string `xml:"groupId" yaml:"groupId"` + ArtifactID string `xml:"artifactId" yaml:"artifactId"` + Version string `xml:"version,omitempty" yaml:"version,omitempty"` + Type string `xml:"type,omitempty" yaml:"type,omitempty"` + Classifier string `xml:"classifier,omitempty" yaml:"classifier,omitempty"` + Scope string `xml:"scope,omitempty" yaml:"scope,omitempty"` + Exclusions *[]Exclusion `xml:"exclusions>exclusion,omitempty" yaml:"exclusions,omitempty"` +} + +// Profile -- +type Profile struct { + ID string `xml:"id"` + Activation Activation `xml:"activation,omitempty"` + Properties Properties `xml:"properties,omitempty"` + Repositories []Repository `xml:"repositories>repository,omitempty"` + PluginRepositories []Repository `xml:"pluginRepositories>pluginRepository,omitempty"` +} + +// Activation -- +type Activation struct { + ActiveByDefault bool `xml:"activeByDefault"` + Property *PropertyActivation `xml:"property,omitempty"` +} + +// PropertyActivation -- +type PropertyActivation struct { + Name string `xml:"name"` + Value string `xml:"value"` +} diff --git a/pkg/util/util.go b/pkg/util/util.go index 4ab515f..542e7cf 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -18,14 +18,14 @@ limitations under the License. package util import ( + "bytes" + "encoding/xml" "os" "os/signal" "path" "regexp" "syscall" - "github.com/magiconair/properties" - "github.com/scylladb/go-set/strset" corev1 "k8s.io/api/core/v1" @@ -104,8 +104,24 @@ func WaitForSignal(sig chan os.Signal, exit func(int)) { }() } +// EncodeXML -- +func EncodeXML(content interface{}) ([]byte, error) { + w := &bytes.Buffer{} + w.WriteString(xml.Header) + + e := xml.NewEncoder(w) + e.Indent("", " ") + + err := e.Encode(content) + if err != nil { + return []byte{}, err + } + + return w.Bytes(), nil +} + // WriteFileWithContent -- -func WriteFileWithContent(buildDir string, relativePath string, content string) error { +func WriteFileWithContent(buildDir string, relativePath string, content []byte) error { filePath := path.Join(buildDir, relativePath) fileDir := path.Dir(filePath) // Create dir if not present @@ -120,13 +136,23 @@ func WriteFileWithContent(buildDir string, relativePath string, content string) } defer file.Close() - _, err = file.WriteString(content) + _, err = file.Write(content) if err != nil { return errors.Wrap(err, "could not write to file "+relativePath) } return nil } +// WriteFileWithBytesMarshallerContent -- +func WriteFileWithBytesMarshallerContent(buildDir string, relativePath string, content BytesMarshaller) error { + data, err := content.MarshalBytes() + if err != nil { + return err + } + + return WriteFileWithContent(buildDir, relativePath, data) +} + // LookupEnvVar -- func LookupEnvVar(vars []corev1.EnvVar, name string) *corev1.EnvVar { for _, e := range vars { @@ -156,40 +182,17 @@ func FindAllDistinctStringSubmatch(data string, regexps ...*regexp.Regexp) []str return submatchs.List() } -// ExtractApplicationPropertiesString -- -func ExtractApplicationPropertiesString(data map[string]string, consumer func(string, string)) error { - pstr, ok := data["application.properties"] - if !ok { - return nil - } - - p, err := properties.LoadString(pstr) - if err != nil { - return err - } - - for _, k := range p.Keys() { - consumer(k, p.MustGet(k)) +// FileExists -- +func FileExists(name string) (bool, error) { + info, err := os.Stat(name) + if os.IsNotExist(err) { + return false, nil } - return nil + return !info.IsDir(), err } -// ExtractApplicationPropertiesBytes -- -func ExtractApplicationPropertiesBytes(data map[string][]byte, consumer func(string, string)) error { - pstr, ok := data["application.properties"] - if !ok { - return nil - } - - p, err := properties.Load(pstr, properties.UTF8) - if err != nil { - return err - } - - for _, k := range p.Keys() { - consumer(k, p.MustGet(k)) - } - - return nil +// MarshalBytes -- +type BytesMarshaller interface { + MarshalBytes() ([]byte, error) }