Skip to content

Commit

Permalink
feat(core): cli command for update/create/delete single flow (#5410)
Browse files Browse the repository at this point in the history
close #747
  • Loading branch information
Skraye authored Oct 14, 2024
1 parent 46f8bef commit a47e293
Show file tree
Hide file tree
Showing 4 changed files with 241 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package io.kestra.cli.commands.flows;

import io.kestra.cli.AbstractApiCommand;
import io.kestra.cli.AbstractValidateCommand;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.MediaType;
import io.micronaut.http.MutableHttpRequest;
import io.micronaut.http.client.exceptions.HttpClientResponseException;
import io.micronaut.http.client.netty.DefaultHttpClient;
import lombok.extern.slf4j.Slf4j;
import picocli.CommandLine;

import java.nio.file.Files;
import java.nio.file.Path;

@CommandLine.Command(
name = "create",
description = "create a single flow",
mixinStandardHelpOptions = true
)
@Slf4j
public class FlowCreateCommand extends AbstractApiCommand {
@CommandLine.Parameters(index = "0", description = "the file containing the flow")
public Path flowFile;

@SuppressWarnings("deprecation")
@Override
public Integer call() throws Exception {
super.call();

checkFile();

String body = Files.readString(flowFile);

try(DefaultHttpClient client = client()) {
MutableHttpRequest<String> request = HttpRequest
.POST(apiUri("/flows"), body).contentType(MediaType.APPLICATION_YAML);

client.toBlocking().retrieve(
this.requestOptions(request),
String.class
);

stdOut("Flow successfully created !");
} catch (HttpClientResponseException e){
AbstractValidateCommand.handleHttpException(e, "flow");
return 1;
}


return 0;
}

protected void checkFile() {
if (!Files.isRegularFile(flowFile)) {
throw new IllegalArgumentException("The file '" + flowFile.toFile().getAbsolutePath() + "' is not a file");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package io.kestra.cli.commands.flows;

import io.kestra.cli.AbstractApiCommand;
import io.kestra.cli.AbstractValidateCommand;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.MutableHttpRequest;
import io.micronaut.http.client.exceptions.HttpClientResponseException;
import io.micronaut.http.client.netty.DefaultHttpClient;
import lombok.extern.slf4j.Slf4j;
import picocli.CommandLine;

@CommandLine.Command(
name = "create",
description = "create a single flow",
mixinStandardHelpOptions = true
)
@Slf4j
public class FlowDeleteCommand extends AbstractApiCommand {

@CommandLine.Parameters(index = "0", description = "the namespace of the flow")
public String namespace;

@CommandLine.Parameters(index = "1", description = "the id of the flow")
public String id;

@SuppressWarnings("deprecation")
@Override
public Integer call() throws Exception {
super.call();

try(DefaultHttpClient client = client()) {
MutableHttpRequest<String> request = HttpRequest
.DELETE(apiUri("/flows/" + namespace + "/" + id ));

client.toBlocking().exchange(
this.requestOptions(request)
);

stdOut("Flow successfully deleted !");
} catch (HttpClientResponseException e){
AbstractValidateCommand.handleHttpException(e, "flow");
return 1;
}

return 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package io.kestra.cli.commands.flows;

import io.kestra.cli.AbstractApiCommand;
import io.kestra.cli.AbstractValidateCommand;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.MediaType;
import io.micronaut.http.MutableHttpRequest;
import io.micronaut.http.client.exceptions.HttpClientResponseException;
import io.micronaut.http.client.netty.DefaultHttpClient;
import lombok.extern.slf4j.Slf4j;
import picocli.CommandLine;

import java.nio.file.Files;
import java.nio.file.Path;

@CommandLine.Command(
name = "update",
description = "update a single flow",
mixinStandardHelpOptions = true
)
@Slf4j
public class FlowUpdateCommand extends AbstractApiCommand {
@CommandLine.Parameters(index = "0", description = "the file containing the flow")
public Path flowFile;

@CommandLine.Parameters(index = "1", description = "the namespace of the flow")
public String namespace;

@CommandLine.Parameters(index = "2", description = "the id of the flow")
public String id;

@SuppressWarnings("deprecation")
@Override
public Integer call() throws Exception {
super.call();

checkFile();

String body = Files.readString(flowFile);

try(DefaultHttpClient client = client()) {
MutableHttpRequest<String> request = HttpRequest
.PUT(apiUri("/flows/" + namespace + "/" + id ), body).contentType(MediaType.APPLICATION_YAML);

client.toBlocking().retrieve(
this.requestOptions(request),
String.class
);

stdOut("Flow successfully updated !");
} catch (HttpClientResponseException e){
AbstractValidateCommand.handleHttpException(e, "flow");
return 1;
}

return 0;
}

protected void checkFile() {
if (!Files.isRegularFile(flowFile)) {
throw new IllegalArgumentException("The file '" + flowFile.toFile().getAbsolutePath() + "' is not a file");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package io.kestra.cli.commands.flows;

import io.micronaut.configuration.picocli.PicocliRunner;
import io.micronaut.context.ApplicationContext;
import io.micronaut.context.env.Environment;
import io.micronaut.runtime.server.EmbeddedServer;
import org.junit.jupiter.api.Test;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.net.URL;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.StringContains.containsString;

public class SingleFlowCommandsTest {


@Test
void all() {
URL flow = SingleFlowCommandsTest.class.getClassLoader().getResource("flows/quattro.yml");
ByteArrayOutputStream out = new ByteArrayOutputStream();
System.setOut(new PrintStream(out));

try (ApplicationContext ctx = ApplicationContext.run(Environment.CLI, Environment.TEST)) {

EmbeddedServer embeddedServer = ctx.getBean(EmbeddedServer.class);
embeddedServer.start();

String[] deleteArgs = {
"--server",
embeddedServer.getURL().toString(),
"--user",
"myuser:pass:word",
"io.kestra.outsider",
"quattro"
};
PicocliRunner.call(FlowDeleteCommand.class, ctx, deleteArgs);

assertThat(out.toString(), containsString("Flow successfully deleted !"));
out.reset();

String[] createArgs = {
"--server",
embeddedServer.getURL().toString(),
"--user",
"myuser:pass:word",
flow.getPath(),
};
PicocliRunner.call(FlowCreateCommand.class, ctx, createArgs);

assertThat(out.toString(), containsString("Flow successfully created !"));


out.reset();String[] updateArgs = {
"--server",
embeddedServer.getURL().toString(),
"--user",
"myuser:pass:word",
flow.getPath(),
"io.kestra.outsider",
"quattro"
};
PicocliRunner.call(FlowUpdateCommand.class, ctx, updateArgs);

assertThat(out.toString(), containsString("Flow successfully updated !"));
out.reset();
}
}

}

0 comments on commit a47e293

Please sign in to comment.