From 7527f348b318a204cecbd6aab92f5e4cad532d4b Mon Sep 17 00:00:00 2001 From: lburgazzoli Date: Mon, 3 Jun 2019 18:51:49 +0200 Subject: [PATCH] Add shortcut for repositories #717 --- pkg/builder/builder_steps.go | 65 ++++--- pkg/builder/builder_steps_test.go | 62 +++---- pkg/builder/builder_types.go | 8 +- pkg/builder/builder_utils.go | 19 +- pkg/builder/builder_utils_test.go | 8 +- pkg/cmd/install.go | 65 +++++++ pkg/trait/rest-dsl.go | 38 ++-- pkg/util/maven/maven.go | 60 +++++-- pkg/util/maven/maven_project.go | 33 +++- pkg/util/maven/maven_project_test.go | 4 +- pkg/util/maven/maven_settings.go | 12 +- pkg/util/maven/maven_settings_test.go | 85 +++++++++ pkg/util/maven/maven_settings_types.go | 23 --- ...{maven_project_types.go => maven_types.go} | 164 +++++++++++++----- pkg/util/util.go | 21 ++- 15 files changed, 456 insertions(+), 211 deletions(-) create mode 100644 pkg/util/maven/maven_settings_test.go delete mode 100644 pkg/util/maven/maven_settings_types.go rename pkg/util/maven/{maven_project_types.go => maven_types.go} (67%) diff --git a/pkg/builder/builder_steps.go b/pkg/builder/builder_steps.go index 46c9a3dcac..0b50b156e5 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" @@ -119,11 +121,11 @@ func generateProject(ctx *Context) error { 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 { @@ -134,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:") @@ -142,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: @@ -160,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", @@ -172,12 +174,13 @@ func generateProject(ctx *Context) error { // generateProjectSettings -- func generateProjectSettings(ctx *Context) error { - settings, err := NewMavenSettings(ctx) + val, err := kubernetes.ResolveValueSource(ctx.C, ctx.Client, ctx.Namespace, &ctx.Build.Platform.Build.Maven.Settings) if err != nil { return err } - - ctx.Settings = settings + if val != "" { + ctx.Maven.SettingsData = []byte(val) + } return nil } @@ -186,8 +189,8 @@ 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 { @@ -197,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{ @@ -205,7 +208,7 @@ func injectDependencies(ctx *Context) error { ArtifactID: e.ArtifactID, } - ctx.Project.AddDependencyExclusion(md, me) + ctx.Maven.Project.AddDependencyExclusion(md, me) } } } @@ -213,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 { @@ -229,7 +232,7 @@ func injectDependencies(ctx *Context) error { ArtifactID: e.ArtifactID, } - ctx.Project.AddDependencyExclusion(md, me) + ctx.Maven.Project.AddDependencyExclusion(md, me) } } } @@ -238,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 } } @@ -260,23 +263,17 @@ func sanitizeDependencies(ctx *Context) error { } func computeDependencies(ctx *Context) error { - p := path.Join(ctx.Path, "maven") + 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) - err := maven.CreateStructure(p, ctx.Project, ctx.Settings) - if err != nil { - return err - } - - 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 8608953be2..b576f8df98 100644 --- a/pkg/builder/builder_steps_test.go +++ b/pkg/builder/builder_steps_test.go @@ -75,29 +75,29 @@ func TestGenerateJvmProject(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, 4, len(ctx.Project.Dependencies)) - assert.Contains(t, ctx.Project.Dependencies, maven.Dependency{ + 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, 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.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.logging.log4j", ArtifactID: "log4j-slf4j-impl", Version: "2.11.2", @@ -152,7 +152,7 @@ func TestMavenSettingsFromConfigMap(t *testing.T) { err = generateProjectSettings(&ctx) assert.Nil(t, err) - assert.Equal(t, []byte("setting-data"), ctx.Settings.Content) + assert.Equal(t, []byte("setting-data"), ctx.Maven.SettingsData) } func TestMavenSettingsFromSecret(t *testing.T) { @@ -202,7 +202,7 @@ func TestMavenSettingsFromSecret(t *testing.T) { err = generateProjectSettings(&ctx) assert.Nil(t, err) - assert.Equal(t, []byte("setting-data"), ctx.Settings.Content) + assert.Equal(t, []byte("setting-data"), ctx.Maven.SettingsData) } func TestGenerateGroovyProject(t *testing.T) { @@ -229,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", @@ -299,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 c948f5abba..549e9aaacb 100644 --- a/pkg/builder/builder_types.go +++ b/pkg/builder/builder_types.go @@ -107,14 +107,18 @@ type Context struct { PublicImage string Error error Namespace string - Project maven.Project - Settings maven.Settings 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 7a64160541..571beceb62 100644 --- a/pkg/builder/builder_utils.go +++ b/pkg/builder/builder_utils.go @@ -20,8 +20,6 @@ package builder import ( "strings" - "github.com/apache/camel-k/pkg/util/kubernetes" - "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" "github.com/apache/camel-k/pkg/util/camel" "github.com/apache/camel-k/pkg/util/defaults" @@ -61,7 +59,7 @@ func NewMavenProject(ctx *Context) (maven.Project, error) { ctx.Catalog = c } - p := maven.NewProject("org.apache.camel.k.integration", "camel-k-integration", defaults.Version) + 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) @@ -99,18 +97,3 @@ func NewMavenProject(ctx *Context) (maven.Project, error) { return p, nil } - -// NewMavenSettings -- -func NewMavenSettings(ctx *Context) (maven.Settings, error) { - settings := maven.NewSettings() - - val, err := kubernetes.ResolveValueSource(ctx.C, ctx.Client, ctx.Namespace, &ctx.Build.Platform.Build.Maven.Settings) - if err != nil { - return maven.Settings{}, err - } - if val != "" { - settings.Content = []byte(val) - } - - return settings, nil -} diff --git a/pkg/builder/builder_utils_test.go b/pkg/builder/builder_utils_test.go index 1491d515c9..5bd0075136 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/cmd/install.go b/pkg/cmd/install.go index 691557e830..2970d5b804 100644 --- a/pkg/cmd/install.go +++ b/pkg/cmd/install.go @@ -23,6 +23,10 @@ import ( "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" "github.com/apache/camel-k/pkg/platform" @@ -40,6 +44,7 @@ import ( 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 { @@ -64,6 +69,7 @@ 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().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") @@ -101,6 +107,7 @@ type installCmdOptions struct { localRepository string buildStrategy string buildTimeout string + repositories []string mavenSettings string properties []string contexts []string @@ -193,6 +200,59 @@ func (o *installCmdOptions) install(_ *cobra.Command, _ []string) error { platform.Spec.Build.Timeout.Duration = d } + if len(o.repositories) > 0 { + o.mavenSettings = fmt.Sprintf("configmap:%s-maven-settings/settings.xml", platform.Name) + + settings := maven.NewSettings() + repositories := make([]maven.Repository, 0, len(o.repositories)) + + for i, r := range o.repositories { + 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 { @@ -294,6 +354,11 @@ func (o *installCmdOptions) validate(_ *cobra.Command, _ []string) error { err := errorIfContextIsNotAvailable(schema, context, len(o.contexts)) result = multierr.Append(result, err) } + + if len(o.repositories) > 0 && o.mavenSettings != "" { + result = fmt.Errorf("incompatible options combinations: you canno set both repositories and mavenSettings") + } + return result } diff --git a/pkg/trait/rest-dsl.go b/pkg/trait/rest-dsl.go index 186f2b4eb3..71cd6b72f2 100644 --- a/pkg/trait/rest-dsl.go +++ b/pkg/trait/rest-dsl.go @@ -107,26 +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.generateMavenProject(e) if err != nil { return err } - settings, err := t.generateMavenSettings(e) - if err != nil { - return err - } - err = maven.CreateStructure(tmpDir, project, settings) + 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 } @@ -212,7 +211,7 @@ func (t *restDslTrait) generateMavenProject(e *Environment) (maven.Project, erro return maven.Project{}, errors.New("unknown camel catalog") } - p := maven.NewProject("org.apache.camel.k.integration", "camel-k-rest-dsl-generator", defaults.Version) + 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{ { @@ -239,18 +238,3 @@ func (t *restDslTrait) generateMavenProject(e *Environment) (maven.Project, erro return p, nil } - -func (t *restDslTrait) generateMavenSettings(e *Environment) (maven.Settings, error) { - settings := maven.NewSettings() - - val, err := kubernetes.ResolveValueSource(e.C, e.Client, e.Integration.Namespace, &e.Platform.Spec.Build.Maven.Settings) - if err != nil { - return maven.Settings{}, err - } - - if val != "" { - settings.Content = []byte(val) - } - - return settings, nil -} diff --git a/pkg/util/maven/maven.go b/pkg/util/maven/maven.go index 78dc1bf0fa..3e28d1858f 100644 --- a/pkg/util/maven/maven.go +++ b/pkg/util/maven/maven.go @@ -19,6 +19,8 @@ package maven import ( "fmt" + "io" + "io/ioutil" "os" "os/exec" "path" @@ -34,24 +36,44 @@ import ( // Log -- var Log = log.WithName("maven") -// CreateStructure -- -func CreateStructure(buildDir string, project Project, settings Settings) error { - Log.Infof("write project: %+v", project) - - pomContent, err := util.EncodeXML(project) - if err != nil { +// GenerateProjectStructure -- +func GenerateProjectStructure(context Context) error { + if err := util.WriteFileWithBytesMarshallerContent(context.Path, "pom.xml", context.Project); err != nil { return err } - err = util.WriteFileWithContent(buildDir, "pom.xml", []byte(pomContent)) - 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 + } } - if len(settings.Content) > 0 { - err = util.WriteFileWithContent(buildDir, "settings.xml", settings.Content) - 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 + } } } @@ -59,15 +81,19 @@ func CreateStructure(buildDir string, project Project, settings Settings) error } // 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(buildDir, "settings.xml") + settingsPath := path.Join(context.Path, "settings.xml") settingsExists, err := util.FileExists(settingsPath) if err != nil { return err @@ -78,7 +104,7 @@ func Run(buildDir string, args ...string) error { } 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 207d3375b1..541414f005 100644 --- a/pkg/util/maven/maven_project.go +++ b/pkg/util/maven/maven_project.go @@ -18,23 +18,48 @@ limitations under the License. package maven import ( + "bytes" "encoding/xml" "strings" ) -func NewProject(group string, artifact string, version string) Project { +// 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", - GroupID: group, - ArtifactID: artifact, - Version: version, } } +// 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_project_test.go b/pkg/util/maven/maven_project_test.go index 7a4814ccd8..cbb7daaac4 100644 --- a/pkg/util/maven/maven_project_test.go +++ b/pkg/util/maven/maven_project_test.go @@ -82,7 +82,7 @@ const expectedPom = ` ` func TestPomGeneration(t *testing.T) { - project := NewProject("org.apache.camel.k.integration", "camel-k-integration", "1.0.0") + project := NewProjectWithGAV("org.apache.camel.k.integration", "camel-k-integration", "1.0.0") project.DependencyManagement = DependencyManagement{ Dependencies: []Dependency{ { @@ -133,7 +133,7 @@ func TestPomGeneration(t *testing.T) { 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/util/maven/maven_settings.go b/pkg/util/maven/maven_settings.go index eb80c82295..16f96b72cd 100644 --- a/pkg/util/maven/maven_settings.go +++ b/pkg/util/maven/maven_settings.go @@ -17,14 +17,14 @@ limitations under the License. package maven +import "encoding/xml" + // NewSettings -- func NewSettings() Settings { - return Settings{} -} - -// NewSettingsWithContent -- -func NewSettingsWithContent(content []byte) Settings { return Settings{ - Content: content, + 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", } } diff --git a/pkg/util/maven/maven_settings_test.go b/pkg/util/maven/maven_settings_test.go new file mode 100644 index 0000000000..cd3c62268d --- /dev/null +++ b/pkg/util/maven/maven_settings_test.go @@ -0,0 +1,85 @@ +/* +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 = ` + + /tmp/artifacts/m2 + + + my-profile + + true + + + + central + https://repo.maven.apache.org/maven2 + + false + + + true + never + + + + + +` + +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_settings_types.go b/pkg/util/maven/maven_settings_types.go deleted file mode 100644 index 2a4d393713..0000000000 --- a/pkg/util/maven/maven_settings_types.go +++ /dev/null @@ -1,23 +0,0 @@ -/* -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 - -// Settings -- -type Settings struct { - Content []byte -} diff --git a/pkg/util/maven/maven_project_types.go b/pkg/util/maven/maven_types.go similarity index 67% rename from pkg/util/maven/maven_project_types.go rename to pkg/util/maven/maven_types.go index e95b48437d..9244121d3a 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,125 @@ 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"` + Repositories []Repository `xml:"repositories>repository,omitempty"` +} + +// Activation -- +type Activation struct { + ActiveByDefault bool `xml:"activeByDefault"` +} diff --git a/pkg/util/util.go b/pkg/util/util.go index cd04aa0334..542e7cfa35 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -105,7 +105,7 @@ func WaitForSignal(sig chan os.Signal, exit func(int)) { } // EncodeXML -- -func EncodeXML(content interface{}) (string, error) { +func EncodeXML(content interface{}) ([]byte, error) { w := &bytes.Buffer{} w.WriteString(xml.Header) @@ -114,10 +114,10 @@ func EncodeXML(content interface{}) (string, error) { err := e.Encode(content) if err != nil { - return "", err + return []byte{}, err } - return w.String(), nil + return w.Bytes(), nil } // WriteFileWithContent -- @@ -143,6 +143,16 @@ func WriteFileWithContent(buildDir string, relativePath string, content []byte) 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 { @@ -181,3 +191,8 @@ func FileExists(name string) (bool, error) { return !info.IsDir(), err } + +// MarshalBytes -- +type BytesMarshaller interface { + MarshalBytes() ([]byte, error) +}