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 54da3a7424466a22e8c78c6961b2954d7ed0ae46 Author: nferraro <ni.ferr...@gmail.com> AuthorDate: Thu Jan 10 15:17:53 2019 +0100 Fix #312: add predefined image published and builder --- cmd/util/publisher/publisher.go | 106 ++++++++++++++++++++++++++++++++++++++++ pkg/builder/builder.go | 5 ++ pkg/builder/builder_steps.go | 44 +++++++++++++++++ pkg/builder/kaniko/kaniko.go | 1 + pkg/builder/s2i/s2i.go | 5 +- pkg/trait/builder_test.go | 4 +- 6 files changed, 162 insertions(+), 3 deletions(-) diff --git a/cmd/util/publisher/publisher.go b/cmd/util/publisher/publisher.go new file mode 100644 index 0000000..c52a76b --- /dev/null +++ b/cmd/util/publisher/publisher.go @@ -0,0 +1,106 @@ +/* +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 main + +import ( + "context" + "io/ioutil" + "os" + "os/exec" + "path" + "path/filepath" + "strings" + + "github.com/apache/camel-k/deploy" + "github.com/apache/camel-k/pkg/apis" + "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" + "github.com/apache/camel-k/pkg/builder" + "github.com/apache/camel-k/pkg/util/camel" + "github.com/apache/camel-k/pkg/util/kubernetes" + clientscheme "k8s.io/client-go/kubernetes/scheme" +) + +// Publishes predefined images for all Camel components +func main() { + scheme := clientscheme.Scheme + panicIfErr(apis.AddToScheme(scheme)) + + platRun, err := kubernetes.LoadResourceFromYaml(scheme, deploy.Resources["platform-cr.yaml"]) + panicIfErr(err) + + p := platRun.(*v1alpha1.IntegrationPlatform) + + for _, a := range camel.Runtime.Artifacts { + if a.GroupID == "org.apache.camel" { + component := strings.TrimPrefix(a.ArtifactID, "camel-") + build(component, p.Spec.Build.CamelVersion) + } + } +} + +func build(component string, camelVersion string) { + dir, err := ioutil.TempDir(os.TempDir(), "camel-k-build-") + panicIfErr(err) + defer panicIfErr(os.RemoveAll(dir)) + + ctx := builder.Context{ + C: context.TODO(), + Path: dir, + Request: builder.Request{ + Platform: v1alpha1.IntegrationPlatformSpec{ + Build: v1alpha1.IntegrationPlatformBuildSpec{ + CamelVersion: camelVersion, + }, + }, + Dependencies: []string{ + "camel-k:knative", + "camel:core", + "runtime:jvm", + "runtime:yaml", + "camel:" + component, + }, + }, + } + + panicIfErr(builder.GenerateProject(&ctx)) + panicIfErr(builder.ComputeDependencies(&ctx)) + panicIfErr(builder.StandardPackager(&ctx)) + + archiveDir, archiveName := filepath.Split(ctx.Archive) + dockerfile := ` + FROM fabric8/s2i-java:2.3 + ADD ` + archiveName + ` /deployments/ + ` + panicIfErr(ioutil.WriteFile(path.Join(archiveDir, "Dockerfile"), []byte(dockerfile), 0777)) + image := builder.PredefinedImageNameFor(component) + buildCmd := exec.Command("docker", "build", "-t", image, archiveDir) + buildCmd.Stdout = os.Stdout + buildCmd.Stderr = os.Stderr + panicIfErr(buildCmd.Run()) + + pushCmd := exec.Command("docker", "push", image) + pushCmd.Stdout = os.Stdout + pushCmd.Stderr = os.Stderr + panicIfErr(pushCmd.Run()) +} + +func panicIfErr(err error) { + if err != nil { + panic(err) + } +} diff --git a/pkg/builder/builder.go b/pkg/builder/builder.go index 9becccb..ae61eaa 100644 --- a/pkg/builder/builder.go +++ b/pkg/builder/builder.go @@ -168,6 +168,11 @@ func (b *defaultBuilder) submit(request Request) { break } + if c.Image != "" && c.PublicImage != "" { + logrus.Info("image already computed: skipping following steps") + break + } + select { case <-b.interrupt: c.Error = errors.New("build canceled") diff --git a/pkg/builder/builder_steps.go b/pkg/builder/builder_steps.go index 79d98d8..6be2a71 100644 --- a/pkg/builder/builder_steps.go +++ b/pkg/builder/builder_steps.go @@ -152,6 +152,50 @@ func ComputeDependencies(ctx *Context) error { return nil } +// LookupPredefinedImage is used to find a suitable predefined image if available +func LookupPredefinedImage(ctx *Context) error { + standardDependencies := map[string]bool { + "camel:core": true, + "runtime:jvm": true, + "runtime:yaml": true, + } + + realDependencies := make(map[string]bool) + for _, d := range ctx.Request.Dependencies { + if _, std := standardDependencies[d]; !std { + realDependencies[d] = true + } + } + + knativeDep := "camel-k:knative" + if len(realDependencies) != 2 || !realDependencies[knativeDep] { + return nil + } + + var otherDep string + for d := range realDependencies { + if d != knativeDep { + otherDep = d + break + } + } + + camelPrefix := "camel:" + if !strings.HasPrefix(otherDep, camelPrefix) { + return nil + } + + comp := strings.TrimPrefix(otherDep, camelPrefix) + ctx.Image = PredefinedImageNameFor(comp) + ctx.PublicImage = ctx.Image + return nil +} + +// PredefinedImageNameFor -- +func PredefinedImageNameFor(comp string) string { + return fmt.Sprintf("camelk/camel-base-knative-%s:%s", comp, version.Version) +} + // ArtifactsSelector -- type ArtifactsSelector func(ctx *Context) error diff --git a/pkg/builder/kaniko/kaniko.go b/pkg/builder/kaniko/kaniko.go index 4b2d826..75a4cd8 100644 --- a/pkg/builder/kaniko/kaniko.go +++ b/pkg/builder/kaniko/kaniko.go @@ -25,6 +25,7 @@ import ( var DefaultSteps = []builder.Step{ builder.NewStep("generate", builder.ProjectGenerationPhase, builder.GenerateProject), builder.NewStep("build/compute-dependencies", builder.ProjectBuildPhase, builder.ComputeDependencies), + builder.NewStep("build/lookup-predefined-dependencies", builder.ProjectBuildPhase + 1, builder.LookupPredefinedImage), builder.NewStep("packager", builder.ApplicationPackagePhase, builder.StandardPackager), builder.NewStep("publisher/kaniko", builder.ApplicationPublishPhase, Publisher), builder.NewStep("notify/context", builder.NotifyPhase, builder.NotifyIntegrationContext), diff --git a/pkg/builder/s2i/s2i.go b/pkg/builder/s2i/s2i.go index df68f3f..8000ea8 100644 --- a/pkg/builder/s2i/s2i.go +++ b/pkg/builder/s2i/s2i.go @@ -17,12 +17,15 @@ limitations under the License. package s2i -import "github.com/apache/camel-k/pkg/builder" +import ( + "github.com/apache/camel-k/pkg/builder" +) // DefaultSteps -- var DefaultSteps = []builder.Step{ builder.NewStep("generate", builder.ProjectGenerationPhase, builder.GenerateProject), builder.NewStep("build/compute-dependencies", builder.ProjectBuildPhase, builder.ComputeDependencies), + builder.NewStep("build/lookup-predefined-dependencies", builder.ProjectBuildPhase + 1, builder.LookupPredefinedImage), builder.NewStep("packager/incremental", builder.ApplicationPackagePhase, builder.IncrementalPackager), builder.NewStep("publisher/s2i", builder.ApplicationPublishPhase, Publisher), builder.NewStep("notify/context", builder.NotifyPhase, builder.NotifyIntegrationContext), diff --git a/pkg/trait/builder_test.go b/pkg/trait/builder_test.go index 1afefab..f67fad0 100644 --- a/pkg/trait/builder_test.go +++ b/pkg/trait/builder_test.go @@ -82,7 +82,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, 5) + assert.Len(t, env.Steps, 6) assert.Condition(t, func() bool { for _, s := range env.Steps { if s.ID() == "publisher/s2i" && s.Phase() == builder.ApplicationPublishPhase { @@ -102,7 +102,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, 5) + assert.Len(t, env.Steps, 6) assert.Condition(t, func() bool { for _, s := range env.Steps { if s.ID() == "publisher/kaniko" && s.Phase() == builder.ApplicationPublishPhase {