asset

package
v1.17.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 27, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

SpamFilterSupportedAPIVersions lists the spam filter apiVersion values the CLI understands. Exported so callers can render the supported list in their own error messages.

Functions

func CarryRecordingRuleVersion added in v1.11.0

func CarryRecordingRuleVersion(src, dst *dash0api.RecordingRule)

CarryRecordingRuleVersion copies the version label from src to dst so that update requests include the optimistic-locking version the API currently requires.

func CheckAlertNameCollisions added in v1.17.0

func CheckAlertNameCollisions(names []PrometheusAlertName) error

CheckAlertNameCollisions validates that no two alerting rules in the same PrometheusRule CRD would derive the identical check-rule id. DeriveAlertCheckRuleID folds each alert's composed name through slugify, which collapses punctuation differences (e.g. "High CPU" and "High_CPU" both fold to "high-cpu") -- if that happens, both alerts would upsert to the identical derived id, silently overwriting each other exactly like the collision this derivation exists to prevent in the first place.

Called both from composePrometheusRuleNames (so apply's actual dispatch and check-rules create/update, which both go through ParseCheckRules, refuse the CRD) and from apply's own pre-flight validatePrometheusRule (so a multi-document apply run fails before any document is applied, not only once this specific CRD's turn comes up mid-run).

func CheckRuleIDsOccupiedByCRD added in v1.17.0

func CheckRuleIDsOccupiedByCRD(identifier string, alerts []PrometheusAlertName) []string

CheckRuleIDsOccupiedByCRD returns the check-rule ids a CRD's alerts live at: the CRD's literal identifier for zero or one alert, each alert's derived id for two or more. ids[i] is alerts[i]'s address, which --since's diff needs.

func DeriveAlertCheckRuleID added in v1.17.0

func DeriveAlertCheckRuleID(sharedID, composedName string) string

DeriveAlertCheckRuleID derives a per-alert check-rule identifier for a PrometheusRule CRD with more than one alerting rule, from the CRD's own shared id and the alert's composed name. See composePrometheusRuleNames' doc comment for the full rationale.

Exported so --since's whole-CRD deletion dispatch (internal/apply/since.go) can compute the exact same derived id per alert when the whole CRD is removed: the check rules that actually exist server-side for a multi-alert CRD live at these derived ids, never at the literal shared id, so deleting the CRD must target each of them individually rather than the shared id alone.

func DetectSpamFilterAPIVersion added in v1.12.2

func DetectSpamFilterAPIVersion(data []byte) (string, error)

DetectSpamFilterAPIVersion peeks at the apiVersion field on a YAML or JSON spam filter document so the caller can route to the matching client method. A missing value defaults to v1alpha1, matching the API client's decodeSpamFilterObject behavior. An unsupported value is rejected with the list of supported versions so the user knows what to fix.

func ExtractIdentifier added in v1.17.0

func ExtractIdentifier(data []byte) (string, error)

ExtractIdentifier returns the user-defined identifier a document is upserted by, or "" when the document carries none. The field location varies by kind, per the "Asset identifiers and idempotent upsert" table in the command reference:

  • Dashboard: metadata.dash0Extensions.id
  • CheckRule: top-level id
  • Dash0NotificationChannel: dash0.com/origin
  • Dash0SpamFilter, Dash0Team: dash0.com/origin, then dash0.com/id
  • everything else (PersesDashboard, PrometheusRule, SyntheticCheck, View): dash0.com/id

Each kind reads only the field its Import helper actually upserts by. A fallback onto some other field would return an identifier no live asset can match, which --since would then "delete" to a 404 and report as already deleted -- returning "" instead routes the document to the NoIdentifier hard-fail. Only teams and spam filters genuinely accept either field.

func FindNonHiddenYAMLFiles added in v1.17.0

func FindNonHiddenYAMLFiles(root string, files *[]string, sawNestedDir *bool) fs.WalkDirFunc

FindNonHiddenYAMLFiles returns a fs.WalkDirFunc for passing directly to filepath.WalkDir(root, ...): it appends every non-hidden .yaml/.yml file visited to *files and skips hidden files and directories (any path component starting with "."), via fs.SkipDir for directories. This is the one walk callback shared by apply's directory-scan and --since's disk-side scan, so both agree on what counts as an asset-definition file without hand-rolling the same callback twice; the filepath.WalkDir call itself stays at each call site for readability.

root itself is exempt from the hidden-name check even if it starts with "." — an -f target the user named explicitly (e.g. -f .dash0-assets/) is a deliberate choice, not something to skip. Only path components *inside* root are checked. ListYAMLFilesAtRef (internal/git/plumbing.go) mirrors this same exemption for --since's git-ref-side scan, so a dot-prefixed -f target means the same thing on both sides of the diff.

sawNestedDir, if non-nil, is set to true the first time the walk visits a non-hidden subdirectory of root — letting a caller tailor a "nothing found" message (e.g. "in <dir> and nested directories" vs a flat "in <dir>"). Pass nil when the caller doesn't need this.

func IsHiddenPath added in v1.17.0

func IsHiddenPath(path string) bool

IsHiddenPath reports whether any slash-separated component of path starts with "." — used to skip hidden files and directories consistently across a directory walk (a single entry name), a git ls-tree listing (a full repo-relative path), and any other path-filtering scan.

func IsValidKind added in v1.17.0

func IsValidKind(kind string) bool

IsValidKind reports whether kind (in any casing/hyphenation NormalizeKind accepts) is one of the Dash0 asset kinds apply/create/--since know how to handle. Used to distinguish a genuine Dash0 document from unrelated YAML (e.g. a stray Kubernetes ConfigMap) that happens to sit in a scanned scope.

func IsYAMLFile added in v1.17.0

func IsYAMLFile(path string) bool

IsYAMLFile reports whether path has a .yaml or .yml extension (case-insensitive) — the file types apply's directory scan and --since's git-ref/disk scans consider.

func KindDisplayName added in v1.1.0

func KindDisplayName(kind string) string

KindDisplayName returns the human-readable name for an asset kind. Multi-word kinds like "CheckRule" become "Check rule" and "SyntheticCheck" becomes "Synthetic check".

func NormalizeKind added in v1.17.0

func NormalizeKind(kind string) string

NormalizeKind lowercases kind, strips "-"/"_", and trims a leading "dash0" prefix, so callers can compare kind strings regardless of how they were cased or hyphenated in the source document (e.g. "Dash0Team" and "team" both normalize to "team").

func ParseCheckRules added in v1.15.4

func ParseCheckRules(data []byte) ([]*dash0api.PrometheusAlertRule, error)

ParseCheckRules parses a CheckRule or PrometheusRule CRD document into one or more check rules ready for import.

For PrometheusRule CRDs the check-rule name is composed as "<group name> - <alert name>", matching the Dash0 Kubernetes operator and the Terraform provider. A plain CheckRule document keeps its name verbatim.

The underlying SDK conversion (ParseAsPrometheusAlertRules) names each check rule after the alert only and discards the group name, so the group-name prefix is reapplied here from the raw CRD.

func PrintDiff added in v1.7.0

func PrintDiff(w io.Writer, displayKind, name string, before, after any) error

PrintDiff computes a unified diff between the before and after states of an asset and writes it to w. If there are no changes, a "no changes" message is printed instead.

func PrometheusRuleHasAlerts added in v1.12.2

func PrometheusRuleHasAlerts(crd *dash0api.RecordingRule) bool

PrometheusRuleHasAlerts reports whether any rule in the CRD is an alerting rule (has `alert:` set). Used by apply to decide whether to dispatch to the check-rule import path.

func PrometheusRuleHasRecordingRule added in v1.17.0

func PrometheusRuleHasRecordingRule(data []byte) (bool, error)

PrometheusRuleHasRecordingRule reports whether a PrometheusRule CRD document has at least one recording rule (a `record:` entry). Returns false for a document that isn't a PrometheusRule CRD at all.

--since uses this as a coarse presence/absence signal to detect a CRD that survives (its own identifier is still present in both snapshots) but whose recording-rule role disappeared entirely -- e.g. its last `record:` entry was removed while an `alert:` entry keeps the CRD's identifier alive. Unlike alerting rules, which become one check rule per alert (and so can be tracked and deleted individually by name), Dash0 models a CRD's recording rules as a single server-side resource, so there is no per-record identity to track -- only whether the role exists at all.

func ReadDefinition

func ReadDefinition(path string, target interface{}, stdin io.Reader) error

ReadDefinition reads a YAML or JSON definition from a file or stdin. If path is "-" or empty, it reads from stdin (assumes YAML format). Otherwise, it reads from the file at the given path.

func ReadDefinitionFile

func ReadDefinitionFile(path string, target interface{}) error

ReadDefinitionFile reads a YAML or JSON file and unmarshals into the target. It auto-detects the format based on file extension, falling back to YAML first.

func ReadRawInput added in v1.1.0

func ReadRawInput(path string, stdin io.Reader) ([]byte, error)

ReadRawInput reads raw bytes from a file or stdin without unmarshalling. If path is "-" or empty, it reads from stdin.

func RecordingOnlyPrometheusRule added in v1.12.2

func RecordingOnlyPrometheusRule(crd *dash0api.RecordingRule) *dash0api.RecordingRule

RecordingOnlyPrometheusRule returns a copy of the input PrometheusRule CRD stripped of alerting rules so it can be sent to the recording-rules API. Returns nil if the input contains no recording rules. Empty groups (after filtering) are dropped.

func RegisterCommonFlags

func RegisterCommonFlags(cmd *cobra.Command, flags *CommonFlags)

RegisterCommonFlags adds common flags to a command

func RegisterDeleteFlags

func RegisterDeleteFlags(cmd *cobra.Command, flags *DeleteFlags)

RegisterDeleteFlags adds delete-specific flags to a command

func RegisterFileInputFlags

func RegisterFileInputFlags(cmd *cobra.Command, flags *FileInputFlags)

RegisterFileInputFlags adds file input flags to a command and marks -f as required

func RegisterGetFlags

func RegisterGetFlags(cmd *cobra.Command, flags *GetFlags)

RegisterGetFlags adds get-specific flags to a command

func RegisterListFlags

func RegisterListFlags(cmd *cobra.Command, flags *ListFlags)

RegisterListFlags adds list-specific flags to a command

func RoutingAssetsWarning added in v1.16.4

func RoutingAssetsWarning(channel *dash0api.NotificationChannelDefinition) string

RoutingAssetsWarning returns a user-facing warning when the notification channel definition carries a non-empty spec.routing.assets, and an empty string otherwise. The Dash0 API treats spec.routing.assets as an API-managed back-reference (populated when a check rule or synthetic check binds to the channel) and silently ignores any value supplied on write — without a warning, users believe they attached the channel when nothing happened. The wording matches the Terraform provider's warnIfRoutingAssetsSet so both IaC clients speak the same language.

func SortSyntheticCheckPermissions added in v1.16.4

func SortSyntheticCheckPermissions(check *dash0api.SyntheticCheckDefinition)

SortSyntheticCheckPermissions is the SyntheticCheck equivalent of SortViewPermissions.

func SortViewPermissions added in v1.16.4

func SortViewPermissions(view *dash0api.ViewDefinition)

SortViewPermissions sorts a view's spec.permissions lexicographically. The server does not guarantee a stable order for this field (see issue #231), so the CLI normalizes it before display or diffing to avoid spurious reordering noise across repeated get/apply cycles.

func SpamFilterUsesOrigin added in v1.17.0

func SpamFilterUsesOrigin(data []byte) (bool, error)

SpamFilterUsesOrigin reports whether a spam filter document (v1alpha1 or v1alpha2 — both share the same metadata/labels shape) carries a non-empty dash0.com/origin label.

--since uses this to warn when a spam filter is about to be deleted by dash0.com/id alone: per ImportSpamFilter's upsert-key selection, an ID-only spam filter's id is reassigned server-side on its first PUT to a brand-new id, so the id recorded in the git history --since diffs against may no longer match the live asset's actual id by the time the document is deleted — deleting by that stale id either 404s (hard-failing without --force) or is silently treated as already-deleted (with --force), leaving the real live filter orphaned either way. There is no local, API-free way to recover the live id from git history alone; the origin label is the only identifier that never gets reassigned.

func WriteDefinitionFile

func WriteDefinitionFile(path string, data interface{}) error

WriteDefinitionFile writes data to a YAML or JSON file. It auto-detects the format based on file extension, defaulting to YAML.

func WriteToStdout

func WriteToStdout(format string, data interface{}) error

WriteToStdout writes data to stdout in the specified format. Format can be "yaml", "yml", or "json".

Types

type CommonFlags

type CommonFlags struct {
	ApiUrl    string
	AuthToken string
	Dataset   string
	Output    string
}

CommonFlags holds common flag values used across all asset commands

type DeleteFlags

type DeleteFlags struct {
	CommonFlags
	Force bool
}

DeleteFlags holds flags specific to delete commands

type FileInputFlags

type FileInputFlags struct {
	CommonFlags
	File   string
	DryRun bool
}

FileInputFlags holds flags for file-based input operations (create, update, apply)

type GetFlags

type GetFlags struct {
	CommonFlags
}

GetFlags holds flags specific to get commands

type ImportAction added in v1.1.0

type ImportAction string

ImportAction indicates whether an asset was created or updated.

const (
	ActionCreated ImportAction = "created"
	ActionUpdated ImportAction = "updated"
)

type ImportResult added in v1.1.0

type ImportResult struct {
	Name   string
	ID     string
	Action ImportAction
	Before any // asset state before update (nil for creates)
	After  any // asset state after update/create
}

ImportResult holds the outcome of importing an asset.

func ImportCheckRule added in v1.1.0

func ImportCheckRule(ctx context.Context, apiClient dash0api.Client, rule *dash0api.PrometheusAlertRule, dataset *string) (ImportResult, error)

ImportCheckRule creates or updates a check rule via the standard CRUD APIs. When the input has a user-defined ID, UPDATE is always used — PUT has create-or-replace semantics, so this is idempotent regardless of whether the rule already exists. When the input has no ID, CREATE is used and the server assigns an ID.

func ImportDashboard added in v1.1.0

func ImportDashboard(ctx context.Context, apiClient dash0api.Client, dashboard *dash0api.DashboardDefinition, dataset *string) (ImportResult, error)

ImportDashboard creates or updates a dashboard via the standard CRUD APIs. When the input has a user-defined ID, UPDATE is always used — PUT has create-or-replace semantics, so this is idempotent regardless of whether the dashboard already exists. When the input has no ID, CREATE is used and the server assigns an ID.

func ImportNotificationChannel added in v1.9.0

func ImportNotificationChannel(ctx context.Context, apiClient dash0api.Client, channel *dash0api.NotificationChannelDefinition) (ImportResult, error)

ImportNotificationChannel creates or updates a notification channel via the standard CRUD APIs. When the input has a user-defined ID (via dash0.com/origin label), UPDATE is always used — PUT has create-or-replace semantics, so this is idempotent regardless of whether the channel already exists. When the input has no origin, CREATE is used and the server assigns an ID.

func ImportRecordingRule added in v1.11.0

func ImportRecordingRule(ctx context.Context, apiClient dash0api.Client, rule *dash0api.RecordingRule, dataset *string) (ImportResult, error)

ImportRecordingRule creates or updates a recording rule via the standard CRUD APIs. When the input has a user-defined ID, UPDATE is always used — PUT has create-or-replace semantics, so this is idempotent regardless of whether the rule already exists. When the input has no ID, CREATE is used and the server assigns an ID.

func ImportSpamFilter added in v1.12.0

func ImportSpamFilter(ctx context.Context, apiClient dash0api.Client, filter *dash0api.SpamFilter, dataset *string) (ImportResult, error)

ImportSpamFilter creates or updates a v1alpha1 spam filter via the standard CRUD APIs.

Upsert key selection — important quirk of the spam filter API:

  • If the input has a user-defined origin (label `dash0.com/origin`), the origin is used as the upsert key. PUT to /spam-filters/{origin} creates the asset on first call and updates it on subsequent calls. This is the only reliable path to idempotent `apply`.
  • If the input has a user-defined ID (label `dash0.com/id`) but no origin, the ID is used as the upsert key. The server only honors this when a record already exists at that ID — a PUT to a brand-new ID generates a fresh server-side ID, so user-defined-id-only flows do not get true idempotency.
  • Otherwise, CREATE is used and the server assigns an ID.

dash0.com/id is captured before StripSpamFilterServerFields runs because that helper clears the id label along with the server source label.

func ImportSpamFilterV1Alpha2 added in v1.12.2

func ImportSpamFilterV1Alpha2(ctx context.Context, apiClient dash0api.Client, filter *dash0api.SpamFilterV1Alpha2, dataset *string) (ImportResult, error)

ImportSpamFilterV1Alpha2 mirrors ImportSpamFilter for the v1alpha2 schema. The v1alpha2 type carries spec.context (scalar) instead of spec.contexts (array); the rest of the lifecycle — upsert-key selection (origin first, ID fallback), existence check via GetSpamFilter, create-vs-update routing — is identical. See ImportSpamFilter for the rationale.

func ImportSyntheticCheck added in v1.1.0

func ImportSyntheticCheck(ctx context.Context, apiClient dash0api.Client, check *dash0api.SyntheticCheckDefinition, dataset *string) (ImportResult, error)

ImportSyntheticCheck creates or updates a synthetic check via the standard CRUD APIs. When the input has a user-defined ID, UPDATE is always used — PUT has create-or-replace semantics, so this is idempotent regardless of whether the check already exists. When the input has no ID, CREATE is used and the server assigns an ID.

func ImportTeam added in v1.16.0

func ImportTeam(ctx context.Context, apiClient dash0api.Client, team *dash0api.TeamDefinitionV1Alpha1) (ImportResult, error)

ImportTeam creates or upserts a team via the CRD Teams API.

Upsert key selection:

  • If the input has a user-defined origin (label `dash0.com/origin`), a preflight GetTeam runs against that origin. On hit, PUT is used to update in place. On miss, PUT is still used — the API treats origin PUT as create-or-replace, so the team materializes at the requested origin.
  • If the input has a user-defined ID (label `dash0.com/id`) but no origin, a preflight GetTeam gates the choice: on hit, PUT (idempotent update); on miss, POST (create fresh with a server-assigned id). The miss path matters for cross-environment apply: a YAML downloaded from one Dash0 org carries an id that does not exist in a different org's backend, and PUT-to-unknown-id returns 404. Falling back to POST keeps `apply` idempotent — the identifier in the file becomes advisory when it cannot be honored.
  • Otherwise, POST is used and the server assigns both id and origin.

dash0.com/id is captured before StripTeamServerFields runs because that helper clears the id label along with the server source label.

Before returning, spec.members on both the before and after states is translated from internal IDs (what the server echoes) to email addresses, so the apply diff renderer prints legible membership changes.

func ImportView added in v1.1.0

func ImportView(ctx context.Context, apiClient dash0api.Client, view *dash0api.ViewDefinition, dataset *string) (ImportResult, error)

ImportView creates or updates a view via the standard CRUD APIs. When the input has a user-defined ID, UPDATE is always used — PUT has create-or-replace semantics, so this is idempotent regardless of whether the view already exists. When the input has no ID, CREATE is used and the server assigns an ID.

type ListFlags

type ListFlags struct {
	CommonFlags
	Limit      int
	All        bool
	SkipHeader bool
}

ListFlags holds flags specific to list commands

type PrometheusAlertName added in v1.17.0

type PrometheusAlertName struct {
	GroupName string
	AlertName string
}

PrometheusAlertName identifies a single alerting rule inside a PrometheusRule CRD by the group it lives in and its own alert name.

Dash0 has no per-alert server-side id — a CRD's alerting rules share the CRD's own identifier — so this pair is the only stable handle on one alert within a CRD. --since uses it to resolve a removed alert by its composed check-rule name.

func ExtractPrometheusAlertNames added in v1.17.0

func ExtractPrometheusAlertNames(data []byte) ([]PrometheusAlertName, error)

ExtractPrometheusAlertNames parses a PrometheusRule CRD document and returns the (group name, alert name) pair for every alerting rule, in document order. Recording rules are skipped.

Unlike a struct-typed unmarshal (sigs.k8s.io/yaml decoding into a *string field, as PrometheusRuleEndpoints and the rest of this file otherwise use), this reads each name's literal scalar value directly off the raw YAML node tree. sigs.k8s.io/yaml's YAML->JSON->struct path resolves an unquoted YAML 1.1/1.2 boolean literal (Y, N, yes, no, on, off, true, false, and case variants) to a real JSON boolean, then silently coerces that boolean into the destination string field as "true"/"false" instead of erroring — so an alert genuinely named e.g. "Y" would otherwise be corrupted to "true" everywhere its name is used (the composed check-rule name here, and --since's alert-tracking diff in internal/git, which calls this function via internal/git/snapshot.go instead of dash0-api-client-go/yaml's identically-named, differently-implemented ExtractPrometheusAlertNames for exactly this reason).

func (PrometheusAlertName) CheckRuleName added in v1.17.0

func (p PrometheusAlertName) CheckRuleName() string

CheckRuleName composes the check-rule name Dash0 gives an alerting rule converted from a PrometheusRule CRD: "<group name> - <alert name>", matching the Dash0 Kubernetes operator and the Terraform provider.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL