From f370892fdc6c02459b1cad2b99b1bda8d8dc922a Mon Sep 17 00:00:00 2001 From: Dominic Sudy <99014187+doosuu@users.noreply.github.com> Date: Tue, 15 Aug 2023 13:22:41 +0200 Subject: [PATCH] Feature: Document AppManifest version 3 design (#107) --- .../vehicle_app_manifest/_index.md | 243 ++++--- .../vehicle_app_manifest/interfaces/_index.md | 8 + .../interfaces/grpc_interface.md | 49 ++ .../vehicle_app_manifest/interfaces/pubsub.md | 43 ++ .../interfaces/vehicle_signal_interface.md | 60 ++ .../manifest.v3.schema.json | 45 ++ .../manifest_context.drawio | 85 +++ .../manifest_context.drawio.png | Bin 0 -> 51590 bytes .../new_app_manifest_overview.drawio.svg | 3 + .../lifecycle_management/packages/_index.md | 2 +- .../lifecycle_management/phases/_index.md | 7 + .../lifecycle_management/phases/create.md | 80 +++ .../phases/project_create_flow_new.drawio.svg | 3 + .../phases/project_create_flow_old.drawio.svg | 3 + .../project_configuration.md | 2 +- .../lifecycle_management/troubleshooting.md | 2 +- .../lifecycle_management/velocitas_cli.md | 2 +- .../assets/direct_service_invocation.drawio | 634 ++++++++++++++++++ 18 files changed, 1160 insertions(+), 111 deletions(-) create mode 100644 content/en/docs/concepts/development_model/vehicle_app_manifest/interfaces/_index.md create mode 100644 content/en/docs/concepts/development_model/vehicle_app_manifest/interfaces/grpc_interface.md create mode 100644 content/en/docs/concepts/development_model/vehicle_app_manifest/interfaces/pubsub.md create mode 100644 content/en/docs/concepts/development_model/vehicle_app_manifest/interfaces/vehicle_signal_interface.md create mode 100644 content/en/docs/concepts/development_model/vehicle_app_manifest/manifest.v3.schema.json create mode 100644 content/en/docs/concepts/development_model/vehicle_app_manifest/manifest_context.drawio create mode 100644 content/en/docs/concepts/development_model/vehicle_app_manifest/manifest_context.drawio.png create mode 100644 content/en/docs/concepts/development_model/vehicle_app_manifest/new_app_manifest_overview.drawio.svg create mode 100644 content/en/docs/concepts/lifecycle_management/phases/_index.md create mode 100644 content/en/docs/concepts/lifecycle_management/phases/create.md create mode 100644 content/en/docs/concepts/lifecycle_management/phases/project_create_flow_new.drawio.svg create mode 100644 content/en/docs/concepts/lifecycle_management/phases/project_create_flow_old.drawio.svg create mode 100644 static/assets/direct_service_invocation.drawio diff --git a/content/en/docs/concepts/development_model/vehicle_app_manifest/_index.md b/content/en/docs/concepts/development_model/vehicle_app_manifest/_index.md index 6aa8fc916..0dec990f5 100644 --- a/content/en/docs/concepts/development_model/vehicle_app_manifest/_index.md +++ b/content/en/docs/concepts/development_model/vehicle_app_manifest/_index.md @@ -7,142 +7,171 @@ description: > --- +## Versions + +* v1 +* v2 +* **v3 (current)** + ## Introduction -The _AppManifest_ defines the name and the requirements of a _Vehicle App_. The requirements are specified on interface level. The manifest defines the required service interfaces (e.g. gRPC functions) and the used vehicle model and accessed data points, but it does not define certain providers of those interfaces. -This concept provides flexibility by separating the requirements of a _Vehicle App_ from the definition of a concrete _Runtime_ and _Middleware_ configuration. +The _AppManifest_ defines the properties of your _Vehicle App_ and its _functional interfaces_ (**FIs**). + +**FIs** may be: + +* required service interfaces (e.g. a required gRPC service interface) +* the used vehicle model and accessed data points. +* an arbitrary abstract interface description used by 3rd parties + +In addition to _required_ **FIs**, _provided_ **FIs** can (and need) to be specified as well. + +These defined interfaces are then used by the Velocitas toolchain to: + +* generate service stubs for either a client implementation (required IF) or a server implementation (provided IF) (i.e. for gRPC) +* generate a source code equivalent of the defined vehicle model + +## Overview + +The image below depicts the interaction between _App Manifest_ and _DevEnv Configuration_ at -development time- The responsibilities are clearly separated; the _App Manifest_ describes the application and its interfaces whereas _DevEnv Configuration_ (or `.velocitas.json`) defines the configuration of the development environment and all the packages used by the Velocitas toolchain. + +![Overview](./new_app_manifest_overview.drawio.svg) + +## Context -The AppManifest is the only source of truth in our _Vehicle App_ templates for: +To fully understand the _AppManifest_, let's have a look at **who** interacts with it: -- Local development environments and configs -- deployment specs generation -- Velocitas CI/CD workflow -- OCI Image creation +![Manifest Context](./manifest_context.drawio.png) ## Purpose -- The AppManifest contains necessary information about the runtime requirements (VehicleModel, interfaces) of the app -- The AppManifest contains all required (or optional) data points that are used in the _Vehicle App_ with the necessary access rights (read, write) -- The AppManifest is service provider/implementation agnostic, while the service configurations are part of a corresponding [Velocitas Lifecycle Management](/docs/concepts/lifecycle_management) runtime package +* Define the requirements of a _Vehicle App_ in an **abstract way** to avoid dependencies on concrete _Runtime_ and _Middleware_ configurations. +* Description of your applications **functional interfaces**(VehicleModel, services, APIs, ...) +* Enable **loose coupling** of functional interface descriptions and the Velocitas toolchain. Some parts of the toolchain are responsible for reading the file and acting upon it, depending on the type of functional interface +* Providing an **extendable** syntax to enable custom functional interface types which may not provided by the Velocitas toolchain itself, but by a third party +* Providing a **single source of truth** for generation of deployment specifications (i.e. Helm-Charts, Kanto spec, etc...) -## Structure +## Example ```json // AppManifest.json { - "name":"SampleApp", - "vehicleModel":{ - "src":"https://github.com/COVESA/vehicle_signal_specification/releases/download/v3.0/vss_rel_3.0.json", - "datapoints":[ - { - "path":"Vehicle.Speed", - "required":"true", - "access":"read" - } - ] - }, - "runtime":[ - "grpc://sdv.databroker.v1.Broker/GetDatapoints", - "grpc://sdv.databroker.v1.Broker/Subscribe", - "grpc://sdv.databroker.v1.Broker/SetDatapoints", - "mqtt" - ] + "manifestVersion": "v3", + "name": "SampleApp", + "interfaces": [ + { + "type": "vehicle-signal-interface", + "config": { + "src": "https://github.com/COVESA/vehicle_signal_specification/releases/download/v3.0/vss_rel_3.0.json", + "datapoints": { + "required": [ + { + "path": "Vehicle.Speed", + "optional": "true", + "access": "read", + } + ], + "provided": [ + { + "path": "Vehicle.Cabin.Seat.Row1.Pos1.Position", + } + ] + } + } + }, + { + "type": "grpc-interface", + "config": { + "src": "https://raw.githubusercontent.com/eclipse/kuksa.val.services/main/seat_service/proto/sdv/edge/comfort/seats/v1/seats.proto", + "required": { + "methods": [ "Move", "MoveComponent" ] + }, + } + }, + { + "type": "pubsub", + "config": { + "reads": [ "sampleapp/getSpeed" ], + "writes": [ "sampleapp/currentSpeed", "sampleapp/getSpeed/response" ] + } + } } ``` -## Vehicle Model Description +The _VehicleApp_ above has an: -The [_Vehicle Model_](/docs/concepts/development_model/#vehicle-models) of the _Vehicle App_ is described with the source and required (or optional) data points. -More information: [Vehicle Model Creation](/docs/tutorials/vehicle_model_creation/) +* interface towards our generated Vehicle Signal Interface based on the [COVESA Vehicle Signal Specification](https://github.com/COVESA/vehicle_signal_specification). In particular, it requires read access to the vehicle signal `Vehicle.Speed` since the signal is marked as _optional_ the application will work, even if the signal is not present in the system. Additionally, the application acts as a provider for the signal `Vehicle.Cabin.Seat.Row1.Pos1.Position` meaning that it will take responsibility of reading/writing data directly to vehicle networks for the respective signal. -The source ("src") identifies the used _Vehicle Model_ description and the data points section defines which signals (i.e. data points) of that model need to be available for the _Vehicle App_ to run: +* interface towards gRPC based on the `seats.proto` file. Since the `direction` is `required` a service client for the `seats` service will be generated who interacts with the Velocitas middleware. -- The `path` references the definition (type, data type, unit, and other metadata) of a data point in the specified model -- The `required` flag tells if that data point is mandatory for the app to run or just optional -- `access` defines the required access right of the app to that data point (see below) +* interface towards the `pubsub` middleware and is reading to the topic `sampleapp/getSpeed` and writing the topics `sampleapp/currentSpeed`, `sampleapp/getSpeed/response`. -Further information can be found here: [How to Reference a Model Specification](/docs/tutorials/vehicle_model_creation/automated_model_lifecycle/#how-to-reference-a-model-specification) -
+The example has no provided interfaces. -### Data Point Access Rights +## Structure + +Describes all external properties and interfaces of a Vehicle Application. + +### Properties {{}} -| Access Right | Description | Vehicle Databroker Interface | -|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------| -| read | app needs to read the value of the data point from the provider (e.g. get value from databroker). | GetDatapoints/Subscribe | -| write | app needs to get and set the value of the data point (e.g. set, set_many values via the databroker or services). WRITE access implicitly has READ access. | SetDatapoints | +| Property | Type | Required | Description | +|-------------------|-------------------------|----------|----------------------------------------------------------| +| `manifestVersion` | string | **Yes** | The version of the App Manifest. | +| `name` | string | **Yes** | The name of the Vehicle Application. | +| `interfaces` | [object](#interfaces)[] | No | Array of all provided or required functional interfaces. | {{
}} -## AppManifest Examples +### interfaces -{{< tabpane lang="json">}} -{{< tab "Runtime interface via databroker" >}} +#### Properties -// Here we have a dependency to the databroker, the App doesn't have any direct -// connection to the SeatService because the databroker forwards the set requests from -// the app via SetDatapoints to the corresponding SeatService +{{}} +| Property | Type | Required | Description | +|----------|-------------------|----------|-----------------------------------------------------------------------------------------| +| `type` | string | **Yes** | The type of the functional interface. | +| `config` | [object](#config) | No | The configuration of the functional interface type. Content may vary between all types. | -{ - "name": "SeatAdjuster", - "vehicleModel": { - "src": "./app/vehiclemodel/used_vss.json", - "datapoints": [ - { - "path": "Vehicle.Cabin.Seat.Row1.Pos1.Position", - "required": "true", - "access": "write" - }, - { - "path": "Vehicle.Speed", - "required": "true", - "access": "read" - } - ], - }, - "runtime": [ - "grpc://sdv.databroker.v1.Broker/GetDatapoints", - "grpc://sdv.databroker.v1.Broker/Subscribe", - "grpc://sdv.databroker.v1.Broker/SetDatapoints", - "mqtt" - ] -} -{{< /tab >}} -{{< tab "Runtime interface via specific service" >}} +{{
}} -// Here the app establishes a direct gRPC connection to the -// Vehicle SeatService and adjusts the seat position via -// the MoveComponent Interface +#### config -{ - "name": "SeatAdjuster", - "vehicleModel": { - "src": "./app/vehiclemodel/used_vss.json", - "datapoints": [ - { - "path": "Vehicle.Cabin.Seat.Row1.Pos1.Position", - "required": "true", - "access": "read" - }, - { - "path": "Vehicle.Speed", - "required": "true", - "access": "read" - } - ], - }, - "runtime": [ - "grpc://sdv.databroker.v1.Broker/GetDatapoints", - "grpc://sdv.databroker.v1.Broker/Subscribe", - "grpc://sdv.edge.comfort.seats.v1.Seats/MoveComponent" - "mqtt" - ] -} -{{< /tab >}} -{{< /tabpane >}} +The configuration of the functional interface type. Content may vary between all types. + +Refer to the [JSON Schema](https://json-schema.org/) of the current _AppManifest_ [here](./manifest.v3.schema.json). + +### Visualization + +```mermaid + +graph TD + manifest(manifest.json) + manifest --> manifestVersion[manifestVersion] + manifest --> name[name] + manifest -.-> interfaces[interfaces] + + interfaces -- "0..n" --> interfaces.item(object) + interfaces.item --> interfaces.item.type[type] + interfaces.item -.-> interfaces.item.config[config] + +``` + +### Functional interface types supported by Velocitas + +Here is a list of functional interface types directly supported by the Velocitas toolchain and which Velocitas CLI packages are exposing the support: + +* [Vehicle Model](./interfaces/vehicle_model/) +* [gRPC interface](./interfaces/grpc_interface/) +* [Publish and subscribe](./interfaces/pubsub/) + +Support for additional interface types may be added by providing a 3rd party [CLI package](/docs/concepts/lifecycle_management/packages/). + +## Planned, but not yet available features + +Some FIs are dependent on used classes, methods or literals in your _Vehicle App_'s source code. For example the `vehicle-model` FI requires you to list required or provided datapoints. At the moment, these attributes need to be filled **manually**. There are ideas to auto-generate these attributes by analyzing the source code, but nothing is planned for that, yet. ## Further information -- Tutorial: [Quickstart](/docs/tutorials/quickstart.md) -- Tutorial: [Vehicle Model Creation](/docs/tutorials/vehicle_model_creation) -- Tutorial: [_Vehicle App_ Development](/docs/tutorials/vehicle_app_development) -- Concept: [Lifecycle Management](/docs/concepts/lifecycle_management) +* Tutorial: [Quickstart](/docs/tutorials/quickstart.md) +* Tutorial: [Vehicle Model Creation](/docs/tutorials/vehicle_model_creation) +* Tutorial: [_Vehicle App_ Development](/docs/tutorials/vehicle_app_development) +* Concept: [Lifecycle Management](/docs/concepts/lifecycle_management) diff --git a/content/en/docs/concepts/development_model/vehicle_app_manifest/interfaces/_index.md b/content/en/docs/concepts/development_model/vehicle_app_manifest/interfaces/_index.md new file mode 100644 index 000000000..ee8a5e232 --- /dev/null +++ b/content/en/docs/concepts/development_model/vehicle_app_manifest/interfaces/_index.md @@ -0,0 +1,8 @@ +--- +title: "Interfaces" +date: 2023-05-31T13:33:25+05:30 +weight: 10 +description: > + Learn more about logical interfaces. + +--- \ No newline at end of file diff --git a/content/en/docs/concepts/development_model/vehicle_app_manifest/interfaces/grpc_interface.md b/content/en/docs/concepts/development_model/vehicle_app_manifest/interfaces/grpc_interface.md new file mode 100644 index 000000000..5ebe50e24 --- /dev/null +++ b/content/en/docs/concepts/development_model/vehicle_app_manifest/interfaces/grpc_interface.md @@ -0,0 +1,49 @@ +--- +title: "gRPC Service Interface" +date: 2023-08-09T00:00:00+01:00 +weight: 20 +description: > + The functional interface for supporting remote procedure calls via gRPC. + +--- + +{{}} +| Providing CLI package | Interface type-key | +|-----------------------------|-----------------------| +| `devenv-devcontainer-setup` | `grpc-interface` | +{{
}} + +## Description + +This interface type introduces a dependency to a gRPC service. It is used to generate either client stubs (in case your application requires the interface) or server stubs (in case your application provides the interface). The result of the generation is a language specific and package manager specific source code package, integrated with the Velocitas SDK core. + +If a _Vehicle App_ requires a `grpc-interface` - a client stub embedded into the Velocitas framework will be generated and added as a build-time dependency of your application. It enables you to access your service from your _Vehicle App_ without any additional effort. + +If a _Vehicle App_ provides a `grpc-interface` - a server stub embedded into the Velocitas framework will be generated and added as a build-time dependency of your application. It enables you to quickly add the business logic of your application. + +## Configuration structure + +{{}} +| Attribute | Example value | Description | +|-|-|-| +| `src` | `"https://raw.githubusercontent.com/eclipse/kuksa.val.services/v0.2.0/seat_service/proto/sdv/edge/comfort/seats/v1/seats.proto"` | URI of the used protobuf specification of the service. URI may point to a local file or to a file provided by a server. It is generally recommended that a **stable** proto file is used. I.e. one that is already released under a proper tag rather than an in-development proto file. | +| `required.methods` | | Array of service's methods that are accessed by the application. In addition to access control the methods attribute may be used to determine backward or forward compatibility i.e. if semantics of a service's interface did not change but methods were added or removed in a future version. | +| `required.methods.[].name` | `"Move"`, `"MoveComponent"` | Name of the method that the application would like to access | +| `provided` | `{}` | Reserved object indicating that the interface is provided. Might be filled with further configuration values. +{{
}} + +## Example + +```json +{ + "type": "grpc-interface", + "config": { + "src": "https://raw.githubusercontent.com/eclipse/kuksa.val.services/v0.2.0/seat_service/proto/sdv/edge/comfort/seats/v1/seats.proto", + "required": { + "methods": [ + "Move", "MoveComponent" + ] + } + } +} +``` diff --git a/content/en/docs/concepts/development_model/vehicle_app_manifest/interfaces/pubsub.md b/content/en/docs/concepts/development_model/vehicle_app_manifest/interfaces/pubsub.md new file mode 100644 index 000000000..3405cd495 --- /dev/null +++ b/content/en/docs/concepts/development_model/vehicle_app_manifest/interfaces/pubsub.md @@ -0,0 +1,43 @@ +--- +title: "Publish Subscribe" +date: 2023-08-09T00:00:00+01:00 +weight: 20 +description: > + The functional interface for supporting communication via publish and subscribe. + +--- + +{{}} +| Providing CLI package | Interface type-key | +|-----------------------------|-----------------------| +| `devenv-runtimes` | `pubsub` | +{{
}} + +## Description + +This interface type introduces a dependency to a publish and subscribe middleware. While this may change in the future due to new middlewares being adopted, at the moment this will always indicate a dependency to MQTT. + +If a _Vehicle App_ requires `pubsub` - this will influence the generated deployment specs to include a publish and subscribe broker (i.e. an MQTT broker). + +If a _Vehicle App_ provides `pubsub` - this will influence the generated deployment specs to include a publish and subscribe broker (i.e. an MQTT broker). + +## Configuration structure + +{{}} +| Attribute | Example value | Description | +|-|-|-| +| `reads` | `[ "sampleapp/getSpeed" ]` | Array of topics which are read by the application. | +| `writes` | `[ "sampleapp/currentSpeed", "sampleapp/getSpeed/response" ]` | Array of topics which are written by the application. | +{{
}} + +## Example + +```json +{ + "type": "pubsub", + "config": { + "reads": [ "sampleapp/getSpeed" ], + "writes": [ "sampleapp/currentSpeed", "sampleapp/getSpeed/response" ] + } +} +``` diff --git a/content/en/docs/concepts/development_model/vehicle_app_manifest/interfaces/vehicle_signal_interface.md b/content/en/docs/concepts/development_model/vehicle_app_manifest/interfaces/vehicle_signal_interface.md new file mode 100644 index 000000000..61a3bccae --- /dev/null +++ b/content/en/docs/concepts/development_model/vehicle_app_manifest/interfaces/vehicle_signal_interface.md @@ -0,0 +1,60 @@ +--- +title: "Vehicle Signal Interface" +date: 2023-08-09T00:00:00+01:00 +weight: 10 +description: > + The functional interface for providing vehicle signal access via VSS specification. + +--- + +{{}} +| Providing CLI package | Interface type-key | +|-----------------------------|----------------------------------| +| `devenv-devcontainer-setup` | `vehicle-signal-interface` | +{{
}} + +The _Vehicle Signal Interface_ formerly known as [_Vehicle Model_](/docs/concepts/development_model/#vehicle-models) interface type creates an interface to a signal interface described by the VSS spec. This interface will generate a source code package equivalent to the contents of your VSS JSON automatically upon devContainer creation. + +If a _Vehicle App_ requires a `vehicle-signal-interface`, it will act as a consumer of datapoints already available in the system. If, on the other hand, a _Vehicle App_ provides a `vehicle-signal-interface`, it will act as a provider (formerly feeder in KUKSA terms) of the declared datapoints. + +More information: [Vehicle Model Creation](/docs/tutorials/vehicle_model_creation/) + +## Configuration structure + +{{}} +| Attribute | Example value | Description | +|-|-|-| +| `src` | `"https://github.com/COVESA/vehicle_signal_specification/releases/download/v3.0/vss_rel_3.0.json"` | URI of the used COVESA Vehicle Signal Specification JSON export. URI may point to a local file or to a file provided by a server. | +| `datapoints` | | Object containing both required and provided datapoints. | +| `datapoints.required` | | Array of required datapoints. | +| `datapoints.required.[].path` | `Vehicle.Speed` | Path of the VSS datapoint. | +| `datapoints.required.[].optional` | `true`, `false` | Is the datapoint optional, i.e. can the _Vehicle App_ work without the datapoint being present in the system. Defaults to `false`. | +| `datapoints.required.[].access` | `read`, `write` | What kind of access to the datapoint is needed by the application. | +| `datapoints.provided` | | Array of provided datapoints. | +| `datapoints.provided.[].path` | `Vehicle.Cabin.Seat.Row1.Pos1.Position` | Path of the VSS datapoint. | +{{
}} + +## Example + +```json +{ + "type": "vehicle-signal-interface", + "config": { + "src": "https://github.com/COVESA/vehicle_signal_specification/releases/download/v3.0/vss_rel_3.0.json", + "datapoints": { + "required": [ + { + "path": "Vehicle.Speed", + "optional": "true", + "access": "read" + } + ], + "provided": [ + { + "path": "Vehicle.Cabin.Seat.Row1.Pos1.Position" + } + ] + } + } +} +``` diff --git a/content/en/docs/concepts/development_model/vehicle_app_manifest/manifest.v3.schema.json b/content/en/docs/concepts/development_model/vehicle_app_manifest/manifest.v3.schema.json new file mode 100644 index 000000000..f9f1ad588 --- /dev/null +++ b/content/en/docs/concepts/development_model/vehicle_app_manifest/manifest.v3.schema.json @@ -0,0 +1,45 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://eclipse.dev/velocitas/schemas/appmanifest", + "title": "Application Manifest", + "description": "Describes all external properties and interfaces of a Vehicle Application.", + "type": "object", + "properties": { + "manifestVersion": { + "type": "string", + "description": "The version of the App Manifest.", + "examples": ["v3"] + }, + "name": { + "type": "string", + "description": "The name of the Vehicle Application.", + "examples": ["Sample App", "Awesome Vehicle Application"] + }, + "interfaces": { + "type": "array", + "description": "Array of all provided or required functional interfaces.", + "items": { + "type": "object", + "title": "Functional Interface", + "properties": { + "type": { + "type": "string", + "description": "The type of the functional interface.", + "examples": ["grpc-interface", "vehicle-signal-interface"] + }, + "config": { + "type": "object", + "description": "The configuration of the functional interface type. Content may vary between all types." + } + }, + "required": [ + "type" + ] + } + } + }, + "required": [ + "manifestVersion", + "name" + ] +} \ No newline at end of file diff --git a/content/en/docs/concepts/development_model/vehicle_app_manifest/manifest_context.drawio b/content/en/docs/concepts/development_model/vehicle_app_manifest/manifest_context.drawio new file mode 100644 index 000000000..774897867 --- /dev/null +++ b/content/en/docs/concepts/development_model/vehicle_app_manifest/manifest_context.drawio @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/docs/concepts/development_model/vehicle_app_manifest/manifest_context.drawio.png b/content/en/docs/concepts/development_model/vehicle_app_manifest/manifest_context.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..aed065df651abf7479a7de972a3cceb6ce758411 GIT binary patch literal 51590 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

{B8e)p8yVE7=7x!{2 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 + +
Velocitas project specific cache
Velocitas project specific cache
Velocitas package repository
Velocitas package repository
Velocitas Github
Velocitas Github
Velocitas project
workspace
Velocitas project...
described by
described by
depends on
depends on
depends on
depends on
Vehicle Application
Vehicle Applica...
references
references
references
references
Application
Manifest
Application...
scans for gRPC
dependencies
scans for gRPC...
<<velocitas pkg>>
grpc-service-support@v1
<<velocitas pkg>>...
<<git repo>>
velocitas-core-sdk
<<git repo>>...
scans for vehicle model
dependencies
scans for vehicle model...
generates
generates
<<velocitas pkg>>
vss-vehiclemodel-support@v2
<<velocitas pkg>>...
scans for uP
dependencies
scans for uP...
generates
generates
<<velocitas pkg>>
uprotocol-service-support@v0.2
<<velocitas pkg>>...
Service IF specification
Service IF spec...
Service IF specification
Service IF spec...
Service IF specification
Service IF spec...
<<pip/conan package>>
sdk-ext-<service>-client
<<pip/conan package>>...
generates
generates
references
references
references
references
references
references
devenv configuration
(.velocitas.json)
devenv configur...
<<git repo>>
grpc-service-support
<<git repo>>...
<<git repo>>
vss-vehiclemodel-support
<<git repo>>...
cloned by CLI
cloned by CLI
<<git repo>>
uprotocol-service-support
<<git repo>>...
<<pip/conan package>>
sdk-ext-vss-vehicle-model
<<pip/conan package>>...
API catalogue
API catalogue
<<pip/conan package>>
sdk-ext-uprotocol-<service>-client
<<pip/conan package>>...
3rd party git server
3rd party git server
<<git repo>>
oem-service-support
<<git repo>>...
references
references
generates
generates
scans for oem
dependencies
scans for oem...
<<velocitas pkg>>
oem-service-support@v0.7
<<velocitas pkg>>...
<<pip/conan package>>
sdk-ext-oem-service-client
<<pip/conan package>>...
Text is not SVG - cannot display
\ No newline at end of file diff --git a/content/en/docs/concepts/lifecycle_management/packages/_index.md b/content/en/docs/concepts/lifecycle_management/packages/_index.md index 9ae56ec4c..74f74e0d6 100644 --- a/content/en/docs/concepts/lifecycle_management/packages/_index.md +++ b/content/en/docs/concepts/lifecycle_management/packages/_index.md @@ -1,7 +1,7 @@ --- title: "Packages" date: 2022-05-09T13:43:25+05:30 -weight: 1 +weight: 40 description: > Learn everything about Velocitas packages. aliases: diff --git a/content/en/docs/concepts/lifecycle_management/phases/_index.md b/content/en/docs/concepts/lifecycle_management/phases/_index.md new file mode 100644 index 000000000..61c71b413 --- /dev/null +++ b/content/en/docs/concepts/lifecycle_management/phases/_index.md @@ -0,0 +1,7 @@ +--- +title: "Phases" +date: 2023-08-11T00:00:00+01:00 +weight: 30 +description: > + Learn about the different phases within the lifecycle of your project. +--- diff --git a/content/en/docs/concepts/lifecycle_management/phases/create.md b/content/en/docs/concepts/lifecycle_management/phases/create.md new file mode 100644 index 000000000..d8070a278 --- /dev/null +++ b/content/en/docs/concepts/lifecycle_management/phases/create.md @@ -0,0 +1,80 @@ +--- +title: "Create" +date: 2023-08-07T00:00:00+01:00 +weight: 20 +description: > + To be filled +resources: +--- + +To be filled. + +#### Template based creation flow + +![Old creation flow](../project_create_flow_old.drawio.svg) + +#### Bootstrapping creation flow + +![New creation flow](../project_create_flow_new.drawio.svg) + +#### Resulting Velocitas CLI and Velocitas Package changes + +* `velocitas create` command shall be introduced + * it will guide through the project creation process, allowing the developer to add APIs and services at creation time which will reference the correct Velocitas CLI packages (either provided by Velocitas or by a 3rd party). + * in addition to an interactive mode where create is invoked without arguments, there shall be a CLI mode where all of the arguments shall be passable as arguments + +* Packages need to be available in a central registry (i.e. a new git repository) otherwise step 3 (depicted below) is not possible. + +* Packages need to expose which dependency types they are providing in their manifest. For each dependency type a human readable name for the type shall be exposed. + +## Interaction mockup + +```bash +> velocitas create +... Creating a new Velocitas project! +> What is the name of your project? +MyApp + +> 1. Which programming language would you like to use for your project? +[ ] Python +[x] C++ + +> 2. Which integrations would you like to use? (multiple selections possible) +[x] Github +[x] Gitlab +[ ] Gitee + +> 3. Which API dependencies does your project have? +[x] gRPC service +[ ] uProtocol service +[x] Vehicle Service Catalogue + +> 4. Add an API dependency (y/n)? +y + +> 5. What type of dependency? +[x] gRPC-IF +[ ] VSC-IF + +> 6. URI of the .proto file? +https://some-url/if.proto + +> 7. Add an(other) API dependency (y/n)? +n + +... Project created! +``` + +*Arguments mockup:* + +```bash + +$ velocitas create \ + --name MyApp \ + --lang cpp \ + --package grpc-service-support \ + --package vsc-support \ + --require grpc-interface:https://some-url/if.proto + +> Project created! +``` diff --git a/content/en/docs/concepts/lifecycle_management/phases/project_create_flow_new.drawio.svg b/content/en/docs/concepts/lifecycle_management/phases/project_create_flow_new.drawio.svg new file mode 100644 index 000000000..84a9a09ad --- /dev/null +++ b/content/en/docs/concepts/lifecycle_management/phases/project_create_flow_new.drawio.svg @@ -0,0 +1,3 @@ + + +
Developer machine
Developer machine
Github
Github
invokes
 `velocitas create`
invokes...
Developer
Deve...
Select and pick
required APIs and services
Select and pick...
creates
creates
Velocitas CLI 
Velocitas CLI 
uses
uses
Velocitas
VSS-Model Support
Velocitas...
Velocitas
gRPC Service Support
Velocitas...
Velocitas
VSC Support
Velocitas...
references developer defined
set of of
references developer defined...
produces
produces
Developer's VApp repo
Developer's VAp...
VApp
VApp
Any git server
Any git server
3rd party package
3rd party packa...
Vehicle Signal Specification
Vehicle Signal...
Text is not SVG - cannot display
\ No newline at end of file diff --git a/content/en/docs/concepts/lifecycle_management/phases/project_create_flow_old.drawio.svg b/content/en/docs/concepts/lifecycle_management/phases/project_create_flow_old.drawio.svg new file mode 100644 index 000000000..1cd7789d0 --- /dev/null +++ b/content/en/docs/concepts/lifecycle_management/phases/project_create_flow_old.drawio.svg @@ -0,0 +1,3 @@ + + +
Github
Github
Use this template
Use this template
Developer
Deve...
creates
creates
Velocitas Project Template
Velocitas Proje...
references fixed set of
references fixed set of
uses
uses
Developer's VApp repo
Developer's VAp...
Velocitas Package
Velocitas Packa...
Velocitas Package
Velocitas Packa...
Velocitas Package repo
Velocitas Packa...
Vehicle Signal Specification
Vehicle Signal...
Text is not SVG - cannot display
\ No newline at end of file diff --git a/content/en/docs/concepts/lifecycle_management/project_configuration.md b/content/en/docs/concepts/lifecycle_management/project_configuration.md index d5882e976..1468d95c3 100644 --- a/content/en/docs/concepts/lifecycle_management/project_configuration.md +++ b/content/en/docs/concepts/lifecycle_management/project_configuration.md @@ -1,7 +1,7 @@ --- title: "Project Configuration" date: 2023-02-13T09:43:25+05:30 -weight: 1 +weight: 10 description: > Learn everything about Velocitas project configuration. aliases: diff --git a/content/en/docs/concepts/lifecycle_management/troubleshooting.md b/content/en/docs/concepts/lifecycle_management/troubleshooting.md index 86f75245c..bebf5a90f 100644 --- a/content/en/docs/concepts/lifecycle_management/troubleshooting.md +++ b/content/en/docs/concepts/lifecycle_management/troubleshooting.md @@ -1,7 +1,7 @@ --- title: "Troubleshooting" date: 2023-02-13T09:43:25+05:30 -weight: 4 +weight: 99 description: > Known issues and fixes. --- diff --git a/content/en/docs/concepts/lifecycle_management/velocitas_cli.md b/content/en/docs/concepts/lifecycle_management/velocitas_cli.md index 11ceb07d6..e3db48418 100644 --- a/content/en/docs/concepts/lifecycle_management/velocitas_cli.md +++ b/content/en/docs/concepts/lifecycle_management/velocitas_cli.md @@ -1,6 +1,6 @@ --- title: "Velocitas CLI" -weight: 3 +weight: 20 date: 2023-02-13T09:43:25+05:30 description: > Learn everything about the Velocitas CLI. diff --git a/static/assets/direct_service_invocation.drawio b/static/assets/direct_service_invocation.drawio new file mode 100644 index 000000000..ffe9510bc --- /dev/null +++ b/static/assets/direct_service_invocation.drawio @@ -0,0 +1,634 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +