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

View file

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