package com.redhat.training; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.util.Optional; import javax.net.ssl.SSLContext; import org.apache.http.ssl.SSLContextBuilder; import org.apache.http.ssl.SSLContexts; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.rest.client.RestClientBuilder; import org.jboss.logging.Logger; import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.ApplicationScoped; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; @ApplicationScoped @Path("/jobs") public class Activator { final Logger LOG = Logger.getLogger(Activator.class.getName()); @ConfigProperty(name = "api.token") Optional token; @ConfigProperty(name = "api.endpoint") Optional apiserver; @ConfigProperty(name = "api.tlsca.file") Optional tlsca; ApiClient k8s; @PostConstruct public void checkEnv() { // Check for API token. if (token.isPresent() && !token.get().isEmpty()) { LOG.debug("Got API token from environment."); } else { LOG.warn("API token not found in environment. Trying service account."); File tf = new File("/var/run/secrets/kubernetes.io/serviceaccount/token"); if (tf.exists()) { try { BufferedReader br = new BufferedReader(new FileReader(tf)); this.token = Optional.of(br.readLine()); br.close(); } catch (IOException ioe) { throw new RuntimeException("Can not load service account token: " + ioe.getMessage(), ioe); } } else { throw new RuntimeException("API token unobtainable. Can not talk to API."); } } // Check for API server. if (apiserver.isPresent() && !apiserver.get().isEmpty()) { LOG.debug("Got API server endpoint from environment."); } else { LOG.warn("API server endpoint not set, defaulting to internal API server."); apiserver = Optional.of("https://kubernetes.default/"); } // Check for TLS CA cert. SSLContext sc = null; if (apiserver.get().startsWith("https://")) { File tlscaFile; if (tlsca.isPresent() && !tlsca.get().isEmpty()) { LOG.debug("Got TLS CA cert file from environment, checking."); tlscaFile = new File(tlsca.get()); } else { LOG.warn("TLS CA cert not found in environment. Trying service account."); tlscaFile = new File("/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"); } if (!tlscaFile.exists()) { throw new RuntimeException("TLS CA cert file set, but does not exist."); } LOG.info("Attempting to build SSLContext with " + tlscaFile.getAbsolutePath()); try { SSLContextBuilder scb = SSLContexts.custom().loadTrustMaterial(tlscaFile); sc = scb.build(); } catch (NoSuchAlgorithmException | KeyStoreException | CertificateException | IOException | KeyManagementException e) { throw new RuntimeException("Could not load TLS CA: " + e.getMessage(), e); } } try { if (sc == null) { this.k8s = RestClientBuilder.newBuilder() .baseUri(new URI(this.apiserver.get())) .build(ApiClient.class); } else { this.k8s = RestClientBuilder.newBuilder() .baseUri(new URI(this.apiserver.get())) .sslContext(sc) .build(ApiClient.class); } } catch (URISyntaxException use) { throw new RuntimeException("Could not construct BASE URI for REST client: " + use.getMessage(), use); } } @POST public String createJob(JobDescription job) { return k8s.createJob("Bearer " + token.get(), job.getNamespace(), job.getName(), new Job(job.getNamespace(), job.getName(), job.getCommand()).getApiResource()); } }