This project uses oapi-codegen to generate the core API client from the Landscape API OpenAPI spec. Update the generated code by setting the OPENAPI_SPEC environment variable to the path of the OpenAPI bundle and running the following:
cd client && go generate ./...Note
There is a workflow that automatically syncs the generated portions of this repository with the OpenAPI spec.
The client package contains the generated code (client.gen.go), its configuration, and a lightweight wrapper around it to make it usable. See examples for some examples that use the API client (without the CLI tool).
This project is used in the (WIP) Terraform provider for Landscape.
Caution
I mainly created the CLI tool for manually testing the API client and it's missing a lot. Ideally this could be generated as well.
This repository also contains a CLI wrapper around the generated code. First, build the CLI tool:
go build ./cmd/landscape-apiYou must provide the base URL of a Landscape Server instance as well as both an API access key and API secret key for it as flags or as environment variables. For example:
export LANDSCAPE_BASE_URL="https://landscape.canonical.com"
export LANDSCAPE_ACCESS_KEY="XXXXX"
export LANDSCAPE_SECRET_KEY="YYYYY"Alternatively, you can provide an email/password combination (and, optionally, an account to log into) if the Landscape instance accepts password-based authentication:
export LANDSCAPE_BASE_URL="https://landscape.example.com"
export LANDSCAPE_EMAIL="jan@example.com"
export LANDSCAPE_PASSWORD="5uper5ecurep@ssword!"
export LANDSCAPE_ACCOUNT="example-org"If set, these values will be used to attempt to log into Landscape, instead of the access key/secret key pair.
Tip
See the help text for the CLI by passing -h to any of the commands. For example:
./landscape-api -hNow, you can use the CLI tool to call the Landscape API. For example, to create a new V2 (versioned, with status) script:
./landscape-api script create -title coolscript -code $'#!/bin/bash\nB)' -script-type V2...
{
"id": 21433,
"title": "coolscript",
"version_number": 1,
"created_by": {
"id": 1234,
"name": "Jan-Yaeger Dhillon"
},
"created_at": "2025-11-10T02:56:25.366742",
"last_edited_by": {
"id": 1234,
"name": "Jan-Yaeger Dhillon"
},
"last_edited_at": "2025-11-10T02:56:25.366742",
"script_profiles": [],
"status": "ACTIVE",
"attachments": [],
"code": "B)",
"interpreter": "/bin/bash",
"access_group": "global",
"time_limit": 300,
"username": ""
}Edit it:
./landscape-api script edit 21433 -c $'#!/bin/bash\nBo)' -t coolerscript...
{
"id": 21433,
"title": "coolerscript",
"version_number": 2,
"created_by": {
"id": 1234,
"name": "Jan-Yaeger Dhillon"
},
"created_at": "2025-11-10T02:56:25.366742",
"last_edited_by": {
"id": 1234,
"name": "Jan-Yaeger Dhillon"
},
"last_edited_at": "2025-11-10T02:57:57.842792",
"script_profiles": [],
"status": "ACTIVE",
"attachments": [],
"code": "Bo)",
"interpreter": "/bin/bash",
"access_group": "global",
"time_limit": 300,
"username": ""
}Create an attachment for it:
code=$(echo "attachment" | base64)
./landscape-api script attachment create 21433 -f "attachment.txt\$\$$code"...
"attachment.txt"
View the script:
./landscape-api script get 21433...
{
"id": 21433,
"title": "coolerscript",
"version_number": 2,
"created_by": {
"id": 1234,
"name": "Jan-Yaeger Dhillon"
},
"created_at": "2025-11-10T02:56:25.366742",
"last_edited_by": {
"id": 1234,
"name": "Jan-Yaeger Dhillon"
},
"last_edited_at": "2025-11-10T02:57:57.842792",
"script_profiles": [],
"status": "ACTIVE",
"attachments": [
{
"filename": "attachment.txt",
"id": 50544
}
],
"code": "Bo)",
"interpreter": "/bin/bash",
"access_group": "global",
"time_limit": 300,
"username": "",
"is_redactable": true,
"is_editable": true,
"is_executable": true
}You can also create and manage V1 scripts (i.e., those shown in the legacy UI) by omitting the -script-type:
./landscape-api script create -title legacy-script -code $'#!/bin/bash\nlegacy script'...
{
"id": 21434,
"access_group": "global",
"creator": {
"name": "Jan-Yaeger Dhillon",
"email": "jan.dhillon@canonical.com",
"id": 1234
},
"title": "legacy-script",
"time_limit": 300,
"username": "",
"attachments": [],
"status": "V1"
}Create an attachment for it:
code=$(echo "legacy attachment" | base64)
./landscape-api script attachment create 21434 -f "legacy-attachment.txt\$\$$code"...
"legacy-attachment.txt"
View the script:
./landscape-api script get 21434...
{
"id": 21434,
"title": "legacy-script",
"creator": {
"id": 1234,
"name": "Jan-Yaeger Dhillon",
"email": "jan.dhillon@canonical.com"
},
"attachments": [
"legacy-attachment.txt"
],
"access_group": "global",
"time_limit": 300,
"username": "",
"status": "V1"
}