diff --git a/CHANGELOG.md b/CHANGELOG.md index a69c657438..bb017f730f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ After this we will switch probably to real [Semantic Versioning 2.0.0](http://se * Fix #1695: IllegalArgumentException when Spring Boot application.yaml contains integer keys * Fix #797: spring-boot generator can not handle multi-profile configuration * Fix #1751: Build Names are suffixed with -s2i regardless of build strategy +* Fix #1770: Support for setting BuildConfig memory/cpu request and limits * Fix #1755: Spring boot enricher does not produce a proper heath check and liveness check path when "/" is used. * Feature: Check maven.compiler.target property for base image detection. * Fix: Enrichers should resolve relative paths against project directory, not working directory diff --git a/core/src/main/java/io/fabric8/maven/core/config/OpenshiftBuildConfig.java b/core/src/main/java/io/fabric8/maven/core/config/OpenshiftBuildConfig.java new file mode 100644 index 0000000000..8266b28c7c --- /dev/null +++ b/core/src/main/java/io/fabric8/maven/core/config/OpenshiftBuildConfig.java @@ -0,0 +1,40 @@ +/** + * Copyright 2016 Red Hat, Inc. + * + * Red Hat 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 io.fabric8.maven.core.config; + +import java.util.Map; + +public class OpenshiftBuildConfig { + private Map limits; + + public Map getRequests() { + return requests; + } + + public void setRequests(Map requests) { + this.requests = requests; + } + + private Map requests; + + public Map getLimits() { + return limits; + } + + public void setLimits(Map resourceLimits) { + this.limits = resourceLimits; + } +} diff --git a/core/src/main/java/io/fabric8/maven/core/config/ResourceConfig.java b/core/src/main/java/io/fabric8/maven/core/config/ResourceConfig.java index 70bca8f602..3c1ab89d9e 100644 --- a/core/src/main/java/io/fabric8/maven/core/config/ResourceConfig.java +++ b/core/src/main/java/io/fabric8/maven/core/config/ResourceConfig.java @@ -15,7 +15,6 @@ */ package io.fabric8.maven.core.config; -import io.fabric8.kubernetes.api.model.extensions.IngressRule; import org.apache.maven.plugins.annotations.Parameter; import java.util.List; @@ -97,6 +96,9 @@ public class ResourceConfig { */ private String routeDomain; + @Parameter + private OpenshiftBuildConfig openshiftBuildConfig; + public Optional> getEnv() { return Optional.ofNullable(env); } @@ -175,6 +177,9 @@ public List getRemotes() { public String getRouteDomain() { return routeDomain; } + public OpenshiftBuildConfig getOpenshiftBuildConfig() { + return openshiftBuildConfig; + } // ============================================================================================= public static class Builder { diff --git a/core/src/main/java/io/fabric8/maven/core/service/BuildService.java b/core/src/main/java/io/fabric8/maven/core/service/BuildService.java index f7bfca9696..2a4a6d929f 100644 --- a/core/src/main/java/io/fabric8/maven/core/service/BuildService.java +++ b/core/src/main/java/io/fabric8/maven/core/service/BuildService.java @@ -19,6 +19,7 @@ import io.fabric8.kubernetes.api.model.KubernetesListBuilder; import io.fabric8.maven.core.config.BuildRecreateMode; import io.fabric8.maven.core.config.OpenShiftBuildStrategy; +import io.fabric8.maven.core.config.ResourceConfig; import io.fabric8.maven.docker.config.ImageConfiguration; import io.fabric8.maven.docker.service.ImagePullManager; import io.fabric8.maven.docker.util.MojoParameters; @@ -72,6 +73,10 @@ class BuildServiceConfig { private boolean s2iImageStreamLookupPolicyLocal; + private ResourceConfig resourceConfig; + + private File resourceDir; + public BuildServiceConfig() { } @@ -121,6 +126,14 @@ public boolean isForcePullEnabled() { return forcePull; } + public ResourceConfig getResourceConfig() { + return resourceConfig; + } + + public File getResourceDir() { + return resourceDir; + } + public void attachArtifact(String classifier, File destFile) { if (attacher != null) { attacher.attach(classifier, destFile); @@ -198,6 +211,16 @@ public Builder imagePullManager(ImagePullManager imagePullManager) { return this; } + public Builder resourceConfig(ResourceConfig resourceConfig) { + config.resourceConfig = resourceConfig; + return this; + } + + public Builder resourceDir(File resourceDir) { + config.resourceDir = resourceDir; + return this; + } + public BuildServiceConfig build() { return config; } diff --git a/core/src/main/java/io/fabric8/maven/core/service/openshift/OpenshiftBuildService.java b/core/src/main/java/io/fabric8/maven/core/service/openshift/OpenshiftBuildService.java index c1196c6da6..058397146b 100644 --- a/core/src/main/java/io/fabric8/maven/core/service/openshift/OpenshiftBuildService.java +++ b/core/src/main/java/io/fabric8/maven/core/service/openshift/OpenshiftBuildService.java @@ -37,6 +37,7 @@ import io.fabric8.kubernetes.api.model.LocalObjectReferenceBuilder; import io.fabric8.kubernetes.api.model.ObjectReference; import io.fabric8.kubernetes.api.model.Pod; +import io.fabric8.kubernetes.api.model.Quantity; import io.fabric8.kubernetes.api.model.Status; import io.fabric8.kubernetes.client.KubernetesClientException; import io.fabric8.kubernetes.client.Watch; @@ -67,6 +68,7 @@ import io.fabric8.openshift.api.model.Build; import io.fabric8.openshift.api.model.BuildConfig; import io.fabric8.openshift.api.model.BuildConfigSpec; +import io.fabric8.openshift.api.model.BuildConfigSpecBuilder; import io.fabric8.openshift.api.model.BuildOutput; import io.fabric8.openshift.api.model.BuildOutputBuilder; import io.fabric8.openshift.api.model.BuildSource; @@ -257,17 +259,50 @@ private String createBuildConfig(KubernetesListBuilder builder, String buildName .withNewMetadata() .withName(buildName) .endMetadata() - .withNewSpec() - .withNewSource() - .withType("Binary") - .endSource() - .withStrategy(buildStrategyResource) - .withOutput(buildOutput) - .endSpec() + .withSpec(getBuildConfigSpec(buildStrategyResource, buildOutput)) .endBuildConfigItem(); return buildName; } + private BuildConfigSpec getBuildConfigSpec(BuildStrategy buildStrategyResource, BuildOutput buildOutput) { + BuildConfigSpecBuilder specBuilder = null; + + // Check for BuildConfig resource fragment + File buildConfigResourceFragment = KubernetesResourceUtil.getResourceFragmentFromSource(config.getResourceDir(), config.getResourceConfig(), "buildconfig.yml", log); + if (buildConfigResourceFragment != null) { + BuildConfig buildConfigFragment = client.buildConfigs().load(buildConfigResourceFragment).get(); + specBuilder = new BuildConfigSpecBuilder(buildConfigFragment.getSpec()); + } else { + specBuilder = new BuildConfigSpecBuilder(); + } + + if (specBuilder.buildSource() == null) { + specBuilder.withNewSource() + .withType("Binary") + .endSource(); + } + + if (specBuilder.buildStrategy() == null) { + specBuilder.withStrategy(buildStrategyResource); + } + + if (specBuilder.buildOutput() == null) { + specBuilder.withOutput(buildOutput); + } + + if (config.getResourceConfig() != null && config.getResourceConfig().getOpenshiftBuildConfig() != null) { + Map limits = KubernetesResourceUtil.getQuantityFromString(config.getResourceConfig().getOpenshiftBuildConfig().getLimits()); + if (limits != null && !limits.isEmpty()) { + specBuilder.editOrNewResources().addToLimits(limits).endResources(); + } + Map requests = KubernetesResourceUtil.getQuantityFromString(config.getResourceConfig().getOpenshiftBuildConfig().getRequests()); + if (limits != null && !limits.isEmpty()) { + specBuilder.editOrNewResources().addToRequests(requests).endResources() ; + } + } + return specBuilder.build(); + } + private String updateBuildConfig(OpenShiftClient client, String buildName, BuildStrategy buildStrategy, BuildOutput buildOutput, BuildConfigSpec spec) { // lets check if the strategy or output has changed and if so lets update the BC diff --git a/core/src/main/java/io/fabric8/maven/core/util/kubernetes/KubernetesResourceUtil.java b/core/src/main/java/io/fabric8/maven/core/util/kubernetes/KubernetesResourceUtil.java index 10ac3be95c..4a04c300a1 100644 --- a/core/src/main/java/io/fabric8/maven/core/util/kubernetes/KubernetesResourceUtil.java +++ b/core/src/main/java/io/fabric8/maven/core/util/kubernetes/KubernetesResourceUtil.java @@ -40,6 +40,7 @@ import io.fabric8.kubernetes.api.model.PodSpecBuilder; import io.fabric8.kubernetes.api.model.PodStatus; import io.fabric8.kubernetes.api.model.PodTemplateSpec; +import io.fabric8.kubernetes.api.model.Quantity; import io.fabric8.kubernetes.api.model.ReplicationController; import io.fabric8.kubernetes.api.model.ReplicationControllerSpec; import io.fabric8.kubernetes.api.model.apps.DaemonSet; @@ -55,6 +56,7 @@ import io.fabric8.kubernetes.api.model.batch.JobSpec; import io.fabric8.kubernetes.client.KubernetesClientException; import io.fabric8.kubernetes.internal.HasMetadataComparator; +import io.fabric8.maven.core.config.ResourceConfig; import io.fabric8.maven.core.util.FileUtil; import io.fabric8.maven.core.config.PlatformMode; import io.fabric8.maven.core.model.GroupArtifactVersion; @@ -1086,4 +1088,44 @@ private static boolean isLocalCustomisation(PodSpec podSpec) { } return true; } + + /** + * Get a specific resource fragment ending with some suffix + * + * @param resourceDirFinal resource directory + * @param resourceConfig resource config in case remote fragments are provided + * @param resourceNameSuffix resource name suffix + * @param log log object + * @return file if present or null + */ + public static File getResourceFragmentFromSource(File resourceDirFinal, ResourceConfig resourceConfig, String resourceNameSuffix, Logger log) { + if (resourceDirFinal != null) { + File[] resourceFiles = KubernetesResourceUtil.listResourceFragments(resourceDirFinal, resourceConfig != null ? resourceConfig.getRemotes() : null, log); + + if (resourceFiles != null) { + for (File file : resourceFiles) { + if (file.getName().endsWith(resourceNameSuffix)) { + return file; + } + } + } + } + return null; + } + + /** + * Get requests or limit objects from string hashmaps + * + * @param quantity hashmap of strings + * @return hashmap of string to quantity + */ + public static Map getQuantityFromString(Map quantity) { + Map stringQuantityMap = new HashMap<>(); + if (quantity != null && !quantity.isEmpty()) { + for (Map.Entry entry : quantity.entrySet()) { + stringQuantityMap.put(entry.getKey(), new Quantity(entry.getValue())); + } + } + return stringQuantityMap; + } } diff --git a/plugin/src/main/java/io/fabric8/maven/plugin/mojo/build/BuildMojo.java b/plugin/src/main/java/io/fabric8/maven/plugin/mojo/build/BuildMojo.java index 1e7f27b68c..19da9f8bbb 100644 --- a/plugin/src/main/java/io/fabric8/maven/plugin/mojo/build/BuildMojo.java +++ b/plugin/src/main/java/io/fabric8/maven/plugin/mojo/build/BuildMojo.java @@ -312,6 +312,8 @@ protected BuildService.BuildServiceConfig getBuildServiceConfig() throws MojoExe .forcePullEnabled(forcePull) .imagePullManager(getImagePullManager(imagePullPolicy, autoPull)) .buildDirectory(project.getBuild().getDirectory()) + .resourceDir(ResourceDirCreator.getFinalResourceDir(resourceDir, environment)) + .resourceConfig(resources) .attacher((classifier, destFile) -> { if (destFile.exists()) { projectHelper.attachArtifact(project, "yml", classifier, destFile);