Skip to content

Commit

Permalink
feat(crd-generator): Add CRD-Generator CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
baloo42 committed May 3, 2024
1 parent 6399eb3 commit 69ea042
Show file tree
Hide file tree
Showing 7 changed files with 347 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright (C) 2015 Red Hat, Inc.
*
* 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.fabric8.crd.generator.cli;

import io.fabric8.crd.generator.collector.CustomResourceCollector;
import io.fabric8.crdv2.generator.CRDGenerationInfo;
import io.fabric8.crdv2.generator.CRDGenerator;
import io.fabric8.crdv2.generator.CustomResourceInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import picocli.CommandLine;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;

@CommandLine.Command(name = "crd-gen", mixinStandardHelpOptions = true, helpCommand = true, versionProvider = KubernetesClientVersionProvider.class)
public class CRDGeneratorCLI implements Runnable {

private static final Logger log = LoggerFactory.getLogger(CustomResourceCollector.class);
private static final CRDGenerationInfo EMPTY_INFO = new CRDGenerationInfo();

@CommandLine.Spec
CommandLine.Model.CommandSpec spec;

@CommandLine.Option(names = { "-c",
"--classes" }, description = "Directories or JAR files to be used to scan for Custom Resource classes")
List<File> classesToIndex;

@CommandLine.Option(names = { "-cr",
"--custom-resource" }, description = "Custom Resource classes, which should be considered to generate the CRDs. If set, scanning is disabled.")
List<String> customResourceClasses;

@CommandLine.Option(names = { "-cp", "--classpath" }, description = "The classpath which be used during the CRD generation")
List<String> classpaths = new ArrayList<>();

@CommandLine.Option(names = { "-o", "--output-dir" }, description = "The output directory for the generated CRDs")
File outputDirectory = new File(".");

@CommandLine.Option(names = { "-f",
"--force-index" }, description = "If true, a Jandex index will be created even if the directory or JAR file contains an existing index.", defaultValue = "false")
Boolean forceIndex;

@CommandLine.Option(names = { "-p", "--parallel" }, description = "Enable parallel generation", defaultValue = "true")
Boolean parallel;

@CommandLine.Option(names = {
"--implicit-preserve-unknown-fields" }, description = "If enabled, all objects are implicitly marked with x-kubernetes-preserve-unknown-fields: true.", defaultValue = "false")
Boolean implicitPreserveUnknownFields;

private CRDGenerationInfo crdGenerationInfo = EMPTY_INFO;

@Override
public void run() {
CustomResourceCollector customResourceCollector = new CustomResourceCollector()
.withParentClassLoader(Thread.currentThread().getContextClassLoader())
.withClasspaths(classpaths)
.withFilesToIndex(classesToIndex)
.withForceIndex(forceIndex)
// TODO: allow to exclude / include
/*
* .withIncludePackages(inclusions.getPackages())
* .withIncludeGroups(inclusions.getGroups())
* .withIncludeVersions(inclusions.getVersions())
* .withExcludePackages(exclusions.getPackages())
* .withExcludeGroups(exclusions.getGroups())
* .withExcludeVersions(exclusions.getVersions())
*/
.withCustomResourceClasses(customResourceClasses);

CustomResourceInfo[] customResourceInfos = customResourceCollector.findCustomResources();

log.info("Found {} CustomResources", customResourceInfos.length);

try {
Files.createDirectories(outputDirectory.toPath());
} catch (IOException e) {
throw new RuntimeException("Could not create output directory: " + e.getMessage());
}

CRDGenerator crdGenerator = new CRDGenerator()
.customResources(customResourceInfos)
.withParallelGenerationEnabled(parallel)
.withImplicitPreserveUnknownFields(implicitPreserveUnknownFields)
.inOutputDir(outputDirectory);

crdGenerationInfo = crdGenerator.detailedGenerate();
crdGenerationInfo.getCRDDetailsPerNameAndVersion().forEach((crdName, versionToInfo) -> {
log.info("Generated CRD {}:", crdName);
versionToInfo.forEach(
(version, info) -> log.info(" {} -> {}", version, info.getFilePath()));
});
}

public CRDGenerationInfo getCrdGenerationInfo() {
return crdGenerationInfo;
}

public static void main(String[] args) {
int exitCode = new CommandLine(new CRDGeneratorCLI()).execute(args);
System.exit(exitCode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2015 Red Hat, Inc.
*
* 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.fabric8.crd.generator.cli;

import io.fabric8.kubernetes.client.Version;
import picocli.CommandLine;

public class KubernetesClientVersionProvider implements CommandLine.IVersionProvider {
@Override
public String[] getVersion() throws Exception {
return new String[] { Version.clientVersion() };
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright (C) 2015 Red Hat, Inc.
*
* 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.fabric8.crd.generator.cli;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import picocli.CommandLine;

import java.nio.file.Path;
import java.nio.file.Paths;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class CRDGeneratorCLITest {

@Test
public void givenNoInput_thenGenerateNoCRDs() {
CRDGeneratorCLI cliApp = new CRDGeneratorCLI();
CommandLine cmd = new CommandLine(cliApp);
int exitCode = cmd.execute();
assertEquals(0, exitCode);
assertEquals(0, cliApp.getCrdGenerationInfo().numberOfGeneratedCRDs());
}

@Test
public void givenSingleCRClassNameFromSameClasspath_thenGenerate(@TempDir Path tempDir) {
CRDGeneratorCLI cliApp = new CRDGeneratorCLI();
CommandLine cmd = new CommandLine(cliApp);
String[] args = new String[] {
"-cr", "io.fabric8.crd.generator.cli.examples.basic.Basic",
"-o", tempDir.toString()
};
int exitCode = cmd.execute(args);
assertEquals(0, exitCode);
assertEquals(1, cliApp.getCrdGenerationInfo().numberOfGeneratedCRDs());
assertTrue(Paths.get(tempDir.toString(), "basics.sample.fabric8.io-v1.yml").toFile().exists());
}

@Test
public void givenSingleCRClassNameFromExternalClasspath_thenGenerate(@TempDir Path tempDir) {
CRDGeneratorCLI cliApp = new CRDGeneratorCLI();
CommandLine cmd = new CommandLine(cliApp);
String[] args = new String[] {
"-cp", "../api-v2/target/test-classes/",
"-cr", "io.fabric8.crdv2.example.basic.Basic",
"-o", tempDir.toString()
};

int exitCode = cmd.execute(args);
assertEquals(0, exitCode);
assertEquals(1, cliApp.getCrdGenerationInfo().numberOfGeneratedCRDs());
assertTrue(Paths.get(tempDir.toString(), "basics.sample.fabric8.io-v1.yml").toFile().exists());
}

@Test
public void givenClassesDirectory_thenScanAndGenerate(@TempDir Path tempDir) {
CRDGeneratorCLI cliApp = new CRDGeneratorCLI();
CommandLine cmd = new CommandLine(cliApp);
String[] args = new String[] {
"-c", "target/test-classes/",
//"-k", "basics.sample.fabric8.io",
"-o", tempDir.toString()
};

int exitCode = cmd.execute(args);
assertEquals(0, exitCode);
assertEquals(1, cliApp.getCrdGenerationInfo().numberOfGeneratedCRDs());
assertTrue(Paths.get(tempDir.toString(), "basics.sample.fabric8.io-v1.yml").toFile().exists());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2015 Red Hat, Inc.
*
* 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.fabric8.crd.generator.cli.examples.basic;

import io.fabric8.kubernetes.api.model.Namespaced;
import io.fabric8.kubernetes.client.CustomResource;
import io.fabric8.kubernetes.model.annotation.Group;
import io.fabric8.kubernetes.model.annotation.Version;

@Group("sample.fabric8.io")
@Version("v1alpha1")
public class Basic extends CustomResource<BasicSpec, BasicStatus> implements Namespaced {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (C) 2015 Red Hat, Inc.
*
* 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.fabric8.crd.generator.cli.examples.basic;

import com.fasterxml.jackson.annotation.JsonIgnore;

public class BasicSpec {
private int myInt;

public int getMyInt() {
return myInt;
}

public void setMyInt(int myInt) {
this.myInt = myInt;
}

private long myLong;

public long getMyLong() {
return myLong;
}

public void setMyLong(long myLong) {
this.myLong = myLong;
}

private double myDouble;

public double getMyDouble() {
return myDouble;
}

public void setMyDouble(long myDouble) {
this.myDouble = myDouble;
}

private float myFloat;

public float getMyFloat() {
return myFloat;
}

public void setMyFloat(long myFloat) {
this.myFloat = myFloat;
}

@JsonIgnore
public Class<?> clazz;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2015 Red Hat, Inc.
*
* 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.fabric8.crd.generator.cli.examples.basic;

public class BasicStatus {
private String message;

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}
}
1 change: 1 addition & 0 deletions crd-generator/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
<module>api</module>
<module>api-v2</module>
<module>collector</module>
<module>cli</module>
<module>maven-plugin</module>
<module>test</module>
</modules>
Expand Down

0 comments on commit 69ea042

Please sign in to comment.