blob: a98faba30d377137bd2b301e6d42a1d5a7944f2a [file] [log] [blame]
/*
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 runtime
import (
"fmt"
"io/ioutil"
"os"
"path"
"github.com/apache/camel-k/pkg/util/digest"
yaml2 "gopkg.in/yaml.v2"
"github.com/pkg/errors"
v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
"github.com/apache/camel-k/pkg/builder"
"github.com/apache/camel-k/pkg/util/camel"
"github.com/apache/camel-k/pkg/util/defaults"
"github.com/apache/camel-k/pkg/util/maven"
)
// QuarkusSteps --
var QuarkusSteps = []builder.Step{
Steps.LoadCamelQuarkusCatalog,
Steps.GenerateQuarkusProject,
Steps.BuildQuarkusRunner,
Steps.ComputeQuarkusDependencies,
}
func loadCamelQuarkusCatalog(ctx *builder.Context) error {
catalog, err := camel.LoadCatalog(ctx.C, ctx.Client, ctx.Build.Meta.Namespace, ctx.Build.Runtime)
if err != nil {
return err
}
if catalog == nil {
return fmt.Errorf("unable to find catalog matching version requirement: runtime=%s, provider=%s",
ctx.Build.Runtime.Version,
ctx.Build.Runtime.Provider)
}
ctx.Catalog = catalog
return nil
}
func generateQuarkusProject(ctx *builder.Context) error {
p := GenerateQuarkusProjectCommon(ctx.Build.Runtime.Metadata["camel-quarkus.version"], ctx.Build.Runtime.Version, ctx.Build.Runtime.Metadata["quarkus.version"])
// Add all the properties from the build configuration
p.Properties.AddAll(ctx.Build.Properties)
ctx.Maven.Project = p
return nil
}
// GenerateQuarkusProjectCommon --
func GenerateQuarkusProjectCommon(camelQuarkusVersion string, runtimeVersion string, quarkusVersion string) maven.Project {
p := maven.NewProjectWithGAV("org.apache.camel.k.integration", "camel-k-integration", defaults.Version)
p.DependencyManagement = &maven.DependencyManagement{Dependencies: make([]maven.Dependency, 0)}
p.Dependencies = make([]maven.Dependency, 0)
p.Build = &maven.Build{Plugins: make([]maven.Plugin, 0)}
// camel-quarkus doe routes discovery at startup but we don't want
// this to happen as routes are loaded at runtime and looking for
// routes at build time may try to load camel-k-runtime routes builder
// proxies which in some case may fail
p.Properties["quarkus.camel.main.routes-discovery.enabled"] = "false"
// disable quarkus banner ...
p.Properties["quarkus.banner.enabled"] = "false"
// DependencyManagement
p.DependencyManagement.Dependencies = append(p.DependencyManagement.Dependencies,
maven.Dependency{
GroupID: "org.apache.camel.quarkus",
ArtifactID: "camel-quarkus-bom",
Version: camelQuarkusVersion,
Type: "pom",
Scope: "import",
},
maven.Dependency{
GroupID: "org.apache.camel.k",
ArtifactID: "camel-k-runtime-bom",
Version: runtimeVersion,
Type: "pom",
Scope: "import",
},
)
// Plugins
p.Build.Plugins = append(p.Build.Plugins,
maven.Plugin{
GroupID: "io.quarkus",
ArtifactID: "quarkus-maven-plugin",
Version: quarkusVersion,
Executions: []maven.Execution{
{
Goals: []string{
"build",
},
},
},
},
)
return p
}
func buildQuarkusRunner(ctx *builder.Context) error {
mc := maven.NewContext(path.Join(ctx.Path, "maven"), ctx.Maven.Project)
mc.SettingsContent = ctx.Maven.SettingsData
mc.LocalRepository = ctx.Build.Maven.LocalRepository
mc.Timeout = ctx.Build.Maven.GetTimeout().Duration
err := BuildQuarkusRunnerCommon(mc)
if err != nil {
return err
}
return nil
}
// BuildQuarkusRunnerCommon --
func BuildQuarkusRunnerCommon(mc maven.Context) error {
resourcesPath := path.Join(mc.Path, "src", "main", "resources")
if err := os.MkdirAll(resourcesPath, os.ModePerm); err != nil {
return errors.Wrap(err, "failure while creating resource folder")
}
// generate an empty application.properties so that there will be something in
// target/classes as if such directory does not exist, the quarkus maven plugin
// mai fail the build
//
// in the future there should be a way to provide build information from secrets,
// configmap, etc.
if _, err := os.Create(path.Join(resourcesPath, "application.properties")); err != nil {
return errors.Wrap(err, "failure while creating application.properties")
}
// Build the project
mc.AddArgument("package")
if err := maven.Run(mc); err != nil {
return errors.Wrap(err, "failure while building project")
}
return nil
}
func computeQuarkusDependencies(ctx *builder.Context) error {
mc := maven.NewContext(path.Join(ctx.Path, "maven"), ctx.Maven.Project)
mc.SettingsContent = ctx.Maven.SettingsData
mc.LocalRepository = ctx.Build.Maven.LocalRepository
mc.Timeout = ctx.Build.Maven.GetTimeout().Duration
// Compute dependencies.
content, err := ComputeQuarkusDependenciesCommon(mc, ctx.Catalog.Runtime.Version)
if err != nil {
return err
}
// Process artifacts list and add it to existing artifacts.
artifacts := []v1.Artifact{}
artifacts, err = ProcessQuarkusTransitiveDependencies(mc, content)
if err != nil {
return err
}
ctx.Artifacts = append(ctx.Artifacts, artifacts...)
return nil
}
// ComputeQuarkusDependenciesCommon --
func ComputeQuarkusDependenciesCommon(mc maven.Context, runtimeVersion string) ([]byte, error) {
// Retrieve the runtime dependencies
mc.AddArgumentf("org.apache.camel.k:camel-k-maven-plugin:%s:generate-dependency-list", runtimeVersion)
if err := maven.Run(mc); err != nil {
return nil, errors.Wrap(err, "failure while determining classpath")
}
dependencies := path.Join(mc.Path, "target", "dependencies.yaml")
content, err := ioutil.ReadFile(dependencies)
if err != nil {
return nil, err
}
return content, nil
}
// ProcessQuarkusTransitiveDependencies --
func ProcessQuarkusTransitiveDependencies(mc maven.Context, content []byte) ([]v1.Artifact, error) {
cp := make(map[string][]v1.Artifact)
err := yaml2.Unmarshal(content, &cp)
if err != nil {
return nil, err
}
artifacts := []v1.Artifact{}
for _, e := range cp["dependencies"] {
_, fileName := path.Split(e.Location)
gav, err := maven.ParseGAV(e.ID)
if err != nil {
return nil, err
}
//
// Compute the checksum if it has not been computed by the camel-k-maven-plugin
//
if e.Checksum == "" {
chksum, err := digest.ComputeSHA1(e.Location)
if err != nil {
return nil, err
}
e.Checksum = "sha1:" + chksum
}
artifacts = append(artifacts, v1.Artifact{
ID: e.ID,
Location: e.Location,
Target: path.Join("dependencies", gav.GroupID+"."+fileName),
Checksum: e.Checksum,
})
}
runner := "camel-k-integration-" + defaults.Version + "-runner.jar"
//
// Quarkus' runner checksum need to be recomputed each time
//
runnerChecksum, err := digest.ComputeSHA1(mc.Path, "target", runner)
if err != nil {
return nil, err
}
artifacts = append(artifacts, v1.Artifact{
ID: runner,
Location: path.Join(mc.Path, "target", runner),
Target: path.Join("dependencies", runner),
Checksum: "sha1:" + runnerChecksum,
})
return artifacts, nil
}