11package io .dagger .modules .ci ;
22
3+ import static io .dagger .client .Dagger .dag ;
4+ import static io .dagger .modules .ci .Utils .*;
5+
36import io .dagger .client .AwsCli ;
47import io .dagger .client .CacheVolume ;
5- import io .dagger .client .Client .AwsCliArguments ;
68import io .dagger .client .Container ;
79import io .dagger .client .Container .PublishArguments ;
8- import io .dagger .client .Container .WithExecArguments ;
910import io .dagger .client .DaggerQueryException ;
1011import io .dagger .client .Directory ;
1112import io .dagger .client .Directory .DockerBuildArguments ;
1213import io .dagger .client .Platform ;
1314import io .dagger .client .Secret ;
14- import io .dagger .client .Service ;
15- import io .dagger .module .AbstractModule ;
1615import io .dagger .module .annotation .Default ;
1716import io .dagger .module .annotation .DefaultPath ;
1817import io .dagger .module .annotation .Function ;
1918import io .dagger .module .annotation .Object ;
2019import java .util .List ;
2120import java .util .concurrent .ExecutionException ;
21+ import org .slf4j .Logger ;
22+ import org .slf4j .LoggerFactory ;
2223
2324/** Ci main object */
2425@ Object
25- public class Ci extends AbstractModule {
26+ public class Ci {
2627
27- /**
28- * Builds the application and optionally run the tests
29- *
30- * @param source the source directory
31- * @param skipTests whether to skip the tests
32- */
28+ static final Logger LOG = LoggerFactory .getLogger (Ci .class );
29+
30+ private static final List <String > ARCHS = List .of ("amd64" , "arm64" );
31+
32+ /** Build and test the application */
3333 @ Function
3434 public Container build (@ DefaultPath ("." ) Directory source , @ Default ("false" ) boolean skipTests )
3535 throws ExecutionException , DaggerQueryException , InterruptedException {
@@ -49,10 +49,14 @@ public Container buildImage(@DefaultPath(".") Directory source)
4949 .withDockerfile ("src/main/docker/Dockerfile.jvm" ));
5050 }
5151
52- private List <Container > buildImageMultiarch (Directory source ) {
53- List <String > variants = List .of ("amd64" , "arm64" );
52+ /**
53+ * Build a list of Docker images for multiple architectures
54+ * @param source the source directory
55+ */
56+ private List <Container > buildImageMultiarch (Directory source , List <String > variants ) {
5457 List <Container > images = variants .stream ().map (platform -> {
5558 try {
59+ LOG .info ("Building image for {}" , platform );
5660 return buildImage (source , platform );
5761 } catch (ExecutionException | DaggerQueryException | InterruptedException e ) {
5862 throw new RuntimeException (e );
@@ -70,59 +74,69 @@ private Container buildImage(Directory source, String platform)
7074 .withDockerfile ("src/main/docker/Dockerfile.jvm" ));
7175 }
7276
73- /**
74- * Runs the application as a service
75- */
76- @ Function
77- public Service run (@ DefaultPath ("." ) Directory source , @ Default ("8080" ) int port ,
78- Secret awsAccessKeyId , Secret awsSecretAccessKey )
79- throws ExecutionException , DaggerQueryException , InterruptedException {
80- Container ctr = buildImage (source )
81- .withSecretVariable ("AWS_ACCESS_KEY_ID" , awsAccessKeyId )
82- .withSecretVariable ("AWS_SECRET_ACCESS_KEY" , awsSecretAccessKey );
83- return ctr .asService ();
84- }
85-
8677 /**
8778 * Publishes the Docker image to ECR
79+ *
80+ * @param source the source directory
81+ * @param awsAccessKeyId the AWS access key ID
82+ * @param awsSecretAccessKey the AWS secret access key
83+ * @param region the AWS region
8884 */
8985 @ Function
90- public String publish (@ DefaultPath ("." ) Directory source , Secret awsAccessKeyId , Secret awsSecretAccessKey )
86+ public String publish (@ DefaultPath ("." ) Directory source , Secret awsAccessKeyId ,
87+ Secret awsSecretAccessKey , @ Default ("eu-west-1" ) String region )
9188 throws ExecutionException , DaggerQueryException , InterruptedException {
92- AwsCli awsCli = dag . awsCli (). withRegion ( "eu-west-1" ). withStaticCredentials ( awsAccessKeyId , awsSecretAccessKey );
89+ AwsCli awsCli = aws ( region , awsAccessKeyId , awsSecretAccessKey );
9390 Secret token = awsCli .ecr ().getLoginPassword ();
9491 String accountId = awsCli .sts ().getCallerIdentity ().account ();
95- String address = "%s.dkr.ecr.eu-west-1 .amazonaws.com/parisjug-dagger-demo/translate-api:%s"
96- .formatted (accountId , dag .gitInfo (source ).commitHash ().substring (0 , 8 ));
97- dag .container ()
92+ String address = "%s.dkr.ecr.%s .amazonaws.com/parisjug-dagger-demo/translate-api:%s"
93+ .formatted (accountId , region , dag () .gitInfo (source ).commitHash ().substring (0 , 8 ));
94+ dag () .container ()
9895 .withRegistryAuth (address , "AWS" , token )
99- .publish (address , new PublishArguments ().withPlatformVariants (buildImageMultiarch (source )));
96+ .publish (address , new PublishArguments ()
97+ .withPlatformVariants (buildImageMultiarch (source , ARCHS )));
10098 return address ;
10199 }
102100
103101 /**
104102 * Deploys the application to EKS
103+ *
104+ * @param source the source directory
105+ * @param image the image address to deploy
106+ * @param clusterName the name of the EKS cluster
107+ * @param awsAccessKeyId the AWS access key ID
108+ * @param awsSecretAccessKey the AWS secret access key
109+ * @param region the AWS region
105110 */
106111 @ Function
107- public String deploy (@ DefaultPath ("." ) Directory source , String image , Secret awsAccessKeyId , Secret awsSecretAccessKey )
112+ public String deploy (@ DefaultPath ("." ) Directory source , String image , String clusterName ,
113+ Secret awsAccessKeyId , Secret awsSecretAccessKey , @ Default ("eu-west-1" ) String region )
108114 throws ExecutionException , DaggerQueryException , InterruptedException {
109- Container deployerCtr = dag .container ().from ("alpine" )
110- .withExec (List .of ("apk" , "add" , "aws-cli" , "kubectl" ));
111- String appYaml = source .file ("src/main/kube/app.yaml" ).contents ().replace ("${IMAGE_TAG}" , image );
112- return dag .awsCli (new AwsCliArguments ().withContainer (deployerCtr ))
113- .withRegion ("eu-west-1" )
114- .withStaticCredentials (awsAccessKeyId , awsSecretAccessKey )
115- .exec (List .of ("eks" , "update-kubeconfig" , "--name" , "confused-classical-sheepdog" ))
116- .withEnvVariable ("IMAGE_TAG" , image )
115+ String appYaml = envsubst (source .file ("src/main/kube/app.yaml" ).contents (), "IMAGE_TAG" , image );
116+ return kubectl (clusterName , region , awsAccessKeyId , awsSecretAccessKey )
117117 .withNewFile ("/tmp/app.yaml" , appYaml )
118118 .withExec (List .of ("kubectl" , "apply" , "-f" , "/tmp/app.yaml" ))
119119 .stdout ();
120120 }
121121
122+ /**
123+ * Returns the ingress address of the application
124+ * @return the ingress address
125+ */
126+ @ Function
127+ public String getIngress (String clusterName , Secret awsAccessKeyId , Secret awsSecretAccessKey ,
128+ @ Default ("eu-west-1" ) String region )
129+ throws ExecutionException , DaggerQueryException , InterruptedException {
130+ String host = kubectl (clusterName , region , awsAccessKeyId , awsSecretAccessKey )
131+ .withExec (List .of ("kubectl" , "-n" , "devoxxfr-dagger" , "get" , "ingress" , "-o" , "jsonpath={.items[0].status.loadBalancer.ingress[0].hostname}" ))
132+ .stdout ();
133+ return "http://%s" .formatted (host );
134+ }
135+
122136 /** Build a ready-to-use development environment */
123137 private Container buildEnv (Directory source ) {
124- CacheVolume mavenCache = dag .cacheVolume ("m2" );
125- return dag
138+ CacheVolume mavenCache = dag () .cacheVolume ("m2" );
139+ return dag ()
126140 .container ()
127141 .from ("maven:3-eclipse-temurin-21" )
128142 .withDirectory ("/src" , source )
0 commit comments