Apps: Add Example App to ./apps (#112069)
* [API Server] Add Example App for reference use. * Remove Printlns. * Upgrade app-sdk to v0.46.0, update apps to handle breaking changes. * Only start the reconciler for the example app if the v1alpha1 API version is enabled. * Some comment doc updates. * Run make update-workspace * Set codeowner for /apps/example * Run make gofmt and make update-workspace * Run prettier on apps/example/README.md * Add COPY apps/example to Dockerfile * Add an authorizer to the example app. * Fix import ordering. * Update apps/example/kinds/manifest.cue Co-authored-by: Owen Diehl <ow.diehl@gmail.com> * Run make update-workspace * Re-run make gen-go for enterprise import updates * Run make update-workspace --------- Co-authored-by: Owen Diehl <ow.diehl@gmail.com>
This commit is contained in:
co-authored by
Owen Diehl
parent
d25f5199c7
commit
bf65c43783
@@ -0,0 +1,2 @@
|
||||
module: "github.com/grafana/grafana/apps/example/kinds"
|
||||
language: version: "v0.8.2"
|
||||
@@ -0,0 +1,52 @@
|
||||
package kinds
|
||||
|
||||
// This is our ExampleKind definition, which contains kind metadata. It is the same across all versions of the kind.
|
||||
exampleKind: {
|
||||
// Name is the human-readable name which is used for generated type names.
|
||||
kind: "Example"
|
||||
// Scope determines the scope of the kind in the API server. It currently allows two values:
|
||||
// * Namespaced - resources for this kind are created inside namespaces
|
||||
// * Cluster - resource for this kind are always cluster-wide (this can be thought of as a "global" namespace)
|
||||
// If not present, this defaults to "Namespaced"
|
||||
scope: "Namespaced"
|
||||
// [OPTIONAL]
|
||||
// The human-readable plural form of the "name" field.
|
||||
// Will default to <name>+"s" if not present.
|
||||
pluralName: "Examples"
|
||||
validation: {
|
||||
operations: [
|
||||
"CREATE",
|
||||
"UPDATE",
|
||||
]
|
||||
}
|
||||
mutation: {
|
||||
operations: [
|
||||
"CREATE",
|
||||
"UPDATE",
|
||||
]
|
||||
}
|
||||
conversion: true
|
||||
// [OPTIONAL]
|
||||
// Codegen is a trait that tells the grafana-app-sdk, or other code generation tooling, how to process this kind.
|
||||
// If not present, default values within the codegen trait are used.
|
||||
// If you wish to specify codegen per-version, put this section in the version's object
|
||||
// (for example, exampleKindv1alpha1) instead.
|
||||
codegen: {
|
||||
// [OPTIONAL]
|
||||
// ts contains TypeScript code generation properties for the kind
|
||||
ts: {
|
||||
// [OPTIONAL]
|
||||
// enabled indicates whether the CLI should generate front-end TypeScript code for the kind.
|
||||
// Defaults to true if not present.
|
||||
enabled: true
|
||||
}
|
||||
// [OPTIONAL]
|
||||
// go contains go code generation properties for the kind
|
||||
go: {
|
||||
// [OPTIONAL]
|
||||
// enabled indicates whether the CLI should generate back-end go code for the kind.
|
||||
// Defaults to true if not present.
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package kinds
|
||||
|
||||
// This is the v0alpha1 version of the kind. Please see v1alpha1 for more complete comments
|
||||
// and a more complex schema and set of capabilities.
|
||||
examplev0alpha1: exampleKind & {
|
||||
schema: {
|
||||
// Spec is the schema of our resource. The spec should include all the user-editable information for the kind.
|
||||
spec: {
|
||||
firstField: int
|
||||
}
|
||||
status: {
|
||||
lastObservedGeneration: int64
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package kinds
|
||||
|
||||
// This is the v1alpha1 version of the kind, which joins the kind metadata and
|
||||
// version-specific information for the kind, such as the schema
|
||||
examplev1alpha1: exampleKind & {
|
||||
// schema is the schema for this version of the kind
|
||||
// As an API server-expressable resource, the schema has a restricted format:
|
||||
// {
|
||||
// spec: { ... }
|
||||
// status: { ... } // optional
|
||||
// metadata: { ... } // optional
|
||||
// }
|
||||
// `spec` must always be present, and is the schema for the object.
|
||||
// `status` is optional, and should contain status or state information which is typically not user-editable
|
||||
// (controlled by controllers/operators). The kind system adds some implicit status information which is
|
||||
// common across all kinds, and becomes present in the unified lineage used for code generation and other tooling.
|
||||
// `metadata` is optional, and should contain kind- or schema-specific metadata. The kind system adds
|
||||
// an explicit set of common metadata which can be found in the definition file for a CUE kind at
|
||||
// [https://github.com/grafana/grafana-app-sdk/blob/main/codegen/cuekind/def.cue]
|
||||
// additional metadata fields cannot conflict with the common metadata field names
|
||||
schema: {
|
||||
// #DefinedType is a re-usable definition for us to use in our schema.
|
||||
// Fields leading with # are definitions in CUE and won't be included in the generated types.
|
||||
#DefinedType: {
|
||||
// Info is information about this entry. This comment, like all comments
|
||||
// on fields or definitions, will be copied into the generated types as well.
|
||||
info: string
|
||||
// Next is an optional next element in the DefinedType, allowing for a self-referential
|
||||
// linked-list like structure. The ? in the field makes this optional.
|
||||
next?: #DefinedType
|
||||
}
|
||||
// Spec is the schema of our resource. The spec should include all the user-editable information for the kind.
|
||||
spec: {
|
||||
// Example fields
|
||||
firstField: string
|
||||
secondField: int
|
||||
list?: #DefinedType
|
||||
}
|
||||
// status is where state and status information which may be used or updated by the operator or back-end should be placed
|
||||
// If you do not have any such information, you do not need to include this field,
|
||||
// however, as mentioned above, certain fields will be added by the kind system regardless.
|
||||
status: {
|
||||
lastObservedGeneration: int64
|
||||
}
|
||||
// Custom is a subresource that will be stored the same way status is stored,
|
||||
// and requires using the /custom route to update.
|
||||
// Its content is returned as part of a GET to the resource itself, just like with status.
|
||||
// To route a subresource to an arbitrary handler, use the 'routes' field instead (see below).
|
||||
custom: {
|
||||
myField: string
|
||||
otherField: string
|
||||
}
|
||||
// metadata if where kind- and schema-specific metadata goes. This is converted into typed annotations
|
||||
// with getters and setters by the code generation.
|
||||
//metadata: {
|
||||
// kindSpecificField: string
|
||||
//}
|
||||
}
|
||||
|
||||
// routes contains subresource routes for the kind, which are exposed as HTTP handlers on 'examples/<resource name>/<subresource>'.
|
||||
// This allows you to add additional non-storage-based handlers to your kind.
|
||||
// These should only be used if the behavior cannot be accomplished by reconciliation on storage events.
|
||||
routes: {
|
||||
// This will add a handler for /foo on the resource
|
||||
"foo": {
|
||||
// GET request handler. A subresource route can have multiple methods attached to it.
|
||||
// Allowed values are GET, POST, PUT, DELETE, PATCH, HEAD, and OPTIONS
|
||||
"GET": {
|
||||
// The response type for the GET /foo method. This will generate a go type, and will also be used for the OpenAPI definition for the route.
|
||||
response: {
|
||||
message: string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package kinds
|
||||
|
||||
manifest: {
|
||||
// appName is the unique name of your app. It is used to reference the app from other config objects,
|
||||
// and to generate the group used by your app in the app platform API.
|
||||
appName: "example"
|
||||
// groupOverride can be used to specify a non-appName-based API group.
|
||||
// By default, an app's API group is LOWER(REPLACE(appName, '-', '')).ext.grafana.com,
|
||||
// but there are cases where this needs to be changed.
|
||||
// Keep in mind that changing this after an app is deployed can cause problems with clients and/or kind data.
|
||||
groupOverride: "example.grafana.app"
|
||||
|
||||
// versions is a map of versions supported by your app. Version names should follow the format "v<integer>" or
|
||||
// "v<integer>(alpha|beta)<integer>". Each version contains the kinds your app manages for that version.
|
||||
// If your app needs access to kinds managed by another app, use permissions.accessKinds to allow your app access.
|
||||
versions: {
|
||||
"v0alpha1": v0alpha1
|
||||
"v1alpha1": v1alpha1
|
||||
}
|
||||
// extraPermissions contains any additional permissions your app may require to function.
|
||||
// Your app will always have all permissions for each kind it manages (the items defined in 'kinds').
|
||||
extraPermissions: {
|
||||
// If your app needs access to additional kinds supplied by other apps, you can list them here
|
||||
accessKinds: [
|
||||
// Here is an example for your app accessing the playlist kind for reads and watch
|
||||
// {
|
||||
// group: "playlist.grafana.app"
|
||||
// resource: "playlists"
|
||||
// actions: ["get","list","watch"]
|
||||
// }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
v0alpha1: {
|
||||
kinds: [examplev0alpha1]
|
||||
// This is explicitly set to false to keep the example app disabled by default.
|
||||
// It can be enabled via conf overrides, or by setting this value to true and regenerating.
|
||||
served: false
|
||||
}
|
||||
|
||||
// v1alpha1 is the v1alpha1 version of the app's API.
|
||||
// It includes kinds which the v1alpha1 API serves, and (future) custom routes served globally from the v1alpha1 version.
|
||||
v1alpha1: {
|
||||
// kinds is the list of kinds served by this version
|
||||
kinds:[examplev1alpha1]
|
||||
// [OPTIONAL]
|
||||
// served indicates whether this particular version is served by the API server.
|
||||
// served should be set to false before a version is removed from the manifest entirely.
|
||||
// served defaults to true if not present.
|
||||
// This is explicitly set to false to keep the example app disabled by default.
|
||||
// It can be enabled via conf overrides, or by setting this value to true and regenerating.
|
||||
served: false
|
||||
// routes contains resource routes for the version, which are split into 'namespaced' and 'cluster' scoped routes.
|
||||
// This allows you to add additional non-storage- and non-kind- based handlers for your app.
|
||||
// These should only be used if the behavior cannot be accomplished by reconciliation on storage events or subresource routes on a kind.
|
||||
routes: {
|
||||
// namespaced contains namespace-scoped resource routes for the version,
|
||||
// which are exposed as HTTP handlers on '<version>/namespaces/<namespace>/<route>'.
|
||||
namespaced: {
|
||||
"/something": {
|
||||
"GET": {
|
||||
response: {
|
||||
namespace: string
|
||||
message: string
|
||||
}
|
||||
request: {
|
||||
query: {
|
||||
message?: string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// cluster contains cluster-scoped resource routes for the version,
|
||||
// which are exposed as HTTP handlers on '<version>/<route>'.
|
||||
cluster: {
|
||||
"/other": {
|
||||
"GET": {
|
||||
response: {
|
||||
message: string
|
||||
}
|
||||
request: {
|
||||
query: {
|
||||
message?: string
|
||||
}
|
||||
}
|
||||
responseMetadata: typeMeta: false // Don't generate or return kubernetes type metadata for this object
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// [OPTIONAL]
|
||||
// Codegen is a trait that tells the grafana-app-sdk, or other code generation tooling, how to process this kind.
|
||||
// If not present, default values within the codegen trait are used.
|
||||
// If you wish to specify codegen per-version, put this section in the version's object
|
||||
// (for example, <no value>v1alpha1) instead.
|
||||
codegen: {
|
||||
// [OPTIONAL]
|
||||
// ts contains TypeScript code generation properties for the kind
|
||||
ts: {
|
||||
// [OPTIONAL]
|
||||
// enabled indicates whether the CLI should generate front-end TypeScript code for the kind.
|
||||
// Defaults to true if not present.
|
||||
enabled: true
|
||||
}
|
||||
// [OPTIONAL]
|
||||
// go contains go code generation properties for the kind
|
||||
go: {
|
||||
// [OPTIONAL]
|
||||
// enabled indicates whether the CLI should generate back-end go code for the kind.
|
||||
// Defaults to true if not present.
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user