Skip to content

Commit

Permalink
Move node configuration to runtime
Browse files Browse the repository at this point in the history
The ApplicationConfiguration object is now more of a directory of
executable wasm modules, and an initial Node configuration.

Subsequent Nodes are created at runtime by passing the serialized
NodeConfiguration protobuf message to `node_create` directly.

This allows removing an extra indirection from application to the config
of individual nodes, in favour of inlining configs in the Wasm code of
the main node itself.

Also remove parts of the logic around the old ApplicationConfiguration
format from the C++ Oak Runtime, under the assumption that it is going
to be deleted soon.

Ref project-oak#688
  • Loading branch information
tiziano88 committed May 26, 2020
1 parent 1d54836 commit faf5dac
Show file tree
Hide file tree
Showing 76 changed files with 755 additions and 1,577 deletions.
69 changes: 5 additions & 64 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 12 additions & 11 deletions docs/abi.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,22 +183,23 @@ Closes the channel identified by `param[0]`.
### `node_create`

Creates a new Node running the Node configuration identified by `param[0]` and
`param[1]`, using the entrypoint specified by `param[2]` and `param[3]`,
assigning the label specified by `param[4]` and `param[5]` to the newly created
Node, passing in an initial handle to the read half of a channel identified by
`param[6]`. The entrypoint name is ignored when creating non-WebAssembly Nodes.
`param[1]`, assigning the label specified by `param[2]` and `param[3]` to the
newly created Node, passing in an initial handle to the read half of a channel
identified by `param[4]`. The entrypoint name is ignored when creating
non-WebAssembly Nodes.

The Node configuration is a serialized
[`NodeConfiguration`](/oak/proto/application.proto) protobuf message.

If creating the specified Node would violate
[information flow control](/docs/concepts.md#labels), returns
`ERR_PERMISSION_DENIED`.

- `param[0]: usize`: Source buffer holding node configuration name
- `param[1]: usize`: Node configuration name size in bytes
- `param[2]: usize`: Source buffer holding entrypoint name
- `param[3]: usize`: Entrypoint name size in bytes
- `param[4]: usize`: Source buffer holding label
- `param[5]: usize`: Label size in bytes
- `param[6]: usize`: Handle to channel
- `param[0]: usize`: Source buffer holding serialized NodeConfiguration
- `param[1]: usize`: Serialized NodeConfiguration size in bytes
- `param[2]: usize`: Source buffer holding label
- `param[3]: usize`: Label size in bytes
- `param[4]: usize`: Handle to channel
- `result[0]: u32`: Status of operation

### random_get
Expand Down
78 changes: 39 additions & 39 deletions docs/programming-oak.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ oak::entrypoint!(grpc_oak_main => |_in_channel| {
config: None,
model: NaiveBayes::new(),
};
let grpc_channel = oak::grpc::server::init_default();
let grpc_channel =
oak::grpc::server::init("[::]:8080").expect("could not create gRPC server pseudo-Node");
oak::run_event_loop(node, grpc_channel);
});
```
Expand Down Expand Up @@ -108,7 +109,8 @@ Application), the easiest way to use a gRPC service implementation is to:
oak::entrypoint!(grpc_oak_main => |_in_channel| {
oak::logger::init_default();
let dispatcher = FormatServiceDispatcher::new(Node);
let grpc_channel = oak::grpc::server::init_default();
let grpc_channel =
oak::grpc::server::init("[::]:8080").expect("could not create gRPC server pseudo-Node");
oak::run_event_loop(dispatcher, grpc_channel);
}
```
Expand Down Expand Up @@ -228,37 +230,21 @@ be serialized into a binary file. The Application first needs to specify a
template configuration file:

<!-- prettier-ignore-start -->
[embedmd]:# (../examples/hello_world/config/config.textproto /node_configs.*/ /initial_entrypoint_name.*/)
[embedmd]:# (../examples/hello_world/config/config.textproto)
```textproto
node_configs {
name: "app"
wasm_config {
module_bytes: "<bytes>"
initial_node_configuration: {
name: "main"
wasm_config: {
wasm_module_name: "app"
wasm_entrypoint_name: "grpc_oak_main"
}
}
node_configs {
name: "translator"
wasm_config {
module_bytes: "<bytes>"
}
}
node_configs {
name: "grpc-server"
grpc_server_config {
address: "[::]:8080"
}
}
node_configs {
name: "log"
log_config {}
}
initial_node_config_name: "app"
initial_entrypoint_name: "grpc_oak_main"
```
<!-- prettier-ignore-end -->

The `module_bytes: "<bytes>"` means that this value will be filled with
WebAssembly module bytes after serialization using the
The `wasm_modules` field (not shown above because empty in the template
configuration) will be filled with WebAssembly module bytes after serialization
using the
[_Application Configuration Serializer_](../oak/common/app_config_serializer.cc),
as follows:

Expand Down Expand Up @@ -421,7 +407,8 @@ to the room:
[embedmd]:# (../examples/chat/module/rust/src/lib.rs Rust /.*channel_create\(\)/ /\}$/)
```Rust
let (wh, rh) = oak::channel_create().unwrap();
oak::node_create("app", "backend_oak_main", rh).expect("could not create node");
oak::node_create(&oak::node_config::wasm("app", "backend_oak_main"), rh)
.expect("could not create node");
oak::channel_close(rh.handle).expect("could not close channel");
Room {
sender: oak::io::Sender::new(wh),
Expand Down Expand Up @@ -539,7 +526,8 @@ oak::entrypoint!(oak_main => |in_channel| {
oak::entrypoint!(grpc_oak_main => |_in_channel| {
oak::logger::init_default();
let dispatcher = TranslatorDispatcher::new(Node);
let grpc_channel = oak::grpc::server::init_default();
let grpc_channel =
oak::grpc::server::init("[::]:8080").expect("could not create gRPC server pseudo-Node");
oak::run_event_loop(dispatcher, grpc_channel);
});
```
Expand All @@ -552,20 +540,32 @@ use of the functionality of the Oak Runtime.
### Testing Multi-Node Applications
It's also possible to test an Oak Application that's built from multiple Nodes,
using `oak_runtime::application_configuration` to create an application
configuration and then `oak_runtime::Runtime::configure_and_run(configuration)`
to configure and run the Runtime.
by defining an appropriate `ApplicationConfiguration` instance and then
`oak_runtime::Runtime::configure_and_run(application_configuration, ...)` to
configure and run the Runtime.
<!-- prettier-ignore-start -->
[embedmd]:# (../examples/abitest/tests/src/tests.rs Rust / +let configuration =/ /configure_and_run.*/)
[embedmd]:# (../examples/abitest/tests/src/tests.rs Rust / +let application_configuration =/ /unable to configure runtime.*/)
```Rust
let configuration = oak_runtime::application_configuration(
build_wasm().expect("failed to build wasm modules"),
LOG_CONFIG_NAME,
FRONTEND_CONFIG_NAME,
FRONTEND_ENTRYPOINT_NAME,
);
let application_configuration = ApplicationConfiguration {
wasm_modules: build_wasm().expect("failed to build wasm modules"),
initial_node_configuration: Some(oak::node_config::wasm(
FRONTEND_MODULE_NAME,
FRONTEND_ENTRYPOINT_NAME,
)),
};
let (runtime, entry_channel) = oak_runtime::configure_and_run(
application_configuration,
oak_runtime::RuntimeConfiguration::default(),
oak_runtime::GrpcConfiguration {
grpc_server_tls_identity: None,
// Some of the tests require a gRPC client, so we populate the required certificate with
// an invalid value here, even though it will still fail when instantiating the actual
// gRPC client.
grpc_client_root_tls_certificate: Some(Certificate::from_pem("invalid-cert")),
},
)
.expect("unable to configure runtime with test wasm");
```
<!-- prettier-ignore-end -->
3 changes: 0 additions & 3 deletions examples/abitest/abitest_common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,3 @@ impl oak::io::Encodable for InternalMessage {
Ok(oak::io::Message { bytes, handles })
}
}

// Expected name for log node config.
pub const LOG_CONFIG_NAME: &str = "logging-config";
4 changes: 2 additions & 2 deletions examples/abitest/config/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ exports_files(srcs = glob(["*.textproto"]))
serialized_config(
name = "config",
modules = {
"frontend-config": "//:target/wasm32-unknown-unknown/release/abitest_0_frontend.wasm",
"backend-config": "//:target/wasm32-unknown-unknown/release/abitest_1_backend.wasm",
"frontend_module": "//:target/wasm32-unknown-unknown/release/abitest_0_frontend.wasm",
"backend_module": "//:target/wasm32-unknown-unknown/release/abitest_1_backend.wasm",
},
textproto = ":config.textproto",
)
63 changes: 5 additions & 58 deletions examples/abitest/config/config.textproto
Original file line number Diff line number Diff line change
@@ -1,60 +1,7 @@
node_configs {
name: "frontend-config"
wasm_config {
module_bytes: "<bytes>"
initial_node_configuration: {
name: "main"
wasm_config: {
wasm_module_name: "frontend_module"
wasm_entrypoint_name: "grpc_frontend_oak_main"
}
}
node_configs {
name: "backend-config"
wasm_config {
module_bytes: "<bytes>"
}
}
node_configs {
name: "logging-config"
log_config {}
}
node_configs {
name: "storage"
storage_config {
address: "localhost:7867"
}
}
node_configs {
name: "absent-storage"
storage_config {
address: "test.invalid:9999"
}
}
node_configs {
name: "grpc-server"
grpc_server_config {
address: "[::]:8080"
}
}
node_configs {
name: "grpc-client"
grpc_client_config {
uri: "https://localhost:7878"
address: "localhost:7878"
}
}
node_configs {
name: "absent-grpc-client"
grpc_client_config {
uri: "https://test.invalid:9999"
address: "test.invalid:9999"
}
}
node_configs {
name: "roughtime-client"
roughtime_client_config {}
}
node_configs {
name: "roughtime-misconfig"
roughtime_client_config {
min_overlapping_intervals: 99
}
}
initial_node_config_name: "frontend-config"
initial_entrypoint_name: "grpc_frontend_oak_main"
Loading

0 comments on commit faf5dac

Please sign in to comment.