io.specmesh.cli.Provision Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2023 SpecMesh Contributors (https://github.com/specmesh)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.specmesh.cli;
import static picocli.CommandLine.Command;
import com.google.common.annotations.VisibleForTesting;
import io.specmesh.kafka.provision.Provisioner;
import io.specmesh.kafka.provision.Status;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Callable;
import picocli.CommandLine;
import picocli.CommandLine.Option;
/** SpecMesh Kafka Provisioner */
@SuppressWarnings("unused")
@Command(
name = "provision",
description =
"Apply a specification.yaml to provision kafka resources on a cluster.\n"
+ "Use 'provision.properties' for common arguments\n"
+ " Explicit properties file location /app/provision.properties\n\n")
public final class Provision implements Callable {
private final Provisioner.ProvisionerBuilder builder = Provisioner.builder();
@VisibleForTesting
Provision() {}
/**
* Main method
*
* @param args args
*/
public static void main(final String[] args) {
final var properties = new Properties();
final var propertyFilename =
System.getProperty("provision.properties", "provision.properties");
try (FileInputStream fis = new FileInputStream(propertyFilename)) {
System.out.println(
"Loading `"
+ propertyFilename
+ "` from:"
+ new File(propertyFilename).getAbsolutePath());
properties.load(fis);
properties.forEach(
(key, value) -> properties.put(key.toString().replace(".", "-"), value));
System.out.println(
"Loaded `properties` from cwd:" + new File(propertyFilename).getAbsolutePath());
} catch (IOException e) {
System.out.println(
"Missing `"
+ propertyFilename
+ " ` FROM:"
+ new File(propertyFilename).getAbsolutePath()
+ "\nERROR:"
+ e);
throw new RuntimeException(e);
}
final var provider = new CommandLine.PropertiesDefaultProvider(properties);
System.exit(
new CommandLine(new Provision()).setDefaultValueProvider(provider).execute(args));
}
@Option(
names = {"-bs", "--bootstrap-server"},
description = "Kafka bootstrap server url")
public void brokerUrl(final String brokerUrl) {
builder.brokerUrl(brokerUrl);
}
@Option(
names = {"-srDisabled", "--sr-disabled"},
description = "Ignore schema related operations")
public void srDisabled(final boolean disable) {
builder.srDisabled(disable);
}
@Option(
names = {"-aclDisabled", "--acl-disabled"},
description = "Ignore ACL related operations")
public void aclDisabled(final boolean disable) {
builder.aclDisabled(disable);
}
@Option(
names = {"-sr", "--schema-registry"},
description = "schemaRegistryUrl")
public void schemaRegistryUrl(final String url) {
builder.schemaRegistryUrl(url);
}
@Option(
names = {"-srKey", "--sr-api-key"},
description = "srApiKey for schema registry")
public void srApiKey(final String key) {
builder.srApiKey(key);
}
@Option(
names = {"-srSecret", "--sr-api-secret"},
description = "srApiSecret for schema secret")
public void srApiSecret(final String secret) {
builder.srApiSecret(secret);
}
@Option(
names = {"-schemaPath", "--schema-path"},
description = "schemaPath where the set of referenced schemas will be loaded")
public void schemaPath(final String path) {
builder.schemaPath(path);
}
@Option(
names = {"-spec", "--spec"},
description = "specmesh specification file")
public void spec(final String path) {
builder.specPath(path);
}
@Option(
names = {"-du", "--domain-user"},
description =
"optional custom domain user, to be used when creating ACLs. By default,"
+ " specmesh expects the principle used to authenticate with Kafka to have"
+ " the same name as the domain id. For example, given a domain id of"
+ " 'urn:acme.products', specmesh expects the user to be called"
+ " 'acme.products', and creates ACLs accordingly. In some situations, e.g."
+ " Confluent Cloud Service Accounts, the username is system generated or"
+ " outside control of administrators. In these situations, use this"
+ " option to provide the generated username and specmesh will provision"
+ " ACLs accordingly.")
public void domainUserAlias(final String alias) {
builder.domainUserAlias(alias);
}
@Option(
names = {"-u", "--username"},
description = "username or api key for the Kafka cluster connection")
public void username(final String username) {
builder.username(username);
}
@Option(
names = {"-s", "--secret"},
description = "secret credential for the Kafka cluster connection")
public void secret(final String secret) {
builder.secret(secret);
}
@Option(
names = {"-dry", "--dry-run"},
fallbackValue = "false",
description =
"Compares the cluster resources against the spec, outputting proposed changes"
+ " if compatible. If the spec incompatible with the cluster then will"
+ " fail with a descriptive error message. A return value of '0' ="
+ " indicates no changes needed; '1' = changes needed; '-1' not"
+ " compatible")
public void dryRun(final boolean enabled) {
builder.dryRun(enabled);
}
@Option(
names = {"-clean", "--clean-unspecified"},
fallbackValue = "false",
description =
"Compares the cluster resources against the spec, outputting proposed set of"
+ " resources that are unexpected (not specified). Use with '-dry-run' for"
+ " non-destructive checks. This operation will not create resources, it"
+ " will only remove unspecified resources")
public void cleanUnspecified(final boolean enabled) {
builder.cleanUnspecified(enabled);
}
@Option(
names = {"-D", "--property"},
mapFallbackValue = "",
description = "Specify Java runtime properties for Apache Kafka." + " ") // allow -Dkey
void setProperty(final Map props) {
props.forEach(System::setProperty);
}
public Integer call() {
final Status status = builder.build().provision();
System.out.println(status.toString());
return status.failed() ? 1 : 0;
}
@VisibleForTesting
Status run() {
return builder.build().provision();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy