Skip to content

Commit c6eae51

Browse files
authored
Merge pull request #35372 from vespa-engine/arnej/generate-and-use-new-doctype-config
generate and use new doctype config
2 parents c25dc2f + d1e06ad commit c6eae51

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2645
-2137
lines changed

config-model/src/main/sh/derive.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env bash
2+
if [ $# != 2 ]; then
3+
echo 'needs 2 arguments: <sd/dir> <outputdir>'
4+
exit 1
5+
fi
6+
7+
# ensure absolute paths:
8+
old_dir=$(pwd)
9+
if [ "$1" = "${1#/}" ]; then set "${old_dir}/$1" "$2"; fi
10+
if [ "$2" = "${2#/}" ]; then set "$1" "${old_dir}/$2"; fi
11+
12+
# assumes you have your vespa checked out and built in ~/git/vespa :
13+
cd ~/git/vespa/config-model
14+
15+
mvn -q exec:java \
16+
-Dexec.args="$*" \
17+
-Dexec.classpathScope="test" \
18+
-Dexec.mainClass=com.yahoo.schema.derived.DeriveConfigFromSchema
19+
20+
echo "Files generated in directory $2:"
21+
ls -l "$2"
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
2+
package com.yahoo.schema.derived;
3+
4+
import com.yahoo.config.application.api.DeployLogger;
5+
import com.yahoo.config.model.application.provider.MockFileRegistry;
6+
import com.yahoo.config.model.deploy.DeployState;
7+
import com.yahoo.config.model.deploy.TestProperties;
8+
import com.yahoo.document.config.DocumentmanagerConfig;
9+
import com.yahoo.document.config.DocumenttypesConfig;
10+
import com.yahoo.io.IOUtils;
11+
import com.yahoo.schema.ApplicationBuilder;
12+
import com.yahoo.schema.Schema;
13+
import com.yahoo.schema.parser.ParseException;
14+
import com.yahoo.vespa.configmodel.producers.DocumentManager;
15+
import com.yahoo.vespa.configmodel.producers.DocumentTypes;
16+
17+
import java.io.File;
18+
import java.io.IOException;
19+
import java.nio.file.Path;
20+
import java.util.logging.Level;
21+
import java.util.logging.Logger;
22+
23+
/**
24+
* Standalone tool to derive Vespa configuration files from a schema (.sd) file.
25+
* Usage: DeriveConfigFromSchema <schema-file.sd> [output-dir]
26+
* @author arnej
27+
*/
28+
public class DeriveConfigFromSchema {
29+
30+
private static final Logger log = Logger.getLogger(DeriveConfigFromSchema.class.getName());
31+
32+
private static class SimpleDeployLogger implements DeployLogger {
33+
@Override
34+
public void log(Level level, String message) {
35+
System.err.println(level + ": " + message);
36+
}
37+
}
38+
39+
/**
40+
* Derive configuration from a single schema file or directory of schema files.
41+
*
42+
* @param schemaPath path to the .sd file or directory containing .sd files
43+
* @param outputDir directory where config files will be written
44+
* @throws IOException if file operations fail
45+
* @throws ParseException if schema parsing fails
46+
*/
47+
public static void deriveFromFile(String schemaPath, String outputDir) throws IOException, ParseException {
48+
File input = new File(schemaPath);
49+
if (!input.exists()) {
50+
throw new IOException("Schema file or directory not found: " + schemaPath);
51+
}
52+
53+
if (input.isDirectory()) {
54+
deriveFromDirectory(schemaPath, outputDir);
55+
} else {
56+
deriveFromSingleFile(schemaPath, outputDir);
57+
}
58+
}
59+
60+
private static void deriveFromSingleFile(String schemaFile, String outputDir) throws IOException, ParseException {
61+
File schema = new File(schemaFile);
62+
if (!schema.getName().endsWith(".sd")) {
63+
throw new IOException("Schema file must have .sd extension: " + schemaFile);
64+
}
65+
66+
// Create output directory
67+
File outDir = new File(outputDir);
68+
outDir.mkdirs();
69+
70+
System.out.println("Processing schema: " + schemaFile);
71+
System.out.println("Output directory: " + outputDir);
72+
73+
DeployLogger logger = new SimpleDeployLogger();
74+
TestProperties properties = new TestProperties();
75+
76+
// Build the application from the schema file
77+
ApplicationBuilder builder = new ApplicationBuilder(logger);
78+
builder.addSchemaFile(schemaFile);
79+
builder.build(true);
80+
81+
// Get the schema (there should be only one)
82+
Schema schema_obj = builder.getSchema();
83+
String schemaName = schema_obj.getName();
84+
System.out.println("Schema name: " + schemaName);
85+
86+
// Create derived configuration
87+
DerivedConfiguration config = new DerivedConfiguration(
88+
new DeployState.Builder()
89+
.properties(properties)
90+
.deployLogger(logger)
91+
.rankProfileRegistry(builder.getRankProfileRegistry())
92+
.queryProfiles(builder.getQueryProfileRegistry())
93+
.build(),
94+
builder.getSchema(schemaName),
95+
SchemaInfo.IndexMode.INDEX
96+
);
97+
98+
// Export all configuration files
99+
exportConfiguration(builder, config, outputDir);
100+
101+
System.out.println("\nSuccessfully generated configuration files in: " + outputDir);
102+
}
103+
104+
/**
105+
* Derive configuration from all schema files in a directory.
106+
* All schemas are loaded together (allowing inheritance between them),
107+
* and configs are generated for each schema in separate subdirectories.
108+
*/
109+
private static void deriveFromDirectory(String schemaDir, String outputDir) throws IOException, ParseException {
110+
File dir = new File(schemaDir);
111+
112+
// Find all .sd files in the directory
113+
File[] schemaFiles = dir.listFiles((d, name) -> name.endsWith(".sd"));
114+
if (schemaFiles == null || schemaFiles.length == 0) {
115+
throw new IOException("No .sd files found in directory: " + schemaDir);
116+
}
117+
118+
System.out.println("Processing directory: " + schemaDir);
119+
System.out.println("Found " + schemaFiles.length + " schema file(s)");
120+
System.out.println("Output directory: " + outputDir);
121+
122+
DeployLogger logger = new SimpleDeployLogger();
123+
TestProperties properties = new TestProperties();
124+
125+
// Build the application from all schema files (so inheritance works)
126+
ApplicationBuilder builder = new ApplicationBuilder(logger);
127+
for (File schemaFile : schemaFiles) {
128+
System.out.println(" Loading: " + schemaFile.getName());
129+
builder.addSchemaFile(schemaFile.getAbsolutePath());
130+
}
131+
builder.build(true);
132+
133+
System.out.println("\nGenerating configurations for " +
134+
builder.application().schemas().size() +
135+
" schema(s)");
136+
137+
// Generate configs for each schema
138+
for (Schema schema : builder.application().schemas().values()) {
139+
String schemaName = schema.getName();
140+
String schemaOutputDir = outputDir + "/" + schemaName;
141+
142+
System.out.println("\n--- Processing schema: " + schemaName + " ---");
143+
144+
// Create output directory for this schema
145+
File outDir = new File(schemaOutputDir);
146+
outDir.mkdirs();
147+
148+
// Create derived configuration
149+
DerivedConfiguration config = new DerivedConfiguration(
150+
new DeployState.Builder()
151+
.properties(properties)
152+
.deployLogger(logger)
153+
.rankProfileRegistry(builder.getRankProfileRegistry())
154+
.queryProfiles(builder.getQueryProfileRegistry())
155+
.build(),
156+
schema,
157+
SchemaInfo.IndexMode.INDEX
158+
);
159+
160+
// Export all configuration files
161+
exportConfiguration(builder, config, schemaOutputDir);
162+
System.out.println("Generated in: " + schemaOutputDir);
163+
}
164+
165+
System.out.println("\n✓ Successfully processed all schemas in: " + schemaDir);
166+
}
167+
168+
private static void exportConfiguration(ApplicationBuilder builder,
169+
DerivedConfiguration config,
170+
String outputDir) throws IOException {
171+
// Export the main derived configuration files
172+
config.export(outputDir);
173+
174+
// Export document manager config
175+
DocumentmanagerConfig.Builder docManagerBuilder = new DocumentmanagerConfig.Builder();
176+
new DocumentManager().produce(builder.getModel(), docManagerBuilder);
177+
DocumentmanagerConfig docManagerConfig = docManagerBuilder.build();
178+
String docManagerCfg = docManagerConfig.toString();
179+
writeConfigFile(outputDir, "documentmanager.cfg", docManagerCfg);
180+
181+
// Export document types config
182+
DocumenttypesConfig.Builder docTypesBuilder = new DocumenttypesConfig.Builder();
183+
new DocumentTypes().produce(builder.getModel(), docTypesBuilder);
184+
DocumenttypesConfig docTypesConfig = docTypesBuilder.build();
185+
String docTypesCfg = docTypesConfig.toString();
186+
writeConfigFile(outputDir, "documenttypes.cfg", docTypesCfg);
187+
188+
// Export query profiles
189+
DerivedConfiguration.exportQueryProfiles(builder.getQueryProfileRegistry(), outputDir);
190+
191+
// Export constants and ONNX models
192+
config.exportConstants(outputDir);
193+
config.exportOnnxModels(outputDir);
194+
195+
System.out.println("\nGenerated configuration files:");
196+
listGeneratedFiles(new File(outputDir));
197+
}
198+
199+
private static void writeConfigFile(String dir, String filename, String content) throws IOException {
200+
String path = dir + "/" + filename;
201+
IOUtils.writeFile(path, content, false);
202+
if (!content.endsWith("\n")) {
203+
IOUtils.writeFile(path, "\n", true);
204+
}
205+
}
206+
207+
private static void listGeneratedFiles(File dir) {
208+
File[] files = dir.listFiles();
209+
if (files == null) return;
210+
211+
for (File file : files) {
212+
if (file.isFile()) {
213+
System.out.println(" - " + file.getName());
214+
}
215+
}
216+
}
217+
218+
public static void main(String[] args) {
219+
if (args.length < 1) {
220+
System.err.println("Usage: DeriveConfigFromSchema <schema-file.sd | schema-dir> [output-dir]");
221+
System.err.println();
222+
System.err.println("Arguments:");
223+
System.err.println(" <schema-file.sd> Path to a Vespa schema file to process");
224+
System.err.println(" <schema-dir> Path to a directory containing .sd files");
225+
System.err.println(" (all schemas loaded together for inheritance support)");
226+
System.err.println(" [output-dir] Optional output directory (default: ./derived-config)");
227+
System.err.println();
228+
System.err.println("When a directory is provided:");
229+
System.err.println(" - All .sd files are loaded together (inheritance works)");
230+
System.err.println(" - Configs for each schema are generated in separate subdirectories");
231+
System.err.println();
232+
System.err.println("Examples:");
233+
System.err.println(" DeriveConfigFromSchema my-schema.sd");
234+
System.err.println(" DeriveConfigFromSchema /path/to/schema.sd /output/path");
235+
System.err.println(" DeriveConfigFromSchema /path/to/schemas/ /output/path");
236+
System.exit(1);
237+
}
238+
239+
String schemaPath = args[0];
240+
String outputDir = args.length > 1 ? args[1] : "./derived-config";
241+
242+
try {
243+
deriveFromFile(schemaPath, outputDir);
244+
} catch (IOException e) {
245+
System.err.println("ERROR: I/O error: " + e.getMessage());
246+
e.printStackTrace();
247+
System.exit(1);
248+
} catch (ParseException e) {
249+
System.err.println("ERROR: Failed to parse schema: " + e.getMessage());
250+
e.printStackTrace();
251+
System.exit(1);
252+
} catch (Exception e) {
253+
System.err.println("ERROR: Unexpected error: " + e.getMessage());
254+
e.printStackTrace();
255+
System.exit(1);
256+
}
257+
}
258+
}
0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)