瀏覽代碼

that is it

Grega Bremec 7 月之前
當前提交
1de70f577c

+ 159 - 0
pom.xml

@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.redhat.training</groupId>
+    <artifactId>job-activator</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+
+    <properties>
+        <compiler-plugin.version>3.12.1</compiler-plugin.version>
+        <maven.compiler.release>17</maven.compiler.release>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
+        <quarkus.platform.group-id>com.redhat.quarkus.platform</quarkus.platform.group-id>
+        <quarkus.platform.version>3.8.5.SP1-redhat-00001</quarkus.platform.version>
+        <skipITs>true</skipITs>
+        <surefire-plugin.version>3.2.5</surefire-plugin.version>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>${quarkus.platform.group-id}</groupId>
+                <artifactId>${quarkus.platform.artifact-id}</artifactId>
+                <version>${quarkus.platform.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy-reactive-jackson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy-reactive</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-rest-client-reactive</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-arc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-junit5</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.rest-assured</groupId>
+            <artifactId>rest-assured</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <repositories>
+        <repository>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+            <id>redhat</id>
+            <url>https://maven.repository.redhat.com/ga</url>
+        </repository>
+    </repositories>
+
+    <pluginRepositories>
+        <pluginRepository>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+            <id>redhat</id>
+            <url>https://maven.repository.redhat.com/ga</url>
+        </pluginRepository>
+    </pluginRepositories>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>${quarkus.platform.group-id}</groupId>
+                <artifactId>quarkus-maven-plugin</artifactId>
+                <version>${quarkus.platform.version}</version>
+                <extensions>true</extensions>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>build</goal>
+                            <goal>generate-code</goal>
+                            <goal>generate-code-tests</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>${compiler-plugin.version}</version>
+                <configuration>
+                    <compilerArgs>
+                        <arg>-parameters</arg>
+                    </compilerArgs>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>${surefire-plugin.version}</version>
+                <configuration>
+                    <systemPropertyVariables>
+                        <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
+                        <maven.home>${maven.home}</maven.home>
+                    </systemPropertyVariables>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <version>${surefire-plugin.version}</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>integration-test</goal>
+                            <goal>verify</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <systemPropertyVariables>
+                        <native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
+                        <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
+                        <maven.home>${maven.home}</maven.home>
+                    </systemPropertyVariables>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>native</id>
+            <activation>
+                <property>
+                    <name>native</name>
+                </property>
+            </activation>
+            <properties>
+                <skipITs>false</skipITs>
+                <quarkus.native.enabled>true</quarkus.native.enabled>
+            </properties>
+        </profile>
+    </profiles>
+</project>

+ 63 - 0
src/main/java/com/redhat/training/Activator.java

@@ -0,0 +1,63 @@
+package com.redhat.training;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Optional;
+
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+import org.eclipse.microprofile.rest.client.inject.RestClient;
+import org.jboss.logging.Logger;
+
+import jakarta.annotation.PostConstruct;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+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<String> token;
+
+    @Inject
+    @RestClient
+    ApiClient k8s;
+
+    @PostConstruct
+    public void checkEnv() {
+        if (token.isPresent() && !token.get().isEmpty()) {
+            LOG.info("Got token from env.");
+            return;
+        }
+
+        LOG.info("Token not found in env. Trying serviceaccount token.");
+        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();
+                return;
+            } catch (IOException ioe) {
+                LOG.error("Can not read service account token. This will probably all go to hell.");
+            }
+        }
+
+        throw new RuntimeException("API Token not set. Can not talk to API.");
+    }
+
+    @POST
+    public String createJob(JobDescription job) {
+        return k8s.createJob(token.get(),
+                            job.getNamespace(),
+                            job.getName(),
+                            new Job(job.getNamespace(),
+                                     job.getName(),
+                                     job.getCommand()).getApiResource());
+    }
+}

+ 40 - 0
src/main/java/com/redhat/training/ApiClient.java

@@ -0,0 +1,40 @@
+package com.redhat.training;
+
+import java.util.List;
+
+import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
+
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.HeaderParam;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+
+@Path("/apis/batch/v1")
+@RegisterRestClient(baseUri="https://kubernetes.default")
+public interface ApiClient {
+    @POST
+    @Path("/namespaces/{namespace}/jobs/{job}")
+    @Consumes("application/yaml")
+    @Produces(MediaType.APPLICATION_JSON)
+    String createJob(@HeaderParam("Authorization") String token,
+                     @PathParam("namespace") String namespace,
+                     @PathParam("job") String jobName,
+                     String job);
+
+    @GET
+    @Path("/namespaces/{namespace}/jobs/{job}")
+    @Produces(MediaType.APPLICATION_JSON)
+    String getJob(@HeaderParam("Authorization") String token,
+                  @PathParam("namespace") String namespace,
+                  @PathParam("job") String jobName);
+
+    @GET
+    @Path("/namespaces/{namespace}/jobs")
+    @Produces(MediaType.APPLICATION_JSON)
+    List<String> getAllJobs(@HeaderParam("Authorization") String token,
+                            @PathParam("namespace") String namespace);
+}

+ 53 - 0
src/main/java/com/redhat/training/Job.java

@@ -0,0 +1,53 @@
+package com.redhat.training;
+
+import org.jboss.logmanager.Logger;
+
+public class Job {
+    final Logger LOG = Logger.getLogger(Job.class.getName());
+
+    final String apiResourceTemplate = """
+            apiVersion: batch/v1
+            kind: Job
+            metadata:
+              name: %s
+              namespace: %s
+            spec:
+              activeDeadlineSeconds: 30
+              completions: 1
+              parallelism: 1
+              selector:
+                matchLabels:
+                  jobname: %s
+              template:
+                metadata:
+                  labels:
+                    jobname: %s
+                spec:
+                  containers:
+                    - name: job-%s
+                      image: registry.access.redhat.com/ubi9/ubi:latest
+                      command:
+                        - /bin/bash
+                        - -c
+                        - %s
+            """;
+    String apiResource;
+
+    public Job(String namespace, String name, String command) {
+        LOG.info("Constructing: namespace = " + namespace + ", " +
+                                "name = " + name + ", " +
+                                "command = " + command);
+
+        this.apiResource = String.format(apiResourceTemplate,
+                                         name,
+                                         namespace,
+                                         name, name, name,
+                                         command);
+
+        LOG.info("Constructed:\n" + this.apiResource);
+    }
+
+    public String getApiResource() {
+        return apiResource;
+    }
+}

+ 25 - 0
src/main/java/com/redhat/training/JobDescription.java

@@ -0,0 +1,25 @@
+package com.redhat.training;
+
+public class JobDescription {
+    String namespace;
+    String name;
+    String command;
+    public String getName() {
+        return name;
+    }
+    public void setName(String name) {
+        this.name = name;
+    }
+    public String getCommand() {
+        return command;
+    }
+    public void setCommand(String command) {
+        this.command = command;
+    }
+    public String getNamespace() {
+        return namespace;
+    }
+    public void setNamespace(String namespace) {
+        this.namespace = namespace;
+    }
+}