@@ -667,6 +667,8 @@ public:
667
667
" run the server" )
668
668
.addSubCommand (" compile" , KJ_BIND_METHOD (*this , getCompile),
669
669
" create a self-contained binary" )
670
+ .addSubCommand (" measure" , KJ_BIND_METHOD (*this , getMeasure),
671
+ " measure the provided worker configuration" )
670
672
.addSubCommand (" test" , KJ_BIND_METHOD (*this , getTest),
671
673
" run unit tests" )
672
674
.build ();
@@ -679,7 +681,13 @@ public:
679
681
auto builder = kj::MainBuilder (context, getVersionString (),
680
682
" Serve requests based on the compiled config." ,
681
683
" This binary has an embedded configuration." );
682
- return addServeOptions (builder);
684
+ return kj::MainBuilder (context, getVersionString (),
685
+ " Runs the Workers JavaScript/Wasm runtime." )
686
+ .addSubCommand (" serve" , KJ_BIND_METHOD (*this , getServeFromEmbeddedConfig),
687
+ " run the server" )
688
+ .addSubCommand (" measure" , KJ_BIND_METHOD (*this , getMeasure),
689
+ " measure the provided worker configuration" )
690
+ .build ();
683
691
}
684
692
}
685
693
@@ -742,10 +750,19 @@ public:
742
750
}
743
751
744
752
kj::MainFunc getServe () {
745
- auto builder = kj::MainBuilder (context, getVersionString (),
753
+ auto builder = getServeBuilder ();
754
+ return addServeOptions (addConfigParsingOptions (builder));
755
+ }
756
+
757
+ kj::MainFunc getServeFromEmbeddedConfig () {
758
+ auto builder = getServeBuilder ();
759
+ return addServeOptions (builder);
760
+ }
761
+
762
+ kj::MainBuilder getServeBuilder () {
763
+ return kj::MainBuilder (context, getVersionString (),
746
764
" Serve requests based on a config." ,
747
765
" Serves requests based on the configuration specified in <config-file>." );
748
- return addServeOptions (addConfigParsingOptions (builder));
749
766
}
750
767
751
768
kj::MainFunc getTest () {
@@ -806,6 +823,16 @@ public:
806
823
.build ();
807
824
}
808
825
826
+ kj::MainFunc getMeasure () {
827
+ return kj::MainBuilder (context, getVersionString (),
828
+ " Measures the provided worker config and outputs the hash." ,
829
+ " Loads a worker's code and config in the same way as would be done by the "
830
+ " `workerd.createWorker` method, hashes the full config, and returns the hash." )
831
+ .expectArg (" <config-file>" , CLI_METHOD (parseWorkerConfigFile))
832
+ .callAfterParsing (CLI_METHOD (measure))
833
+ .build ();
834
+ }
835
+
809
836
void addImportPath (kj::StringPtr pathStr) {
810
837
auto path = fs->getCurrentPath ().evalNative (pathStr);
811
838
if (fs->getRoot ().tryOpenSubdir (path) != kj::none) {
@@ -929,6 +956,19 @@ public:
929
956
}
930
957
931
958
void parseConfigFile (kj::StringPtr pathStr) {
959
+ config = parseCapnpConfig<config::Config>(pathStr);
960
+ // We'll fail at getConfig() if there are multiple top level Config objects.
961
+ // The error message says that you have to specify which config to use, but
962
+ // it's not clear that there is any mechanism to do that.
963
+ util::Autogate::initAutogate (getConfig ().getAutogates ());
964
+ }
965
+
966
+ void parseWorkerConfigFile (kj::StringPtr pathStr) {
967
+ workerConfig = parseCapnpConfig<config::Worker>(pathStr);
968
+ }
969
+
970
+ template <typename T>
971
+ kj::Maybe<typename T::Reader> parseCapnpConfig (kj::StringPtr pathStr) {
932
972
if (pathStr == " -" ) {
933
973
// Read from stdin.
934
974
@@ -944,8 +984,8 @@ public:
944
984
#else
945
985
auto reader = kj::heap<capnp::StreamFdMessageReader>(STDIN_FILENO, CONFIG_READER_OPTIONS);
946
986
#endif
947
- config = reader->getRoot <config::Config>();
948
987
configOwner = kj::mv (reader);
988
+ return reader->getRoot <T>();
949
989
} else {
950
990
// Read file from disk.
951
991
auto path = fs->getCurrentPath ().evalNative (pathStr);
@@ -958,11 +998,11 @@ public:
958
998
mapping.size () / sizeof (capnp::word));
959
999
auto reader = kj::heap<capnp::FlatArrayMessageReader>(words, CONFIG_READER_OPTIONS)
960
1000
.attach (kj::mv (mapping));
961
- config = reader->getRoot <config::Config>();
962
1001
configOwner = kj::mv (reader);
1002
+ return reader->getRoot <T>();
963
1003
} else {
964
1004
// Interpret as schema file.
965
- schemaParser.loadCompiledTypeAndDependencies <config::Config >();
1005
+ schemaParser.loadCompiledTypeAndDependencies <T >();
966
1006
967
1007
parsedSchema = schemaParser.parseFile (
968
1008
kj::heap<SchemaFileImpl>(fs->getRoot (), fs->getCurrentPath (),
@@ -975,18 +1015,14 @@ public:
975
1015
auto constSchema = nested.asConst ();
976
1016
auto type = constSchema.getType ();
977
1017
if (type.isStruct () &&
978
- type.asStruct ().getProto ().getId () == capnp::typeId<config::Config >()) {
979
- topLevelConfigConstants. add (constSchema );
1018
+ type.asStruct ().getProto ().getId () == capnp::typeId<T >()) {
1019
+ return constSchema. as <T>( );
980
1020
}
981
1021
}
982
1022
}
1023
+ return kj::none;
983
1024
}
984
1025
}
985
-
986
- // We'll fail at getConfig() if there are multiple top level Config objects.
987
- // The error message says that you have to specify which config to use, but
988
- // it's not clear that there is any mechanism to do that.
989
- util::Autogate::initAutogate (getConfig ().getAutogates ());
990
1026
}
991
1027
992
1028
void setConstName (kj::StringPtr name) {
@@ -1193,6 +1229,19 @@ public:
1193
1229
}
1194
1230
}
1195
1231
1232
+ void measure () {
1233
+ if (hadErrors) context.exit ();
1234
+ auto measurement = workerd::server::measureConfig (
1235
+ KJ_UNWRAP_OR (workerConfig, CLI_ERROR (" no worker config provided" )));
1236
+ auto measurementHex = kj::encodeHex (measurement);
1237
+ #if _WIN32
1238
+ kj::FdOutputStream out (_fileno (stdout));
1239
+ #else
1240
+ kj::FdOutputStream out (STDOUT_FILENO);
1241
+ #endif
1242
+ out.write (measurementHex.asBytes ().begin (), measurementHex.size ());
1243
+ }
1244
+
1196
1245
[[noreturn]] void serve () noexcept {
1197
1246
serveImpl ([&](jsg::V8System& v8System, config::Config::Reader config) {
1198
1247
#if _WIN32
@@ -1286,6 +1335,7 @@ private:
1286
1335
1287
1336
kj::Own<void > configOwner; // backing object for `config`, if it's not `schemaParser`.
1288
1337
kj::Maybe<config::Config::Reader> config;
1338
+ kj::Maybe<config::Worker::Reader> workerConfig;
1289
1339
1290
1340
kj::Vector<int > inheritedFds;
1291
1341
0 commit comments