Skip to content

Latest commit

 

History

History
78 lines (54 loc) · 6.6 KB

code-generation.md

File metadata and controls

78 lines (54 loc) · 6.6 KB

Code Generation

Code generation done by the grafana-app-sdk can be broadly split into two buckets: what we call kind code generation which is run to generate code from your CUE kinds which can be used in your app, and project component generation, which is a run-once kind of codegen that scaffolds your project with boilerplate code that you can then alter as you see fit.

code generation is done with the generate command in the CLI, and project component generation is done with the project component add command in the CLI (also note that project init is a special case of codegen that scaffolds your initial project with opinionated defaults). The general workflow is that component generation is run only once, while kind code generation is run whenever you update or add a kind, or whenever you update your version of the grafana-app-sdk (to ensure that your generated code works with the new library version).

Kind Code Generation

Code generation turns kinds written in CUE into go and TypeScript code which can be used to write your app logic. A full breakdown on writing CUE kinds and using them with the CLI's code generation can be found in the Writing Kinds document.

Kind codegen uses grafana-app-sdk generate as its base commands, and uses a few flags that you can leave as default values if you use the setup that grafana-app-sdk project init gives you. The full command looks like:

grafana-app-sdk generate [-c|--cuepath=kinds] [-g|--gogenpath=pkg/generated] [-t|--tsgenpath=plugin/src/generated] [--crdencoding=json] [--crdpath=definitions]

This command scans the cuepath for CUE files, and parses all top-level fields in all present CUE files as CUE kinds. If kind validation encounters any errors, no files will be written, and the validation error(s) will be printed out. On successful generation:

  • kind go code will be written to gogenpath, with a package for each unique kind-version combination
  • kind TypeScript code will be written to tsgenpath, with a folder for each unique kind-version combination
  • kind CRD files will be written to crdpath, encoded as JSON or YAML based on crdencoding, with a CRD file per kind

Important

Because the interfaces that the grafana-app-sdk libraries use can change, be sure to run kind code generation using a version of the grafana-app-sdk CLI that matches the version of the dependency you use in your project. Whenever you update the dependency, make sure you re-run the kind code generation as well.

Please see Writing Kinds for a more detailed look at kind code generation from CUE.

Project Component Generation

Project component generation is used to add boilerplate code for a "component" of your app. Components understood by the SDK are:

  • frontend - a frontend plugin for your app, written in TypeScript. This is deployed in grafana as a standard app plugin, and is coupled with the backend component (if it exists) when deployed.
  • backend - a backend component to an app plugin, written in go. This is deployed in grafana as a standard app plugin, and is coupled with the frontend component when deployed.
  • operator - a standalone operator, written in go (see Operator-based applications in Application design patterns).

Multiple components can be specified in the same command. The full syntax is:

grafana-app-sdk project component add <list of space-separated components> [-c|--cuepath=kinds]

A list of valid components can also be found by running

grafana-app-sdk project component add

Without any components to add

frontend

The frontend component generates TypeScript code and configuration for a grafana plugin in plugin, similar to the output of the npm grafana/create-plugin tool (if you would like to use create-plugin instead, see the Get started docs, and create an app plugin).

backend

The backend component generates plugin backend code in pkg/plugin for setting up a set of HTTP handlers to proxy Create, Read, Update, Delete, and List requests to the API server, using a TypedStore, and pulling kube config information for the API server from the secureJsonData of the plugin. It also adds a main.go to plugin/pkg, which is the entrypoint for the back-end component of the grafana app plugin.

Note

backend component generation will eventually be deprecated in favor of the frontend component communicating directly with the API server, rather than through a back-end proxy.

operator

The operator component generates a boilerplate watcher for each kind in cuepath in pkg/watchers/. The rest of the operator code is generated in cmd/operator, and includes configuration, telemetry, a main file that sets up an operator using the simple package, and a Dockerfile for building a deploying a docker image for your operator. The generated boilerplate code works with the operator targets in the Makefile generated by grafana-app-sdk project init.

Note

The project command also has a kind target, which can be used to generate a boilerplate kind, with

grafana-app-sdk project kind add <kind name> [--plugin-id] [-c|--cuepath=kinds]

This is not a component command, but is useful for quickly generating a CUE kind in your cuepath.

Project Initialization

Project initialization is a special case of code generation used to initialize a new app-sdk project. It is not required to work with the app-sdk, but exists as a convenient way of setting up a project with the default workflow of the grafana-app-sdk. The syntax is:

grafana-app-sdk project init <project go module name>

This sets up your project with a go module, a kinds directory with a CUE module, a Makefile with some sample targets, and a local directory that can be used with grafana-app-sdk project local commands (see Local Development & Testing).

Examples & Testing

Code generation for both kinds and project components is done as part of the issue tracker tutorial (kind code generation, project component generation).

Automated testing of kind code generation is done using the files in codegen/cuekind/testing/, with generated files compared against codegen/testing/golden_generated.