Menu
Grafana Cloud

Note

Fleet Management is currently in public preview. Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available.

The Collector API

API usage

NOTE TO SELF: CONTENT DUMP NO EDITS YET

Collector API

The collector API is pretty straightforward for CRUD operations on individual collectors. In case of success, it returns an empty payload with 200 - OK status code. Otherwise, an explanatory error message is returned instead.

--- create-collector.json ---
{
    "collector": {
        "id": "karasu",
        "attribute_overrides": {"mycustomattr": "mycustomval"},
        "name": "raven",
        "enabled": true
    }
}

--- update-collector.json ---
{
    "collector": {
        "id": "karasu",
        "attribute_overrides": {"mycustomattr": "mynewcustomval"},
        "enabled": true
    }
}

--- get-collector.json ---
{
    "id": "karasu"
}


--- delete-collector.json ---
{
    "id": "karasu"
}

Here’s how the requests look like using the above payloads

$ curl -q \
    -d @create-collector.json \
    -u "user:pass" \
    --header "Content-Type: application/json" \
    -X POST https://fleet-management-dev-001.grafana-dev.net/collector.v1.CollectorService/CreateCollector
{}%

$ curl -q \
    -d @create-collector.json \
    -u "user:pass" \
    --header "Content-Type: application/json" \
    -X POST https://fleet-management-dev-001.grafana-dev.net/collector.v1.CollectorService/CreateCollector
{}%

$ curl -q \
    -d @get-collector.json \
    -u "user:pass" \
    --header "Content-Type: application/json" \
    -X POST https://fleet-management-dev-001.grafana-dev.net/collector.v1.CollectorService/GetCollector
{"attributeOverrides":{"mycustomattr":"mynewcustomval"}, "createdAt":"2024-09-02T14:59:13Z", "updatedAt":"2024-09-02T16:18:38Z", "attributes":{"cluster":"dev", "collector.os":"linux", "collector.version":"v1.4.0-devel+wip", "namespace":"team-c"}, "enabled":true}

$ curl -q \
    -d @delete-collector.json \
    -u "user:pass" \
    --header "Content-Type: application/json" \
    -X POST https://fleet-management-dev-001.grafana-dev.net/collector.v1.CollectorService/DeleteCollector
{}%

$ curl -q \
    -d '{}' \
    -u "user:pass" \
    --header "Content-Type: application/json" \
    -X POST https://fleet-management-dev-001.grafana-dev.net/collector.v1.CollectorService/ListCollectors

$ curl -q \
    -d '{"matchers": ["collector.os=linux"]}' \
    -u "user:pass" \
    --header "Content-Type: application/json" \
    -X POST https://fleet-management-dev-001.grafana-dev.net/collector.v1.CollectorService/ListCollectors

Pipeline API

The pipeline API requires some more handling because requests and responses are generally longer and require proper escaping of the pipeline contents. For this reason, some use of jq is helpful. Let’s say that the contents of the pipeline are saved in a file named config.alloy.

--- config.alloy ---
prometheus.exporter.self "alloy" { }

prometheus.scrape "alloy" {
	targets    = prometheus.exporter.self.alloy.targets
	forward_to = [prometheus.remote_write.grafanacloud.receiver]

	scrape_interval = "60s"
}

prometheus.remote_write "grafanacloud" {
	// Must match the uniquely-identifiable ID set up in the remotecfg block.
	external_labels = {"collector_id" = constants.hostname}

	endpoint {
		url = "https://prometheus-dev-01-dev-us-central-0.grafana-dev.net/api/prom/push"

		basic_auth {
			username      = "20191"
			password_file = "/var/secrets/fleet-management-creds/api-user"
		}
	}
}

To build a payload for the CreatePipeline and UpsertPipeline requests with properly-escaped content, the following command is a good starting point:

jq --arg contents "$(cat config.alloy)" \
   --arg name "myname" \
   --argjson matchers '["collector.os=linux", "team!=team-a"]' \
   --argjson enabled true \
   '.pipeline = {name: $name, contents: $contents, matchers: $matchers, enabled: $enabled}' \
   <<< '{}' > create-pipeline.json

Here, it is redirected to a create-pipeline.json file for easier handling.

The CreatePipeline call response verifies what was created, and also lists the unique ID for this pipeline.

curl -q \
    -d @create-pipeline.json \
    -u "user:pass" \
    --header "Content-Type: application/json" \
    -X POST https://fleet-management-dev-001.grafana-dev.net/pipeline.v1.PipelineService/CreatePipeline
{
  "name": "myname",
  "contents": " ... pipeline contents ...",
  "matchers": [
    "collector.os=\"linux\"",
    "team!=\"team-a\""
  ],
  "enabled": true,
  "id": "22234"
}

The ListPipelines takes an empty payload and returns all available pipelines.

$  curl -q \
    -d '{}' \
    -u "user:pass" \
    --header "Content-Type: application/json" \
    -X POST https://fleet-management-dev-001.grafana-dev.net/pipeline.v1.PipelineService/ListPipelines
{
  "pipelines": [
    {
      "name": "pipeline_1",
      "contents": " ... pipeline contents ...",
      "matchers": [
        "team=\"team-a\""
      ],
      "createdAt": "2024-09-02T12:31:47Z",
      "updatedAt": "2024-09-02T14:08:10Z",
      "enabled": false,
      "id": "22231"
    },
    {
      "name": "pipeline_2",
      "contents": " ... pipeline contents ...",
      "matchers": [
        "collector.os=\"linux\"",
        "team!=\"team-a\""
      ],
      "createdAt": "2024-09-02T16:42:26Z",
      "updatedAt": "2024-09-02T16:42:26Z",
      "enabled": true,
      "id": "22234"
    }
  ]
}

We can use a similar jq command to build an UpdatePipeline command, by adding the unique pipeline ID

jq --arg contents "$(cat self.alloy)" \
   --arg id "22234" \
   --arg name "myname" \
   --argjson matchers '["collector.os=linux", "team!=team-a"]' \
   --argjson enabled true \
   '.pipeline = {id: $id, name: $name, contents: $contents, matchers: $matchers, enabled: $enabled}' \
   <<< '{}' > update-pipeline.json
{
  "name": "myname",
  "contents": " ... new pipeline contents ...",
  "matchers": [
    "collector.os=\"linux\"",
    "team!=\"team-a\""
  ],
  "enabled": true,
  "id": "22234"
}

Finally, the GetPipeline and DeletePipeline calls are simpler and only require an ID.

curl -q \
    -d '{"id": "22234"}' \
    -u "user:pass" \
    --header "Content-Type: application/json" \
    -X POST https://fleet-management-dev-001.grafana-dev.net/pipeline.v1.PipelineService/GetPipeline
{
  "name": "myname",
  "contents": "... pipeline contents ...",
  "matchers": [
    "collector.os=\"linux\"",
    "team!=\"team-a\""
  ],
  "createdAt": "2024-09-02T16:42:26Z",
  "updatedAt": "2024-09-02T16:42:26Z",
  "enabled": true,
  "id": "22234"
}

curl -q \
    -d '{"id": "22234"}' \
    -u "user:pass" \
    --header "Content-Type: application/json" \
    -X POST https://fleet-management-dev-001.grafana-dev.net/pipeline.v1.PipelineService/DeletePipeline
{}