Initial toolchain for Quarkus distribution documentation

Closes #9054
This commit is contained in:
stianst 2021-11-18 13:40:02 +01:00 committed by Pedro Igor
parent fc237a8b63
commit c7134fd539
17 changed files with 587 additions and 3 deletions

88
docs/guides/pom.xml Normal file
View file

@ -0,0 +1,88 @@
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-docs-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>16.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<name>Keycloak Guides</name>
<artifactId>keycloak-guides</artifactId>
<description>Keycloak Guides</description>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-guides-maven-plugin</artifactId>
<version>16.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-guides-maven-plugin</artifactId>
<executions>
<execution>
<id>generate-asciidoc</id>
<goals>
<goal>keycloak-guide</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>1.5.5</version>
<executions>
<execution>
<id>asciidoc-to-html</id>
<phase>generate-resources</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<sourceDirectory>${basedir}/target/generated-guides/server</sourceDirectory>
<sourceDocumentName>index.adoc</sourceDocumentName>
<backend>html5</backend>
<sourceHighlighter>coderay</sourceHighlighter>
<attributes>
<imagesdir>./</imagesdir>
<toc>left</toc>
<toc>left</toc>
<icons>font</icons>
<sectanchors>true</sectanchors>
<idprefix/>
<idseparator>-</idseparator>
<docinfo1>true</docinfo1>
</attributes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,27 @@
<#import "/templates/guide.adoc" as template>
<@template.guide
title="All configuration"
summary="All the configuration you will ever need and want">
<#list ctx.options.categories as category>
<#assign categoryOptions=ctx.options.getValues(category)>
<#if categoryOptions?has_content>
== ${category.heading}
|===
|Key|CLI|ENV|Description|Default|Values
<#list categoryOptions as option>
|${option.key}
|${option.keyCli}
|${option.keyEnv}
|${option.description}
|${option.defaultValue!}
|${option.expectedValues?join(", ")}
<#if option?has_next>
</#if>
</#list>
|===
</#if>
</#list>
</@template.guide>

View file

@ -0,0 +1,23 @@
<#import "/templates/guide.adoc" as tmpl>
<#import "/templates/kc.adoc" as kc>
<#import "/templates/options.adoc" as opts>
<@tmpl.guide
title="Relational database setup"
summary="Understand how to configure different relational databases for Keycloak"
includedOptions="db db.* hostname">
First step is to decide which database vendor you are going to use. Keycloak has support for a number of different vendors.
Selecting the database vendor is done at build-time rather than at runtime. To select the database vendor run:
<@kc.build parameters="--db <vendor>"/>
Valid options for database vendors include:
<@opts.expectedValues option="db"/>
Once configured you can easily connect to the database with:
<@kc.start parameters="--db-host <hostname> --db-schema <schema> --db-user <username> --db-password <password>"/>
</@tmpl.guide>

View file

@ -0,0 +1,5 @@
= Keycloak server guide
<#list ctx.serverGuides as guide>
include::${guide}[leveloffset=+1]
</#list>

View file

@ -0,0 +1,30 @@
<#macro guide title summary includedOptions="">
:title: ${title}
:summary: ${summary}
[[${ctx.getAnchor(title)}]]
= {title}
{summary}
<#nested>
<#if includedOptions?has_content>
== Relevant options
|===
|Key|CLI|ENV|Description|Default|Values
<#list ctx.options.getOptions(includedOptions) as option>
|${option.key}
|${option.keyCli}
|${option.keyEnv}
|${option.description}
|${option.defaultValue!}
|${option.expectedValues?join(", ")}
<#if option?has_next>
</#if>
</#list>
|===
</#if>
</#macro>

View file

@ -0,0 +1,13 @@
<#macro build parameters>
[source,bash]
----
bin/kc.[sh|bat] build ${parameters}
----
</#macro>
<#macro start parameters>
[source,bash]
----
bin/kc.[sh|bat] start ${parameters}
----
</#macro>

View file

@ -0,0 +1,5 @@
<#macro expectedValues option>
<#list ctx.options.getOption(option).expectedValues as expectedValue>
* ${expectedValue}
</#list>
</#macro>

View file

@ -0,0 +1,22 @@
package org.keycloak.guides;
import freemarker.template.TemplateException;
import org.keycloak.guides.maven.GuideBuilder;
import java.io.File;
import java.io.IOException;
public class DocsBuildDebugUtil {
public static void main(String[] args) throws IOException, TemplateException {
String userDir = System.getProperty("user.dir");
File usrDir = new File(System.getProperty("user.dir"));
File srcDir = usrDir.toPath().resolve("docs/guides/src/main").toFile();
File targetDir = usrDir.toPath().resolve("target/generated-guides-tests").toFile();
targetDir.mkdirs();
GuideBuilder builder = new GuideBuilder(srcDir, targetDir, null);
builder.server();
System.out.println("Guides generated to: " + targetDir.getAbsolutePath().toString());
}
}

86
docs/maven-plugin/pom.xml Normal file
View file

@ -0,0 +1,86 @@
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-docs-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>16.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<name>Keycloak Guides Maven Plugin</name>
<artifactId>keycloak-guides-maven-plugin</artifactId>
<description>Keycloak Guides Maven Plugin</description>
<packaging>maven-plugin</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-bom</artifactId>
<version>${quarkus.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.6.3</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.6.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-quarkus-server</artifactId>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core</artifactId>
</dependency>
<dependency>
<groupId>io.smallrye.config</groupId>
<artifactId>smallrye-config</artifactId>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
</dependencies>
</project>

View file

@ -0,0 +1,29 @@
package org.keycloak.guides.maven;
import java.io.File;
public class Context {
private File srcDir;
private Options options;
private String[] serverGuides;
public Context(File srcDir) {
this.srcDir = srcDir;
this.options = new Options();
this.serverGuides = new File(srcDir, "server").list((dir, f) -> f.endsWith(".adoc") && !f.equals("index.adoc"));
}
public String getAnchor(String title) {
return title.toLowerCase().replace(' ', '_');
}
public Options getOptions() {
return options;
}
public String[] getServerGuides() {
return new File(srcDir, "server").list((dir, f) -> f.endsWith(".adoc") && !f.equals("index.adoc"));
}
}

View file

@ -0,0 +1,44 @@
package org.keycloak.guides.maven;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Map;
public class FreeMarker {
private File targetDir;
private Map<String, Object> attributes;
private Configuration configuration;
public FreeMarker(File srcDir, File targetDir, Map<String, Object> attributes) throws IOException {
this.targetDir = targetDir;
this.attributes = attributes;
configuration = new Configuration(Configuration.VERSION_2_3_31);
configuration.setDirectoryForTemplateLoading(srcDir);
configuration.setDefaultEncoding("UTF-8");
configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
configuration.setLogTemplateExceptions(false);
}
public void template(String template) throws IOException, TemplateException {
Template t = configuration.getTemplate(template);
File out = targetDir.toPath().resolve(template).toFile();
File parent = out.getParentFile();
if (!parent.isDirectory()) {
parent.mkdir();
}
Writer w = new FileWriter(out);
t.process(attributes, w);
}
}

View file

@ -0,0 +1,43 @@
package org.keycloak.guides.maven;
import freemarker.template.TemplateException;
import org.apache.maven.plugin.logging.Log;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class GuideBuilder {
private final FreeMarker freeMarker;
private final File srcDir;
private final File targetDir;
private final Log log;
public GuideBuilder(File srcDir, File targetDir, Log log) throws IOException {
this.srcDir = srcDir;
this.targetDir = targetDir;
this.log = log;
Map<String, Object> globalAttributes = new HashMap<>();
globalAttributes.put("ctx", new Context(srcDir));
this.freeMarker = new FreeMarker(srcDir, targetDir, globalAttributes);
}
public void server() throws TemplateException, IOException {
File serverGuidesDir = new File(srcDir, "server");
if (!serverGuidesDir.isDirectory()) {
serverGuidesDir.mkdir();
}
for (String t : serverGuidesDir.list((dir, name) -> name.endsWith(".adoc"))) {
freeMarker.template("server/" + t);
if (log != null) {
log.info("Templated: server/" + t);
}
}
}
}

View file

@ -0,0 +1,43 @@
package org.keycloak.guides.maven;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import java.io.File;
@Mojo(name = "keycloak-guide", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
public class GuideMojo extends AbstractMojo {
@Parameter(property = "project.build.sourceDirectory")
private String sourceDir;
@Parameter(property = "project.build.directory")
private String targetDir;
@Override
public void execute() throws MojoFailureException {
try {
Log log = getLog();
File srcDir = new File(sourceDir).getParentFile();
File targetDir = new File(this.targetDir, "generated-guides");
if (!targetDir.isDirectory()) {
targetDir.mkdirs();
}
log.info("Guide dir: " + srcDir.getAbsolutePath());
log.info("Target dir: " + targetDir.getAbsolutePath());
GuideBuilder g = new GuideBuilder(srcDir, targetDir, log);
g.server();
} catch (Exception e) {
e.printStackTrace();
throw new MojoFailureException("Failed to generated asciidoc files", e);
}
}
}

View file

@ -0,0 +1,91 @@
package org.keycloak.guides.maven;
import org.keycloak.quarkus.runtime.configuration.mappers.ConfigCategory;
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
public class Options {
private final Map<String, Option> options;
public Options() {
options = PropertyMappers.getMappers().stream()
.filter(m -> !m.isHidden())
.map(m -> new Option(m.getFrom(), m.getCategory(), m.isBuildTime(), m.getDescription(), m.getDefaultValue(), m.getExpectedValues()))
.collect(Collectors.toMap(Option::getKey, o -> o, (o1, o2) -> o1)); // Need to ignore duplicate keys??
}
public ConfigCategory[] getCategories() {
return ConfigCategory.values();
}
public Collection<Option> getValues() {
return options.values();
}
public Collection<Option> getValues(ConfigCategory category) {
return options.values().stream().filter(o -> o.category.equals(category)).collect(Collectors.toList());
}
public Option getOption(String key) {
return options.get(key);
}
public List<Option> getOptions(String includeOptions) {
final String r = includeOptions.replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*").replace(' ', '|');
return this.options.values().stream().filter(o -> o.getKey().matches(r)).collect(Collectors.toList());
}
public static class Option {
private String key;
private ConfigCategory category;
private boolean build;
private String description;
private String defaultValue;
private List<String> expectedValues;
public Option(String key, ConfigCategory category, boolean build, String description, String defaultValue, Iterable<String> expectedValues) {
this.key = key;
this.category = category;
this.build = build;
this.description = description;
this.defaultValue = defaultValue;
this.expectedValues = StreamSupport.stream(expectedValues.spliterator(), false).collect(Collectors.toList());
}
public boolean isBuild() {
return build;
}
public String getKey() {
return key.substring(3);
}
public String getKeyCli() {
return "--" + key.substring(3).replace('.', '-');
}
public String getKeyEnv() {
return key.toUpperCase().replace('.', '_').replace('-', '_');
}
public String getDescription() {
return description;
}
public String getDefaultValue() {
return defaultValue;
}
public List<String> getExpectedValues() {
return expectedValues;
}
}
}

36
docs/pom.xml Executable file
View file

@ -0,0 +1,36 @@
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>16.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<name>Keycloak Docs Parent</name>
<description/>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-docs-parent</artifactId>
<packaging>pom</packaging>
<modules>
<module>maven-plugin</module>
<module>guides</module>
</modules>
</project>

View file

@ -35,6 +35,7 @@
<packaging>pom</packaging>
<properties>
<quarkus.version>2.5.1.Final</quarkus.version>
<!--
Performing a Wildfly upgrade? Run the:
@ -262,6 +263,7 @@
<module>common</module>
<module>core</module>
<module>dependencies</module>
<module>docs</module>
<module>server-spi</module>
<module>server-spi-private</module>
<module>saml-core-api</module>

View file

@ -31,9 +31,6 @@
<packaging>pom</packaging>
<properties>
<!-- Quarkus version -->
<quarkus.version>2.5.1.Final</quarkus.version>
<!--
Override versions based on Quarkus dependencies.
Make sure to update these dependencies when Quarkus version changes.