-
Notifications
You must be signed in to change notification settings - Fork 3k
Apply manifests from URL and await resources with readiness #48990
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
762027a
e38dce9
6343bf0
a89bef3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,12 +11,10 @@ | |
| import java.io.ByteArrayOutputStream; | ||
| import java.io.IOException; | ||
| import java.io.InputStream; | ||
| import java.net.URL; | ||
| import java.time.Duration; | ||
| import java.util.Base64; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Objects; | ||
| import java.util.Optional; | ||
| import java.util.*; | ||
| import java.util.concurrent.TimeUnit; | ||
| import java.util.function.Function; | ||
| import java.util.function.Supplier; | ||
| import java.util.stream.Collectors; | ||
|
|
@@ -45,8 +43,12 @@ | |
| import com.github.dockerjava.api.DockerClient; | ||
| import com.github.dockerjava.api.command.InspectContainerResponse; | ||
|
|
||
| import io.fabric8.kubernetes.api.model.HasMetadata; | ||
| import io.fabric8.kubernetes.api.model.*; | ||
| import io.fabric8.kubernetes.api.model.apps.Deployment; | ||
| import io.fabric8.kubernetes.api.model.apps.ReplicaSet; | ||
| import io.fabric8.kubernetes.api.model.apps.StatefulSet; | ||
| import io.fabric8.kubernetes.client.*; | ||
| import io.fabric8.kubernetes.client.Config; | ||
| import io.quarkus.deployment.Feature; | ||
| import io.quarkus.deployment.IsDevServicesSupportedByLaunchMode; | ||
| import io.quarkus.deployment.annotations.BuildProducer; | ||
|
|
@@ -196,10 +198,7 @@ public void applyManifests( | |
| .withConfig(Config.fromKubeconfig(kubernetesDevServiceInfoBuildItem.getKubeConfig())) | ||
| .build()) { | ||
| for (String manifestPath : manifests.get()) { | ||
| // Load the manifest from the resources directory | ||
| InputStream manifestStream = Thread.currentThread() | ||
| .getContextClassLoader() | ||
| .getResourceAsStream(manifestPath); | ||
| InputStream manifestStream = getManifestStream(manifestPath); | ||
|
|
||
| if (manifestStream == null) { | ||
| log.errorf("Could not find manifest file in resources: %s", manifestPath); | ||
|
|
@@ -210,21 +209,58 @@ public void applyManifests( | |
| try { | ||
| // A single manifest file may contain multiple resources to deploy | ||
| List<HasMetadata> resources = client.load(manifestStream).items(); | ||
| List<HasMetadata> resourcesWithReadiness = new ArrayList<>(); | ||
|
|
||
| if (resources.isEmpty()) { | ||
| log.warnf("No resources found in manifest: %s", manifestPath); | ||
| } else { | ||
| resources.forEach(resource -> client.resource(resource).create()); | ||
| resources.forEach(resource -> { | ||
| client.resource(resource).create(); | ||
|
|
||
| if (isReadinessApplicable(resource)) { | ||
| resourcesWithReadiness.add(resource); | ||
| } | ||
| }); | ||
|
|
||
| resourcesWithReadiness.forEach(resource -> { | ||
| log.info("Waiting for " + resource.getClass().getSimpleName() + " " | ||
| + resource.getMetadata().getName() | ||
| + " to be ready..."); | ||
| client.resource(resource).waitUntilReady(60, TimeUnit.SECONDS); | ||
| }); | ||
| } | ||
| } catch (Exception ex) { | ||
| log.errorf("Failed to deploy manifest %s: %s", manifestPath, ex.getMessage()); | ||
| log.errorf("Failed to apply manifest %s: %s", manifestPath, ex.getMessage()); | ||
| } | ||
| } | ||
|
|
||
| log.infof("Applied manifest %s.", manifestPath); | ||
| } | ||
| } catch (Exception e) { | ||
| log.error("Failed to create Kubernetes client while trying to deploy manifests.", e); | ||
| log.error("Failed to create Kubernetes client while trying to apply manifests.", e); | ||
| } | ||
| } | ||
|
|
||
| private boolean isReadinessApplicable(HasMetadata item) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've created a PR: fabric8io/kubernetes-client#7206, we should use the implementation from the client's
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah perfect! That is indeed exactly why I copied the function over, because it wasn't available publicly
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This probably has to go through the whole cycle though of merge -> release -> upgrade in Quarkus, then we can change this? Would it be possible to merge this PR with the copied over function for now and I'll make sure I'll make a followup PR once the function is available? So we can make the next LTS Quarkus release with these changes?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new version of fabric8 has been released and merged in, however I'm still not happy with the public API as it's non-static, I made a followup PR before we remove the copied method: fabric8io/kubernetes-client#7280 |
||
| return (item instanceof Deployment || | ||
| item instanceof io.fabric8.kubernetes.api.model.extensions.Deployment || | ||
| item instanceof ReplicaSet || | ||
| item instanceof Pod || | ||
| item instanceof ReplicationController || | ||
| item instanceof Endpoints || | ||
| item instanceof Node || | ||
| item instanceof StatefulSet); | ||
| } | ||
|
|
||
| private InputStream getManifestStream(String manifestPath) throws IOException { | ||
| if (manifestPath.startsWith("http://") || manifestPath.startsWith("https://")) { | ||
LarsSven marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // Option 1: The manifest is a URL, in which case we download it | ||
| return new URL(manifestPath).openStream(); | ||
| } else { | ||
| // Option 2: The manifest is a file in the resources directory | ||
| return Thread.currentThread() | ||
| .getContextClassLoader() | ||
| .getResourceAsStream(manifestPath); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,2 @@ | ||
| quarkus.kubernetes-client.devservices.manifests=kubernetes/namespace.yaml | ||
| quarkus.kubernetes-client.devservices.manifests[0]=kubernetes/namespace.yaml | ||
| quarkus.kubernetes-client.devservices.manifests[1]=https://k8s.io/examples/admin/namespace-dev.yaml |
Uh oh!
There was an error while loading. Please reload this page.