Skip to content

Instantly share code, notes, and snippets.

@kylebrandt
Last active June 7, 2024 12:55
Show Gist options
  • Save kylebrandt/973bc9549fa1b2449b98d89c37ba0ea6 to your computer and use it in GitHub Desktop.
Save kylebrandt/973bc9549fa1b2449b98d89c37ba0ea6 to your computer and use it in GitHub Desktop.
ScopeNodes Example

Notes

  • NB" The "name" (id) fields are named using the path in these examples. This is not part of the API itself currently
  • e.g. http://localhost:3000/swagger?urls.primaryName=scope.grafana.app%2Fv0alpha1 for Swagger definitions.

Files

  • example.http: VSCode REST Client Extension HTTP Calls
  • scopesnodes.json: JSON output of ScopeNode kind items created in example.http
  • scopes.json: JSON output of Scope kind items created in example.http
  • find_no_param_response.json and find_parent_param_is_applications_response.json: The responses to the two calls to the find/scope_node_children endpoint that are in the example.http file

Example Node and Scope Structure

Scopes

There are two "application" scopes, slothPictureFactory (e.g. with filter app="slothPictureFactory") and slothVoteTracker. Then there are also two cluster scopes.

There is a fifth scope called indexHelperCluster that filters indexHelper="cluster". This exists to demonstrate a Scope being attached to a container in the following "Node Structure" section

Node Structure

Notes:

  • There are two Node Types: container and leaf.
  • All the leaf nodes in the example reference a scope. The Clusters and Applications/Clusters containers also reference a scope even though they are not leaves.
  • Bold is a container, for display only, containers are sorted before leaves within a container.

Structure:

  • Applications
    • Clusters
      • slothClusterNorth
      • slothClusterSouth
    • slothPictureFactory
    • slothVoteTracker
  • Clusters
    • Applications
      • slothPictureFactory
      • slothVoteTracker
    • slothClusterNorth
    • slothClusterSouth
### Scope Node Model
@baseURL = http://admin:admin@localhost:3000
@appKey = app
@myAppOne = slothPictureFactory
@myAppTwo = slothVoteTracker
@clusterKey = cluster
@myClusterOne = slothClusterNorth
@myClusterTwo = slothClusterSouth
## Create Some Scopes
### Make SlothPictureFactory Scope
POST {{baseURL}}/apis/scope.grafana.app/v0alpha1/namespaces/default/scopes
Content-Type: application/json
Accept: application/json
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "Scope",
"metadata": {
"name": "{{myAppOne}}"
},
"spec": {
"description": "{{myAppOne}}",
"filters": [
{
"key": "{{appKey}}",
"operator": "equals",
"value": "{{myAppOne}}"
}
],
"title": "{{myAppOne}}"
}
}
### Make slothVoteTracker Scope
POST {{baseURL}}/apis/scope.grafana.app/v0alpha1/namespaces/default/scopes
Content-Type: application/json
Accept: application/json
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "Scope",
"metadata": {
"name": "{{myAppTwo}}"
},
"spec": {
"description": "{{myAppTwo}}",
"filters": [
{
"key": "{{appKey}}",
"operator": "equals",
"value": "{{myAppTwo}}"
}
],
"title": "{{myAppTwo}}"
}
}
### Make slothClusterNorth Scope
POST {{baseURL}}/apis/scope.grafana.app/v0alpha1/namespaces/default/scopes
Content-Type: application/json
Accept: application/json
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "Scope",
"metadata": {
"name": "{{myClusterOne}}"
},
"spec": {
"description": "{{myClusterOne}}",
"filters": [
{
"key": "{{clusterKey}}",
"operator": "equals",
"value": "{{myClusterOne}}"
}
],
"title": "{{myClusterOne}}"
}
}
### Make slothClusterSouth Scope
POST {{baseURL}}/apis/scope.grafana.app/v0alpha1/namespaces/default/scopes
Content-Type: application/json
Accept: application/json
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "Scope",
"metadata": {
"name": "{{myClusterTwo}}"
},
"spec": {
"description": "{{myClusterTwo}}",
"filters": [
{
"key": "{{clusterKey}}",
"operator": "equals",
"value": "{{myClusterTwo}}"
}
],
"title": "{{myClusterTwo}}"
}
}
### Make indexHelperCluster Scope
POST {{baseURL}}/apis/scope.grafana.app/v0alpha1/namespaces/default/scopes
Content-Type: application/json
Accept: application/json
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "Scope",
"metadata": {
"name": "indexHelperCluster"
},
"spec": {
"description": "redundant label filter but makes queries faster",
"filters": [
{
"key": "indexHelper",
"operator": "equals",
"value": "cluster"
}
],
"title": "Cluster Index Helper"
}
}
## Build Container Nodes
### Create Top Container Node for Applications
POST {{baseURL}}/apis/scope.grafana.app/v0alpha1/namespaces/default/scopenodes
Content-Type: application/json
Accept: application/json
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "ScopeNode",
"metadata": {
"name": "applications"
},
"spec": {
"description": "Application Scopes",
"title": "Applications",
"nodeType": "container"
}
}
### Create Container Node Applications/Clusters
# Note: The "name" (id) has no special meaning, nodeA.nodeB is too help author/reader keep track
POST {{baseURL}}/apis/scope.grafana.app/v0alpha1/namespaces/default/scopenodes
Content-Type: application/json
Accept: application/json
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "ScopeNode",
"metadata": {
"name": "applications.clusters"
},
"spec": {
"description": "Application/Clusters Scopes",
"title": "Clusters",
"nodeType": "container",
"parentName": "applications",
"linkId": "indexHelperCluster",
"linkType": "scope"
}
}
### Create Top Container for Clusters
POST {{baseURL}}/apis/scope.grafana.app/v0alpha1/namespaces/default/scopenodes
Content-Type: application/json
Accept: application/json
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "ScopeNode",
"metadata": {
"name": "clusters"
},
"spec": {
"description": "Cluster Scopes",
"title": "Clusters",
"nodeType": "container",
"linkId": "indexHelperCluster",
"linkType": "scope"
}
}
### Create Container Node Clusters/Applications
POST {{baseURL}}/apis/scope.grafana.app/v0alpha1/namespaces/default/scopenodes
Content-Type: application/json
Accept: application/json
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "ScopeNode",
"metadata": {
"name": "clusters.application"
},
"spec": {
"description": "Clusters/Application Scopes",
"title": "Applications",
"nodeType": "container",
"parentName": "clusters"
}
}
## Create Leaf Nodes
### Create Leaf Nodes For Root Applications
#### Applications: SlothPictureFactory
POST {{baseURL}}/apis/scope.grafana.app/v0alpha1/namespaces/default/scopenodes
Content-Type: application/json
Accept: application/json
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "ScopeNode",
"metadata": {
"name": "applications-{{myAppOne}}"
},
"spec": {
"description": "{{myAppOne}}",
"title": "{{myAppOne}}",
"nodeType": "leaf",
"parentName": "applications",
"linkId": "{{myAppOne}}",
"linkType": "scope"
}
}
#### Applications: SlothVoteTracker
POST {{baseURL}}/apis/scope.grafana.app/v0alpha1/namespaces/default/scopenodes
Content-Type: application/json
Accept: application/json
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "ScopeNode",
"metadata": {
"name": "applications-{{myAppTwo}}"
},
"spec": {
"description": "{{myAppTwo}}",
"title": "{{myAppTwo}}",
"nodeType": "leaf",
"parentName": "applications",
"linkId": "{{myAppTwo}}",
"linkType": "scope"
}
}
### Create Leaf Nodes For Applications/Clusters
#### Applications/Clusters: SlothClusterNorth
POST {{baseURL}}/apis/scope.grafana.app/v0alpha1/namespaces/default/scopenodes
Content-Type: application/json
Accept: application/json
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "ScopeNode",
"metadata": {
"name": "applications.clusters-{{myClusterOne}}"
},
"spec": {
"description": "{{myClusterOne}}",
"title": "{{myClusterOne}}",
"nodeType": "leaf",
"parentName": "applications.clusters",
"linkId": "{{myClusterOne}}",
"linkType": "scope"
}
}
#### Applications/Clusters: SlothClusterSouth
POST {{baseURL}}/apis/scope.grafana.app/v0alpha1/namespaces/default/scopenodes
Content-Type: application/json
Accept: application/json
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "ScopeNode",
"metadata": {
"name": "applications.clusters-{{myClusterTwo}}"
},
"spec": {
"description": "{{myClusterTwo}}",
"title": "{{myClusterTwo}}",
"nodeType": "leaf",
"parentName": "applications.clusters",
"linkId": "{{myClusterTwo}}",
"linkType": "scope"
}
}
### Create Leaf Nodes For Root Clusters
#### Clusters: SlothClusterNorth
POST {{baseURL}}/apis/scope.grafana.app/v0alpha1/namespaces/default/scopenodes
Content-Type: application/json
Accept: application/json
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "ScopeNode",
"metadata": {
"name": "clusters-{{myClusterOne}}"
},
"spec": {
"description": "{{myClusterOne}}",
"title": "{{myClusterOne}}",
"nodeType": "leaf",
"parentName": "clusters",
"linkId": "{{myClusterOne}}",
"linkType": "scope"
}
}
#### Clusters: SlothClusterSouth
POST {{baseURL}}/apis/scope.grafana.app/v0alpha1/namespaces/default/scopenodes
Content-Type: application/json
Accept: application/json
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "ScopeNode",
"metadata": {
"name": "clusters-{{myClusterTwo}}"
},
"spec": {
"description": "{{myClusterTwo}}",
"title": "{{myClusterTwo}}",
"nodeType": "leaf",
"parentName": "clusters",
"linkId": "{{myClusterTwo}}",
"linkType": "scope"
}
}
### Create Leaf Nodes For Clusters/Applications
#### Clusters/Applications: slothPictureFactory
POST {{baseURL}}/apis/scope.grafana.app/v0alpha1/namespaces/default/scopenodes
Content-Type: application/json
Accept: application/json
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "ScopeNode",
"metadata": {
"name": "clusters.applications-{{myAppOne}}"
},
"spec": {
"description": "{{myAppOne}}",
"title": "{{myAppOne}}",
"nodeType": "leaf",
"parentName": "clusters.applications",
"linkId": "{{myAppOne}}",
"linkType": "scope"
}
}
#### Clusters/Applications: slothVoteTracker
POST {{baseURL}}/apis/scope.grafana.app/v0alpha1/namespaces/default/scopenodes
Content-Type: application/json
Accept: application/json
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "ScopeNode",
"metadata": {
"name": "slothPictureFactory"
},
"spec": {
"description": "{{myAppTwo}}",
"title": "{{myAppTwo}}",
"nodeType": "leaf",
"parentName": "clusters.applications",
"linkId": "{{myAppTwo}}",
"linkType": "scope"
}
}
### Delete Something
#DELETE {{baseURL}}/apis/scope.grafana.app/v0alpha1/namespaces/default/scopenodes/clusters
## Getting "Folders" (Container Nodes)
### Top Level (Forest)
GET {{baseURL}}/apis/scope.grafana.app/v0alpha1/namespaces/default/find/scope_node_children
Accept: application/json
### Top Level Applications
GET {{baseURL}}/apis/scope.grafana.app/v0alpha1/namespaces/default/find/scope_node_children?parent=applications
Accept: application/json
### Top Level Applications
GET {{baseURL}}/apis/scope.grafana.app/v0alpha1/namespaces/default/find/scope_node_children?parent=
Accept: application/json
{
"kind": "FindScopeNodeChildrenResults",
"apiVersion": "scope.grafana.app/v0alpha1",
"metadata": {},
"items": [
{
"kind": "ScopeNode",
"apiVersion": "scope.grafana.app/v0alpha1",
"metadata": {
"name": "applications",
"namespace": "default",
"uid": "a6d5c907-8a25-4dd5-a958-bd93fc28925f",
"resourceVersion": "1790389707893379072",
"creationTimestamp": "2024-05-14T14:32:24Z",
"managedFields": [
{
"manager": "vscode-restclient",
"operation": "Update",
"apiVersion": "scope.grafana.app/v0alpha1",
"time": "2024-05-14T14:32:24Z",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:spec": {
"f:description": {},
"f:nodeType": {},
"f:title": {}
}
}
}
]
},
"spec": {
"nodeType": "container",
"title": "Applications",
"description": "Application Scopes",
"disableMultiSelect": false
}
},
{
"kind": "ScopeNode",
"apiVersion": "scope.grafana.app/v0alpha1",
"metadata": {
"name": "clusters",
"namespace": "default",
"uid": "664c3b6b-4da3-4b60-a327-496909c091af",
"resourceVersion": "1790389762926841856",
"creationTimestamp": "2024-05-14T14:32:37Z",
"managedFields": [
{
"manager": "vscode-restclient",
"operation": "Update",
"apiVersion": "scope.grafana.app/v0alpha1",
"time": "2024-05-14T14:32:37Z",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:spec": {
"f:description": {},
"f:linkId": {},
"f:linkType": {},
"f:nodeType": {},
"f:title": {}
}
}
}
]
},
"spec": {
"nodeType": "container",
"title": "Clusters",
"description": "Cluster Scopes",
"disableMultiSelect": false,
"linkType": "scope",
"linkId": "indexHelperCluster"
}
}
]
}
{
"kind": "FindScopeNodeChildrenResults",
"apiVersion": "scope.grafana.app/v0alpha1",
"metadata": {},
"items": [
{
"kind": "ScopeNode",
"apiVersion": "scope.grafana.app/v0alpha1",
"metadata": {
"name": "applications-slothPictureFactory",
"namespace": "default",
"uid": "1c0781cb-26f2-4906-bd4b-97b2e1d312fc",
"resourceVersion": "1790389779053940736",
"creationTimestamp": "2024-05-14T14:32:41Z",
"managedFields": [
{
"manager": "vscode-restclient",
"operation": "Update",
"apiVersion": "scope.grafana.app/v0alpha1",
"time": "2024-05-14T14:32:41Z",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:spec": {
"f:description": {},
"f:linkId": {},
"f:linkType": {},
"f:nodeType": {},
"f:parentName": {},
"f:title": {}
}
}
}
]
},
"spec": {
"parentName": "applications",
"nodeType": "leaf",
"title": "slothPictureFactory",
"description": "slothPictureFactory",
"disableMultiSelect": false,
"linkType": "scope",
"linkId": "slothPictureFactory"
}
},
{
"kind": "ScopeNode",
"apiVersion": "scope.grafana.app/v0alpha1",
"metadata": {
"name": "applications-slothVoteTracker",
"namespace": "default",
"uid": "4edcc822-97c1-40a2-b20a-e2bb5409a062",
"resourceVersion": "1790389787564183552",
"creationTimestamp": "2024-05-14T14:32:43Z",
"managedFields": [
{
"manager": "vscode-restclient",
"operation": "Update",
"apiVersion": "scope.grafana.app/v0alpha1",
"time": "2024-05-14T14:32:43Z",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:spec": {
"f:description": {},
"f:linkId": {},
"f:linkType": {},
"f:nodeType": {},
"f:parentName": {},
"f:title": {}
}
}
}
]
},
"spec": {
"parentName": "applications",
"nodeType": "leaf",
"title": "slothVoteTracker",
"description": "slothVoteTracker",
"disableMultiSelect": false,
"linkType": "scope",
"linkId": "slothVoteTracker"
}
},
{
"kind": "ScopeNode",
"apiVersion": "scope.grafana.app/v0alpha1",
"metadata": {
"name": "applications.clusters",
"namespace": "default",
"uid": "5f484bd5-a5e2-414d-8c91-f63fa6c5c3e1",
"resourceVersion": "1790389744358658048",
"creationTimestamp": "2024-05-14T14:32:33Z",
"managedFields": [
{
"manager": "vscode-restclient",
"operation": "Update",
"apiVersion": "scope.grafana.app/v0alpha1",
"time": "2024-05-14T14:32:33Z",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:spec": {
"f:description": {},
"f:linkId": {},
"f:linkType": {},
"f:nodeType": {},
"f:parentName": {},
"f:title": {}
}
}
}
]
},
"spec": {
"parentName": "applications",
"nodeType": "container",
"title": "Clusters",
"description": "Application/Clusters Scopes",
"disableMultiSelect": false,
"linkType": "scope",
"linkId": "indexHelperCluster"
}
}
]
}
{
"kind": "FindScopeNodeChildrenResults",
"apiVersion": "scope.grafana.app/v0alpha1",
"metadata": {},
"items": [
{
"kind": "ScopeNode",
"apiVersion": "scope.grafana.app/v0alpha1",
"metadata": {
"name": "applications-slothPictureFactory",
"namespace": "default",
"uid": "1c0781cb-26f2-4906-bd4b-97b2e1d312fc",
"resourceVersion": "1790389779053940736",
"creationTimestamp": "2024-05-14T14:32:41Z",
"managedFields": [
{
"manager": "vscode-restclient",
"operation": "Update",
"apiVersion": "scope.grafana.app/v0alpha1",
"time": "2024-05-14T14:32:41Z",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:spec": {
"f:description": {},
"f:linkId": {},
"f:linkType": {},
"f:nodeType": {},
"f:parentName": {},
"f:title": {}
}
}
}
]
},
"spec": {
"parentName": "applications",
"nodeType": "leaf",
"title": "slothPictureFactory",
"description": "slothPictureFactory",
"disableMultiSelect": false,
"linkType": "scope",
"linkId": "slothPictureFactory"
}
},
{
"kind": "ScopeNode",
"apiVersion": "scope.grafana.app/v0alpha1",
"metadata": {
"name": "applications-slothVoteTracker",
"namespace": "default",
"uid": "4edcc822-97c1-40a2-b20a-e2bb5409a062",
"resourceVersion": "1790389787564183552",
"creationTimestamp": "2024-05-14T14:32:43Z",
"managedFields": [
{
"manager": "vscode-restclient",
"operation": "Update",
"apiVersion": "scope.grafana.app/v0alpha1",
"time": "2024-05-14T14:32:43Z",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:spec": {
"f:description": {},
"f:linkId": {},
"f:linkType": {},
"f:nodeType": {},
"f:parentName": {},
"f:title": {}
}
}
}
]
},
"spec": {
"parentName": "applications",
"nodeType": "leaf",
"title": "slothVoteTracker",
"description": "slothVoteTracker",
"disableMultiSelect": false,
"linkType": "scope",
"linkId": "slothVoteTracker"
}
},
{
"kind": "ScopeNode",
"apiVersion": "scope.grafana.app/v0alpha1",
"metadata": {
"name": "applications.clusters",
"namespace": "default",
"uid": "5f484bd5-a5e2-414d-8c91-f63fa6c5c3e1",
"resourceVersion": "1790389744358658048",
"creationTimestamp": "2024-05-14T14:32:33Z",
"managedFields": [
{
"manager": "vscode-restclient",
"operation": "Update",
"apiVersion": "scope.grafana.app/v0alpha1",
"time": "2024-05-14T14:32:33Z",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:spec": {
"f:description": {},
"f:linkId": {},
"f:linkType": {},
"f:nodeType": {},
"f:parentName": {},
"f:title": {}
}
}
}
]
},
"spec": {
"parentName": "applications",
"nodeType": "container",
"title": "Clusters",
"description": "Application/Clusters Scopes",
"disableMultiSelect": false,
"linkType": "scope",
"linkId": "indexHelperCluster"
}
}
]
}
[
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "Scope",
"metadata": {
"creationTimestamp": "2024-06-05T16:13:18Z",
"name": "indexHelperCluster",
"namespace": "default",
"resourceVersion": "1798387631478804480",
"uid": "a2d02a6b-bff0-4bbf-a5b0-8df6d26056be"
},
"spec": {
"description": "redundant label filter but makes queries faster",
"filters": [
{
"key": "indexHelper",
"operator": "equals",
"value": "cluster"
}
],
"title": "Cluster Index Helper"
}
},
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "Scope",
"metadata": {
"creationTimestamp": "2024-06-05T16:13:01Z",
"name": "slothClusterNorth",
"namespace": "default",
"resourceVersion": "1798387562239234048",
"uid": "3b1fe861-efb9-47fa-ba70-141b559fc0f0"
},
"spec": {
"description": "slothClusterNorth",
"filters": [
{
"key": "cluster",
"operator": "equals",
"value": "slothClusterNorth"
}
],
"title": "slothClusterNorth"
}
},
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "Scope",
"metadata": {
"creationTimestamp": "2024-06-05T16:13:04Z",
"name": "slothClusterSouth",
"namespace": "default",
"resourceVersion": "1798387572792102912",
"uid": "83c93159-320b-41d4-a535-9e2b23104208"
},
"spec": {
"description": "slothClusterSouth",
"filters": [
{
"key": "cluster",
"operator": "equals",
"value": "slothClusterSouth"
}
],
"title": "slothClusterSouth"
}
},
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "Scope",
"metadata": {
"creationTimestamp": "2024-06-05T16:12:53Z",
"name": "slothPictureFactory",
"namespace": "default",
"resourceVersion": "1798387526642176000",
"uid": "883d7c47-b4b3-4658-a550-8934127174eb"
},
"spec": {
"description": "slothPictureFactory",
"filters": [
{
"key": "app",
"operator": "equals",
"value": "slothPictureFactory"
}
],
"title": "slothPictureFactory"
}
},
{
"apiVersion": "scope.grafana.app/v0alpha1",
"kind": "Scope",
"metadata": {
"creationTimestamp": "2024-06-05T16:12:59Z",
"name": "slothVoteTracker",
"namespace": "default",
"resourceVersion": "1798387554051952640",
"uid": "9d2e0941-1216-41a7-b749-1edd440f7c3f"
},
"spec": {
"description": "slothVoteTracker",
"filters": [
{
"key": "app",
"operator": "equals",
"value": "slothVoteTracker"
}
],
"title": "slothVoteTracker"
}
}
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment