Skip to content

Commit

Permalink
Merge pull request #3 from rnc/NCL8969
Browse files Browse the repository at this point in the history
Port implementation code from JBS
  • Loading branch information
rnc authored Dec 9, 2024
2 parents f9d2037 + 32a8248 commit 6be43f4
Show file tree
Hide file tree
Showing 20 changed files with 714 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,4 @@ jobs:
"password": "${{ secrets.SONATYPE_PASSWORD }}"
}]
- name: Deploy Snapshot
run: mvn -B -V -Pjboss-release org.apache.maven.plugins:maven-source-plugin:jar-no-fork deploy
run: mvn -B -V -Pjboss-release deploy
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
# konflux-build-driver
# konflux-build-driver

Uses the same pattern as https://github.com/project-ncl/build-driver/ or https://github.com/project-ncl/environment-driver/ but targeted towards a Konflux deployment.
118 changes: 118 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@
</dependencyManagement>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-info</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc</artifactId>
Expand All @@ -81,10 +85,29 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc-client</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-openshift-client</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-client-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.quarkiverse.tektonclient</groupId>
<artifactId>quarkus-tekton-client</artifactId>
<version>1.0.1</version>
</dependency>

<dependency>
<groupId>org.jboss.pnc</groupId>
<artifactId>pnc-api</artifactId>
<version>3.0.0</version>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
Expand All @@ -98,11 +121,31 @@
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-component</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-mockito</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-kubernetes-client</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down Expand Up @@ -156,6 +199,7 @@
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
Expand All @@ -179,5 +223,79 @@
<quarkus.native.enabled>true</quarkus.native.enabled>
</properties>
</profile>
<profile>
<id>format</id>
<activation>
<activeByDefault>true</activeByDefault>
<property>
<name>!validate-format</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>net.revelc.code.formatter</groupId>
<artifactId>formatter-maven-plugin</artifactId>
<executions>
<execution>
<phase>process-sources</phase>
<goals>
<goal>format</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>net.revelc.code</groupId>
<artifactId>impsort-maven-plugin</artifactId>
<executions>
<execution>
<id>sort-imports</id>
<goals>
<goal>sort</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>validate</id>
<activation>
<activeByDefault>false</activeByDefault>
<property>
<name>validate-format</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>net.revelc.code.formatter</groupId>
<artifactId>formatter-maven-plugin</artifactId>
<executions>
<execution>
<phase>process-sources</phase>
<goals>
<goal>validate</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>net.revelc.code</groupId>
<artifactId>impsort-maven-plugin</artifactId>
<executions>
<execution>
<id>check-imports</id>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
142 changes: 142 additions & 0 deletions src/main/java/org/jboss/pnc/konfluxbuilddriver/Driver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package org.jboss.pnc.konfluxbuilddriver;

import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
import jakarta.inject.Inject;

import org.apache.commons.io.IOUtils;
import org.eclipse.microprofile.config.ConfigProvider;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.jboss.pnc.konfluxbuilddriver.clients.IndyService;
import org.jboss.pnc.konfluxbuilddriver.clients.IndyTokenRequestDTO;
import org.jboss.pnc.konfluxbuilddriver.clients.IndyTokenResponseDTO;
import org.jboss.pnc.konfluxbuilddriver.dto.BuildRequest;
import org.jboss.pnc.konfluxbuilddriver.dto.BuildResponse;
import org.jboss.pnc.konfluxbuilddriver.dto.CancelRequest;
import org.jboss.pnc.konfluxbuilddriver.util.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.fabric8.knative.internal.pkg.apis.Condition;
import io.fabric8.kubernetes.api.model.Quantity;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.tekton.client.TektonClient;
import io.fabric8.tekton.pipeline.v1.ParamBuilder;
import io.fabric8.tekton.pipeline.v1.PipelineRun;
import io.fabric8.tekton.pipeline.v1.PipelineRunStatusBuilder;
import io.quarkus.oidc.client.OidcClient;
import io.quarkus.runtime.StartupEvent;

@ApplicationScoped
public class Driver {

private static final Logger logger = LoggerFactory.getLogger(Driver.class);

@Inject
OidcClient oidcClient;

@RestClient
IndyService indyService;

@Inject
KubernetesClient client;

@Inject
Configuration config;

URL pipelineRunTemplate;

void onStart(@Observes StartupEvent ev) {
try {
pipelineRunTemplate = IOUtils.resourceToURL("pipeline-run.yaml", Thread.currentThread().getContextClassLoader());
logger.debug("Driver creating with {}", pipelineRunTemplate);
} catch (IOException e) {
throw new RuntimeException(e);
}
}

public BuildResponse create(BuildRequest buildRequest) {

logger.info("Establishing token from Indy using clientId {}",
ConfigProvider.getConfig().getConfigValue("quarkus.oidc.client-id").getValue());
IndyTokenResponseDTO tokenResponseDTO = indyService.getAuthToken(
new IndyTokenRequestDTO(buildRequest.repositoryBuildContentId()),
"Bearer " + getFreshAccessToken());

Map<String, String> templateProperties = new HashMap<>();
templateProperties.put("ACCESS_TOKEN", tokenResponseDTO.token());
templateProperties.put("BUILD_ID", buildRequest.repositoryBuildContentId());
templateProperties.put("BUILD_SCRIPT", buildRequest.buildScript());
templateProperties.put("BUILD_TOOL", buildRequest.buildTool());
templateProperties.put("BUILD_TOOL_VERSION", buildRequest.buildToolVersion());
templateProperties.put("JAVA_VERSION", buildRequest.javaVersion());
templateProperties.put("MVN_REPO_DEPENDENCIES_URL", buildRequest.repositoryDependencyUrl());
templateProperties.put("MVN_REPO_DEPLOY_URL", buildRequest.repositoryDeployUrl());
templateProperties.put("QUAY_REPO", config.quayRepo());
templateProperties.put("RECIPE_IMAGE", buildRequest.recipeImage());
templateProperties.put("JVM_BUILD_SERVICE_REQPROCESSOR_IMAGE", config.processor());
templateProperties.put("REVISION", buildRequest.scmRevision());
templateProperties.put("URL", buildRequest.scmUrl());
templateProperties.put("caTrustConfigMapName", "custom-ca");
// TODO: This should be changed to true eventually.
templateProperties.put("ENABLE_INDY_PROXY", config.indyProxyEnabled());

// Various ways to create the initial PipelineRun object. We can use an objectmapper,
// client.getKubernetesSerialization() or the load calls on the Fabric8 objects.
PipelineRun pipelineRun = client.adapt(TektonClient.class).v1().pipelineRuns().load(pipelineRunTemplate).item();
pipelineRun = pipelineRun.edit().editOrNewSpec()
.editPipelineRef()
.editFirstParam().editOrNewValue().withStringVal(config.resolverTarget()).endValue()
.endParam()
.endPipelineRef()
.addAllToParams(templateProperties.entrySet().stream()
.map(t -> new ParamBuilder().withName(t.getKey()).withNewValue(t.getValue()).build()).toList())
.editFirstTaskRunSpec()
.editFirstStepSpec()
.editComputeResources()
.addToLimits("memory", new Quantity(buildRequest.podMemoryOverride()))
.addToRequests("memory", new Quantity(buildRequest.podMemoryOverride()))
.endComputeResources()
.endStepSpec()
.endTaskRunSpec()
.endSpec().build();

var created = client.resource(pipelineRun).inNamespace(buildRequest.namespace()).create();

return BuildResponse.builder().namespace(buildRequest.namespace()).pipelineId(created.getMetadata().getName()).build();
}

public void cancel(CancelRequest request) {
var tc = client.adapt(TektonClient.class);
var pipeline = tc.v1().pipelineRuns().inNamespace(request.namespace()).withName(request.pipelineId()).get();

logger.info("Retrieved pipeline {}", pipeline.getMetadata().getName());

// https://tekton.dev/docs/pipelines/pipelineruns/#monitoring-execution-status
Condition cancelCondition = new Condition();
cancelCondition.setType("Succeeded");
cancelCondition.setStatus("False");
// https://github.com/tektoncd/community/blob/main/teps/0058-graceful-pipeline-run-termination.md
cancelCondition.setReason("CancelledRunFinally");
cancelCondition.setMessage("The PipelineRun was cancelled");

pipeline.setStatus(new PipelineRunStatusBuilder(pipeline.getStatus()).withConditions(cancelCondition).build());

tc.v1().pipelineRuns().inNamespace(request.namespace()).resource(pipeline).updateStatus();
}

/**
* Get a fresh access token for the service account. This is done because we want to get a super-new token to be used since
* we're not entirely sure when the http request will be done.
*
* @return fresh access token
*/
public String getFreshAccessToken() {
return oidcClient.getTokens().await().indefinitely().getAccessToken();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

/**
Expand All @@ -15,12 +16,11 @@
public interface IndyService {

/**
* Ask Indy to give us the token that we will use for Maven communication with Indy, in the builder pod for the
* particular buildId
* Ask Indy to give us the token that we will use for Maven communication with Indy, in the builder pod for the particular
* buildId
*
* @param indyTokenRequestDTO the DTO to send to Indy
* @param accessToken accessToken required to send data. Note that it should include "Bearer <token>"
*
* @return Token DTO
*/
@Path("/api/security/auth/token")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.jboss.pnc.konfluxbuilddriver.clients;

import com.fasterxml.jackson.annotation.JsonProperty;

import lombok.Builder;

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.jboss.pnc.konfluxbuilddriver.dto;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import lombok.Builder;

@Builder(builderClassName = "Builder")
@JsonIgnoreProperties(ignoreUnknown = true)
public record BuildRequest(
String recipeImage,
String buildTool,
String buildToolVersion,
String javaVersion,
String projectName,
String scmUrl,
String scmRevision,
String buildScript,
String repositoryDependencyUrl,
String repositoryDeployUrl,
String repositoryBuildContentId,
String namespace,
String podMemoryOverride) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.jboss.pnc.konfluxbuilddriver.dto;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import lombok.Builder;

@Builder(builderClassName = "Builder")
@JsonIgnoreProperties(ignoreUnknown = true)
public record BuildResponse(
String pipelineId,
String namespace) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.jboss.pnc.konfluxbuilddriver.dto;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import lombok.Builder;

@Builder(builderClassName = "Builder")
@JsonIgnoreProperties(ignoreUnknown = true)
public record CancelRequest(
String pipelineId,
String namespace) {

}
Loading

0 comments on commit 6be43f4

Please sign in to comment.