diff --git a/README.md b/README.md index a6e0473..4079033 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,17 @@ Run `flashduty --help` for the commands in a group, and `flashduty ", + Short: "Get dedicated integration detail", + Long: `Get dedicated integration detail. + +Get one channel-owned integration, including its integration key and masked settings. + +API: POST /channel/integration/info (channel-integration-read-info) + +Request fields: + --integration-id int (required) — Dedicated integration ID returned by create, list, or info. Public integration IDs are not accepted. (min 1) + +Response fields ('data' envelope is unwrapped — these fields are at the top level): + - category (string) (required) — Integration category; dedicated integration creation accepts 'event.alert' alert integrations. + - channel_id (integer) (required) — ID of the channel that owns the dedicated integration. + - created_at (string) (required) — Creation time as a Unix timestamp in seconds. CLI '--json' renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null. + - description (string) (required) — Integration description; empty when unset. + - exclusive_data_source_id (integer) (required) — Compatibility identifier for earlier integrations; '0' when absent. Use 'integration_id' for this API group. + - integration_id (integer) (required) — Dedicated integration ID; use this ID for subsequent API calls. + - integration_key (string) (required) — Complete integration key for alert ingestion; separate from the management App Key. + - last_source_time (string) (required) — Source time of the most recent event as a Unix timestamp in seconds; '0' when unavailable. CLI '--json' renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null. + - last_time (string) (required) — Most recent received-event time as a Unix timestamp in seconds; '0' when no event has arrived. CLI '--json' renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null. + - name (string) (required) — Integration name. + - plugin_id (integer) (required) — Numeric integration type ID. Create uses the string 'plugin_type' instead. + - plugin_type (string) (required) — Integration type identifier, such as 'standard.alert'. + - plugin_type_name (string) (required) — Integration type display name, localized to the request language. + - settings (object) (required) — Integration-type-specific configuration; saved secret values in responses are masked as '******'. + - status (string) (required) — Lifecycle status: 'enabled' accepts alerts; 'disabled' pauses ingestion. [enabled, disabled] + - updated_at (string) (required) — Last update time as a Unix timestamp in seconds. CLI '--json' renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null. +`, + Args: requireBodyFieldOrExactArg("integration_id", "integration-id"), + Example: ` flashduty channel integration-info --data '{"integration_id":10001}'`, + RunE: func(cmd *cobra.Command, args []string) error { + return runCommand(cmd, args, func(ctx *RunContext) error { + body, err := genAssembleBody(dataJSON, func(body map[string]any) error { + if err := genFoldPositional(args, body, "integration_id", "int"); err != nil { + return err + } + if cmd.Flags().Changed("integration-id") { + body["integration_id"] = fIntegrationID + } + return nil + }) + if err != nil { + return err + } + req := new(flashduty.ChannelIntegrationIDRequest) + if err := genBindBody(ctx.Cmd.ErrOrStderr(), body, req); err != nil { + return err + } + out, _, err := ctx.Client.DedicatedIntegrations.ReadInfo(cmdContext(ctx.Cmd), req) + if err != nil { + return err + } + return printGenericResult(ctx, out, body, listDefaultsFor("DedicatedIntegrations", "ReadInfo")) + }) + }, + } + cmd.Flags().Int64Var(&fIntegrationID, "integration-id", 0, "Dedicated integration ID returned by create, list, or info. Public integration IDs are not accepted. (required) (min 1)") + cmd.Flags().StringVar(&dataJSON, "data", "", "Full request body as JSON; positional arguments and typed flags override its fields. Accepts inline JSON, or - to read stdin.") + return cmd +} + +func genDedicatedIntegrationsReadListCmd() *cobra.Command { + var dataJSON string + var fP int64 + var fLimit int64 + var fSearchAfterCtx string + var fChannelID int64 + var fName string + var fPluginType string + var fStatus string + cmd := &cobra.Command{ + Use: "integration-list ", + Short: "List dedicated integrations", + Long: `List dedicated integrations. + +List the dedicated integrations owned by one channel. + +API: POST /channel/integration/list (channel-integration-read-list) + +Request fields: + --page int — Page number, starting at 1. (min 1) + --limit int — Number of items per page, at most 100. (1-100) + --search-after-ctx string + --channel-id int (required) — Channel ID to list dedicated integrations for. (min 1) + --name string — Filter by integration name. (≤49 chars) + --plugin-type string — Filter by one integration type. + --status string — Filter by 'enabled' integrations that accept alerts or 'disabled' integrations that pause ingestion. [enabled, disabled] + +Response fields ('data' envelope is unwrapped — rows are nested under items[]; pipe 'jq '.items[]'', NOT '.data.items[]'): + - items (array) (required) — Dedicated integrations on this page. + - category (string) (required) — Integration category; dedicated integration creation accepts 'event.alert' alert integrations. + - channel_id (integer) (required) — ID of the channel that owns the dedicated integration. + - created_at (string) (required) — Creation time as a Unix timestamp in seconds. CLI '--json' renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null. + - description (string) (required) — Integration description; empty when unset. + - exclusive_data_source_id (integer) (required) — Compatibility identifier for earlier integrations; '0' when absent. Use 'integration_id' for this API group. + - integration_id (integer) (required) — Dedicated integration ID; use this ID for subsequent API calls. + - integration_key (string) (required) — Complete integration key for alert ingestion; separate from the management App Key. + - last_source_time (string) (required) — Source time of the most recent event as a Unix timestamp in seconds; '0' when unavailable. CLI '--json' renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null. + - last_time (string) (required) — Most recent received-event time as a Unix timestamp in seconds; '0' when no event has arrived. CLI '--json' renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null. + - name (string) (required) — Integration name. + - plugin_id (integer) (required) — Numeric integration type ID. Create uses the string 'plugin_type' instead. + - plugin_type (string) (required) — Integration type identifier, such as 'standard.alert'. + - plugin_type_name (string) (required) — Integration type display name, localized to the request language. + - settings (object) (required) — Integration-type-specific configuration; saved secret values in responses are masked as '******'. + - status (string) (required) — Lifecycle status: 'enabled' accepts alerts; 'disabled' pauses ingestion. [enabled, disabled] + - updated_at (string) (required) — Last update time as a Unix timestamp in seconds. CLI '--json' renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null. + - limit (integer) (required) — Returned page size. + - p (integer) (required) — Returned page number. + - total (integer) (required) — Total number of matching dedicated integrations. +`, + Args: requireBodyFieldOrExactArg("channel_id", "channel-id"), + Example: ` flashduty channel integration-list --data '{"channel_id":20001,"limit":20,"p":1}'`, + RunE: func(cmd *cobra.Command, args []string) error { + return runCommand(cmd, args, func(ctx *RunContext) error { + body, err := genAssembleBody(dataJSON, func(body map[string]any) error { + if err := genFoldPositional(args, body, "channel_id", "int"); err != nil { + return err + } + if cmd.Flags().Changed("page") { + body["p"] = fP + } + if cmd.Flags().Changed("limit") { + body["limit"] = fLimit + } + if cmd.Flags().Changed("search-after-ctx") { + body["search_after_ctx"] = fSearchAfterCtx + } + if cmd.Flags().Changed("channel-id") { + body["channel_id"] = fChannelID + } + if cmd.Flags().Changed("name") { + body["name"] = fName + } + if cmd.Flags().Changed("plugin-type") { + body["plugin_type"] = fPluginType + } + if cmd.Flags().Changed("status") { + body["status"] = fStatus + } + return nil + }) + if err != nil { + return err + } + req := new(flashduty.ChannelIntegrationListRequest) + if err := genBindBody(ctx.Cmd.ErrOrStderr(), body, req); err != nil { + return err + } + out, _, err := ctx.Client.DedicatedIntegrations.ReadList(cmdContext(ctx.Cmd), req) + if err != nil { + return err + } + return printGenericResult(ctx, out, body, listDefaultsFor("DedicatedIntegrations", "ReadList")) + }) + }, + } + cmd.Flags().Int64Var(&fP, "page", 0, "Page number, starting at 1. (min 1)") + cmd.Flags().Int64Var(&fLimit, "limit", 0, "Number of items per page, at most 100. (1-100)") + cmd.Flags().StringVar(&fSearchAfterCtx, "search-after-ctx", "", "Request field ") + cmd.Flags().Int64Var(&fChannelID, "channel-id", 0, "Channel ID to list dedicated integrations for. (required) (min 1)") + cmd.Flags().StringVar(&fName, "name", "", "Filter by integration name. (≤49 chars)") + cmd.Flags().StringVar(&fPluginType, "plugin-type", "", "Filter by one integration type.") + cmd.Flags().StringVar(&fStatus, "status", "", "Filter by 'enabled' integrations that accept alerts or 'disabled' integrations that pause ingestion. [enabled, disabled]") + cmd.Flags().StringVar(&dataJSON, "data", "", "Full request body as JSON; positional arguments and typed flags override its fields. Accepts inline JSON, or - to read stdin.") + return cmd +} + +func genDedicatedIntegrationsWriteCreateCmd() *cobra.Command { + var dataJSON string + var fChannelID int64 + var fDescription string + var fIntegrationKey string + var fName string + var fPluginType string + cmd := &cobra.Command{ + Use: "integration-create ", + Short: "Create dedicated integration", + Long: `Create dedicated integration. + +Create a dedicated alert integration for an enabled channel. + +API: POST /channel/integration/create (channel-integration-write-create) + +Request fields: + --channel-id int (required) — Target channel ID; the channel must be enabled. (min 1) + --description string — Description, at most 499 characters. (≤499 chars) + --integration-key string — Optional supplied integration key. A non-empty value must have 35 characters, match the account suffix, and be unique. (≤35 chars) + --name string — Integration name, 2–49 characters when supplied; omitted or empty uses the integration type default. (≤49 chars) + --plugin-type string (required) — Enabled alert integration type identifier, such as 'standard.alert'. + settings (object, via --data) — Integration-type-specific configuration; saved secret values in responses are masked as '******'. + +Response fields ('data' envelope is unwrapped — these fields are at the top level): + - integration_id (integer) (required) — Created dedicated integration ID. + - integration_key (string) (required) — Integration key for alert ingestion. +`, + Args: requireBodyFieldOrExactArg("channel_id", "channel-id"), + Example: ` flashduty channel integration-create --data '{"channel_id":20001,"description":"Alerts for the payments channel","name":"Payments alerts","plugin_type":"standard.alert","settings":{}}'`, + RunE: func(cmd *cobra.Command, args []string) error { + return runCommand(cmd, args, func(ctx *RunContext) error { + body, err := genAssembleBody(dataJSON, func(body map[string]any) error { + if err := genFoldPositional(args, body, "channel_id", "int"); err != nil { + return err + } + if cmd.Flags().Changed("channel-id") { + body["channel_id"] = fChannelID + } + if cmd.Flags().Changed("description") { + body["description"] = fDescription + } + if cmd.Flags().Changed("integration-key") { + body["integration_key"] = fIntegrationKey + } + if cmd.Flags().Changed("name") { + body["name"] = fName + } + if cmd.Flags().Changed("plugin-type") { + body["plugin_type"] = fPluginType + } + return nil + }) + if err != nil { + return err + } + req := new(flashduty.ChannelIntegrationCreateRequest) + if err := genBindBody(ctx.Cmd.ErrOrStderr(), body, req); err != nil { + return err + } + out, _, err := ctx.Client.DedicatedIntegrations.WriteCreate(cmdContext(ctx.Cmd), req) + if err != nil { + return err + } + return printGenericResult(ctx, out, body, listDefaultsFor("DedicatedIntegrations", "WriteCreate")) + }) + }, + } + cmd.Flags().Int64Var(&fChannelID, "channel-id", 0, "Target channel ID; the channel must be enabled. (required) (min 1)") + cmd.Flags().StringVar(&fDescription, "description", "", "Description, at most 499 characters. (≤499 chars)") + cmd.Flags().StringVar(&fIntegrationKey, "integration-key", "", "Optional supplied integration key. A non-empty value must have 35 characters, match the account suffix, and be unique. (≤35 chars)") + cmd.Flags().StringVar(&fName, "name", "", "Integration name, 2–49 characters when supplied; omitted or empty uses the integration type default. (≤49 chars)") + cmd.Flags().StringVar(&fPluginType, "plugin-type", "", "Enabled alert integration type identifier, such as 'standard.alert'. (required)") + cmd.Flags().StringVar(&dataJSON, "data", "", "Full request body as JSON; positional arguments and typed flags override its fields. Accepts inline JSON, or - to read stdin.") + return cmd +} + +func genDedicatedIntegrationsWriteDeleteCmd() *cobra.Command { + var dataJSON string + var fIntegrationID int64 + cmd := &cobra.Command{ + Use: "integration-delete ", + Short: "Delete dedicated integration", + Long: `Delete dedicated integration. + +Delete a dedicated integration after its references have been removed. + +API: POST /channel/integration/delete (channel-integration-write-delete) + +Request fields: + --integration-id int (required) — Dedicated integration ID returned by create, list, or info. Public integration IDs are not accepted. (min 1) +`, + Args: requireBodyFieldOrExactArg("integration_id", "integration-id"), + Example: ` flashduty channel integration-delete --data '{"integration_id":10001}'`, + RunE: func(cmd *cobra.Command, args []string) error { + return runCommand(cmd, args, func(ctx *RunContext) error { + body, err := genAssembleBody(dataJSON, func(body map[string]any) error { + if err := genFoldPositional(args, body, "integration_id", "int"); err != nil { + return err + } + if cmd.Flags().Changed("integration-id") { + body["integration_id"] = fIntegrationID + } + return nil + }) + if err != nil { + return err + } + req := new(flashduty.ChannelIntegrationIDRequest) + if err := genBindBody(ctx.Cmd.ErrOrStderr(), body, req); err != nil { + return err + } + resp, err := ctx.Client.DedicatedIntegrations.WriteDelete(cmdContext(ctx.Cmd), req) + if err != nil { + return err + } + if resp != nil && len(resp.Raw) > 0 { + return ctx.WriteRaw(resp.Raw) + } + ctx.WriteResult("OK: POST /channel/integration/delete") + return nil + }) + }, + } + cmd.Flags().Int64Var(&fIntegrationID, "integration-id", 0, "Dedicated integration ID returned by create, list, or info. Public integration IDs are not accepted. (required) (min 1)") + cmd.Flags().StringVar(&dataJSON, "data", "", "Full request body as JSON; positional arguments and typed flags override its fields. Accepts inline JSON, or - to read stdin.") + return cmd +} + +func genDedicatedIntegrationsWriteDisableCmd() *cobra.Command { + var dataJSON string + var fIntegrationID int64 + cmd := &cobra.Command{ + Use: "integration-disable ", + Short: "Disable dedicated integration", + Long: `Disable dedicated integration. + +Disable a dedicated integration to pause alert ingestion. + +API: POST /channel/integration/disable (channel-integration-write-disable) + +Request fields: + --integration-id int (required) — Dedicated integration ID returned by create, list, or info. Public integration IDs are not accepted. (min 1) +`, + Args: requireBodyFieldOrExactArg("integration_id", "integration-id"), + Example: ` flashduty channel integration-disable --data '{"integration_id":10001}'`, + RunE: func(cmd *cobra.Command, args []string) error { + return runCommand(cmd, args, func(ctx *RunContext) error { + body, err := genAssembleBody(dataJSON, func(body map[string]any) error { + if err := genFoldPositional(args, body, "integration_id", "int"); err != nil { + return err + } + if cmd.Flags().Changed("integration-id") { + body["integration_id"] = fIntegrationID + } + return nil + }) + if err != nil { + return err + } + req := new(flashduty.ChannelIntegrationIDRequest) + if err := genBindBody(ctx.Cmd.ErrOrStderr(), body, req); err != nil { + return err + } + resp, err := ctx.Client.DedicatedIntegrations.WriteDisable(cmdContext(ctx.Cmd), req) + if err != nil { + return err + } + if resp != nil && len(resp.Raw) > 0 { + return ctx.WriteRaw(resp.Raw) + } + ctx.WriteResult("OK: POST /channel/integration/disable") + return nil + }) + }, + } + cmd.Flags().Int64Var(&fIntegrationID, "integration-id", 0, "Dedicated integration ID returned by create, list, or info. Public integration IDs are not accepted. (required) (min 1)") + cmd.Flags().StringVar(&dataJSON, "data", "", "Full request body as JSON; positional arguments and typed flags override its fields. Accepts inline JSON, or - to read stdin.") + return cmd +} + +func genDedicatedIntegrationsWriteEnableCmd() *cobra.Command { + var dataJSON string + var fIntegrationID int64 + cmd := &cobra.Command{ + Use: "integration-enable ", + Short: "Enable dedicated integration", + Long: `Enable dedicated integration. + +Enable a dedicated integration so it can receive alerts. + +API: POST /channel/integration/enable (channel-integration-write-enable) + +Request fields: + --integration-id int (required) — Dedicated integration ID returned by create, list, or info. Public integration IDs are not accepted. (min 1) +`, + Args: requireBodyFieldOrExactArg("integration_id", "integration-id"), + Example: ` flashduty channel integration-enable --data '{"integration_id":10001}'`, + RunE: func(cmd *cobra.Command, args []string) error { + return runCommand(cmd, args, func(ctx *RunContext) error { + body, err := genAssembleBody(dataJSON, func(body map[string]any) error { + if err := genFoldPositional(args, body, "integration_id", "int"); err != nil { + return err + } + if cmd.Flags().Changed("integration-id") { + body["integration_id"] = fIntegrationID + } + return nil + }) + if err != nil { + return err + } + req := new(flashduty.ChannelIntegrationIDRequest) + if err := genBindBody(ctx.Cmd.ErrOrStderr(), body, req); err != nil { + return err + } + resp, err := ctx.Client.DedicatedIntegrations.WriteEnable(cmdContext(ctx.Cmd), req) + if err != nil { + return err + } + if resp != nil && len(resp.Raw) > 0 { + return ctx.WriteRaw(resp.Raw) + } + ctx.WriteResult("OK: POST /channel/integration/enable") + return nil + }) + }, + } + cmd.Flags().Int64Var(&fIntegrationID, "integration-id", 0, "Dedicated integration ID returned by create, list, or info. Public integration IDs are not accepted. (required) (min 1)") + cmd.Flags().StringVar(&dataJSON, "data", "", "Full request body as JSON; positional arguments and typed flags override its fields. Accepts inline JSON, or - to read stdin.") + return cmd +} + +func genDedicatedIntegrationsWriteRotateKeyCmd() *cobra.Command { + var dataJSON string + var fIntegrationID int64 + cmd := &cobra.Command{ + Use: "integration-key-rotate ", + Short: "Rotate dedicated integration key", + Long: `Rotate dedicated integration key. + +Issue a new dedicated integration key and invalidate the previous key. + +API: POST /channel/integration/key/rotate (channel-integration-write-rotate-key) + +Request fields: + --integration-id int (required) — Dedicated integration ID returned by create, list, or info. Public integration IDs are not accepted. (min 1) + +Response fields ('data' envelope is unwrapped — these fields are at the top level): + - integration_key (string) (required) — New integration key; the previous key stops working immediately. +`, + Args: requireBodyFieldOrExactArg("integration_id", "integration-id"), + Example: ` flashduty channel integration-key-rotate --data '{"integration_id":10001}'`, + RunE: func(cmd *cobra.Command, args []string) error { + return runCommand(cmd, args, func(ctx *RunContext) error { + body, err := genAssembleBody(dataJSON, func(body map[string]any) error { + if err := genFoldPositional(args, body, "integration_id", "int"); err != nil { + return err + } + if cmd.Flags().Changed("integration-id") { + body["integration_id"] = fIntegrationID + } + return nil + }) + if err != nil { + return err + } + req := new(flashduty.ChannelIntegrationIDRequest) + if err := genBindBody(ctx.Cmd.ErrOrStderr(), body, req); err != nil { + return err + } + out, _, err := ctx.Client.DedicatedIntegrations.WriteRotateKey(cmdContext(ctx.Cmd), req) + if err != nil { + return err + } + return printGenericResult(ctx, out, body, listDefaultsFor("DedicatedIntegrations", "WriteRotateKey")) + }) + }, + } + cmd.Flags().Int64Var(&fIntegrationID, "integration-id", 0, "Dedicated integration ID returned by create, list, or info. Public integration IDs are not accepted. (required) (min 1)") + cmd.Flags().StringVar(&dataJSON, "data", "", "Full request body as JSON; positional arguments and typed flags override its fields. Accepts inline JSON, or - to read stdin.") + return cmd +} + +func genDedicatedIntegrationsWriteUpdateCmd() *cobra.Command { + var dataJSON string + var fDescription string + var fIntegrationID int64 + var fName string + cmd := &cobra.Command{ + Use: "integration-update ", + Short: "Update dedicated integration", + Long: `Update dedicated integration. + +Update the name, description, or settings of a dedicated integration. + +API: POST /channel/integration/update (channel-integration-write-update) + +Request fields: + --description string — New description, at most 499 characters; empty clears it, omitted or null keeps it. (≤499 chars) + --integration-id int (required) — Dedicated integration ID returned by create, list, or info. Public integration IDs are not accepted. (min 1) + --name string — New name, 2–49 characters; omitted or null keeps the stored name. (2-49 chars) + settings (object, via --data) — Replacement type-specific configuration. Omitted or null keeps it; masked or omitted secret fields retain their stored value. + +Response fields ('data' envelope is unwrapped — these fields are at the top level): + - category (string) (required) — Integration category; dedicated integration creation accepts 'event.alert' alert integrations. + - channel_id (integer) (required) — ID of the channel that owns the dedicated integration. + - created_at (string) (required) — Creation time as a Unix timestamp in seconds. CLI '--json' renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null. + - description (string) (required) — Integration description; empty when unset. + - exclusive_data_source_id (integer) (required) — Compatibility identifier for earlier integrations; '0' when absent. Use 'integration_id' for this API group. + - integration_id (integer) (required) — Dedicated integration ID; use this ID for subsequent API calls. + - integration_key (string) (required) — Complete integration key for alert ingestion; separate from the management App Key. + - last_source_time (string) (required) — Source time of the most recent event as a Unix timestamp in seconds; '0' when unavailable. CLI '--json' renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null. + - last_time (string) (required) — Most recent received-event time as a Unix timestamp in seconds; '0' when no event has arrived. CLI '--json' renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null. + - name (string) (required) — Integration name. + - plugin_id (integer) (required) — Numeric integration type ID. Create uses the string 'plugin_type' instead. + - plugin_type (string) (required) — Integration type identifier, such as 'standard.alert'. + - plugin_type_name (string) (required) — Integration type display name, localized to the request language. + - settings (object) (required) — Integration-type-specific configuration; saved secret values in responses are masked as '******'. + - status (string) (required) — Lifecycle status: 'enabled' accepts alerts; 'disabled' pauses ingestion. [enabled, disabled] + - updated_at (string) (required) — Last update time as a Unix timestamp in seconds. CLI '--json' renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null. +`, + Args: requireBodyFieldOrExactArg("integration_id", "integration-id"), + Example: ` flashduty channel integration-update --data '{"description":"","integration_id":10001,"name":"Payments production alerts"}'`, + RunE: func(cmd *cobra.Command, args []string) error { + return runCommand(cmd, args, func(ctx *RunContext) error { + body, err := genAssembleBody(dataJSON, func(body map[string]any) error { + if err := genFoldPositional(args, body, "integration_id", "int"); err != nil { + return err + } + if cmd.Flags().Changed("description") { + body["description"] = fDescription + } + if cmd.Flags().Changed("integration-id") { + body["integration_id"] = fIntegrationID + } + if cmd.Flags().Changed("name") { + body["name"] = fName + } + return nil + }) + if err != nil { + return err + } + req := new(flashduty.ChannelIntegrationUpdateRequest) + if err := genBindBody(ctx.Cmd.ErrOrStderr(), body, req); err != nil { + return err + } + out, _, err := ctx.Client.DedicatedIntegrations.WriteUpdate(cmdContext(ctx.Cmd), req) + if err != nil { + return err + } + return printGenericResult(ctx, out, body, listDefaultsFor("DedicatedIntegrations", "WriteUpdate")) + }) + }, + } + cmd.Flags().StringVar(&fDescription, "description", "", "New description, at most 499 characters; empty clears it, omitted or null keeps it. (≤499 chars)") + cmd.Flags().Int64Var(&fIntegrationID, "integration-id", 0, "Dedicated integration ID returned by create, list, or info. Public integration IDs are not accepted. (required) (min 1)") + cmd.Flags().StringVar(&fName, "name", "", "New name, 2–49 characters; omitted or null keeps the stored name. (2-49 chars)") + cmd.Flags().StringVar(&dataJSON, "data", "", "Full request body as JSON; positional arguments and typed flags override its fields. Accepts inline JSON, or - to read stdin.") + return cmd +} + +func registerGeneratedDedicatedIntegrations(root *cobra.Command) { + gChannel := genGroup(root, "channel", "On-call API") + genAddLeaf(gChannel, genDedicatedIntegrationsReadInfoCmd()) + genAddLeaf(gChannel, genDedicatedIntegrationsReadListCmd()) + genAddLeaf(gChannel, genDedicatedIntegrationsWriteCreateCmd()) + genAddLeaf(gChannel, genDedicatedIntegrationsWriteDeleteCmd()) + genAddLeaf(gChannel, genDedicatedIntegrationsWriteDisableCmd()) + genAddLeaf(gChannel, genDedicatedIntegrationsWriteEnableCmd()) + genAddLeaf(gChannel, genDedicatedIntegrationsWriteRotateKeyCmd()) + genAddLeaf(gChannel, genDedicatedIntegrationsWriteUpdateCmd()) +} diff --git a/internal/cli/zz_generated_integrations.go b/internal/cli/zz_generated_integrations.go index 935a3b3..1e46499 100644 --- a/internal/cli/zz_generated_integrations.go +++ b/internal/cli/zz_generated_integrations.go @@ -64,8 +64,8 @@ func genIntegrationsIntegrationAPIReadInfoCmd() *cobra.Command { var fIntegrationID int64 cmd := &cobra.Command{ Use: "info ", - Short: "Get integration detail", - Long: `Get integration detail. + Short: "Get public integration detail", + Long: `Get public integration detail. Get a public integration with its stored settings and decrypted integration key. @@ -148,8 +148,8 @@ func genIntegrationsIntegrationAPIReadListCmd() *cobra.Command { var fType string cmd := &cobra.Command{ Use: "list", - Short: "List integrations", - Long: `List integrations. + Short: "List public integrations", + Long: `List public integrations. List public integrations with their stored settings, decrypted keys, and edit permissions. @@ -371,8 +371,8 @@ func genIntegrationsIntegrationAPIWriteCreateCmd() *cobra.Command { var fTeamID int64 cmd := &cobra.Command{ Use: "create", - Short: "Create integration", - Long: `Create integration. + Short: "Create public integration", + Long: `Create public integration. Create a public integration for a supported alert, change, IM, or webhook type. @@ -448,8 +448,8 @@ func genIntegrationsIntegrationAPIWriteDeleteCmd() *cobra.Command { var fIntegrationID int64 cmd := &cobra.Command{ Use: "delete ", - Short: "Delete integration", - Long: `Delete integration. + Short: "Delete public integration", + Long: `Delete public integration. Delete an integration that nothing else references. @@ -500,8 +500,8 @@ func genIntegrationsIntegrationAPIWriteDisableCmd() *cobra.Command { var fIntegrationID int64 cmd := &cobra.Command{ Use: "disable ", - Short: "Disable integration", - Long: `Disable integration. + Short: "Disable public integration", + Long: `Disable public integration. Disable an integration without deleting its configuration. @@ -552,8 +552,8 @@ func genIntegrationsIntegrationAPIWriteEnableCmd() *cobra.Command { var fIntegrationID int64 cmd := &cobra.Command{ Use: "enable ", - Short: "Enable integration", - Long: `Enable integration. + Short: "Enable public integration", + Long: `Enable public integration. Re-enable a disabled integration so it accepts events again. @@ -604,8 +604,8 @@ func genIntegrationsIntegrationAPIWriteRotateKeyCmd() *cobra.Command { var fIntegrationID int64 cmd := &cobra.Command{ Use: "key-rotate ", - Short: "Rotate integration key", - Long: `Rotate integration key. + Short: "Rotate public integration key", + Long: `Rotate public integration key. Issue a new integration key and invalidate the previous one. @@ -615,7 +615,7 @@ Request fields: --integration-id int (required) — Integration ID. (min 1) Response fields ('data' envelope is unwrapped — these fields are at the top level): - - integration_key (string) (required) — New integration key; the previous key stops working immediately. Also readable from '/integration/list' and '/integration/info'. + - integration_key (string) (required) — New integration key; the previous key stops working immediately. `, Args: requireBodyFieldOrExactArg("integration_id", "integration-id"), Example: ` flashduty integration key-rotate --data '{"integration_id":6113996590131}'`, @@ -659,8 +659,8 @@ func genIntegrationsIntegrationAPIWriteUpdateCmd() *cobra.Command { var fTeamID int64 cmd := &cobra.Command{ Use: "update ", - Short: "Update integration", - Long: `Update integration. + Short: "Update public integration", + Long: `Update public integration. Update an integration's name, description, team, or settings. diff --git a/internal/cli/zz_generated_list_defaults.go b/internal/cli/zz_generated_list_defaults.go index 4f4b093..91c877a 100644 --- a/internal/cli/zz_generated_list_defaults.go +++ b/internal/cli/zz_generated_list_defaults.go @@ -24,6 +24,7 @@ var listDefaultsBySDKMethod = map[string]listDefaults{ "Dashboards.ReadList": {PageBase: pageUnknown}, "Dashboards.ReadSearch": {PageBase: pageUnknown}, "Dashboards.TrashReadList": {PageBase: pageUnknown}, + "DedicatedIntegrations.ReadList": {Limit: 100, PageBase: pageOne}, "ErrorIngestionRules.HistoryList": {Limit: 20, PageBase: pageZero}, "Facets.FacetCount": {Limit: 100}, "Incidents.AlertList": {Limit: 1000, PageBase: pageOne}, diff --git a/internal/cli/zz_generated_manifest.go b/internal/cli/zz_generated_manifest.go index 1a00829..135b301 100644 --- a/internal/cli/zz_generated_manifest.go +++ b/internal/cli/zz_generated_manifest.go @@ -46,6 +46,14 @@ var generatedOpIDs = []string{ "calendarList", "calendarUpdate", "change-read-list", + "channel-integration-read-info", + "channel-integration-read-list", + "channel-integration-write-create", + "channel-integration-write-delete", + "channel-integration-write-disable", + "channel-integration-write-enable", + "channel-integration-write-rotate-key", + "channel-integration-write-update", "channelCreate", "channelDelete", "channelDisable", diff --git a/internal/cli/zz_generated_register.go b/internal/cli/zz_generated_register.go index 6cb459f..9fadfb6 100644 --- a/internal/cli/zz_generated_register.go +++ b/internal/cli/zz_generated_register.go @@ -25,6 +25,7 @@ func registerGenerated(root *cobra.Command) { registerGeneratedCalendars(root) registerGeneratedChanges(root) registerGeneratedChannels(root) + registerGeneratedDedicatedIntegrations(root) registerGeneratedImIntegrations(root) registerGeneratedIncidents(root) registerGeneratedIntegrations(root) diff --git a/internal/cli/zz_generated_response_help.go b/internal/cli/zz_generated_response_help.go index c72a42a..d65230a 100644 --- a/internal/cli/zz_generated_response_help.go +++ b/internal/cli/zz_generated_response_help.go @@ -118,6 +118,11 @@ var responseHelpBySDKMethod = map[string]string{ "DataSources.ToolsInvoke": "Response fields (`data` envelope is unwrapped — these fields are at the top level):\n - data (any) (required) — Tool-specific JSON evidence, preserved without conversion; never null. No nested legacy diagnose envelope.\n - datasource_id (integer) (required) — Datasource ID from /monit/datasource/list. (min 1)\n - summary (string) — Optional non-empty summary.\n - tool (string) (required) — Executed tool name matching the request.\n - truncated (object)\n - reason (string) (required) — Why the result was truncated. Presence of this object indicates truncation.\n", "DataSources.WriteCreate": "Response fields (`data` envelope is unwrapped — these fields are at the top level):\n - account_id (integer) (required) — Account ID.\n - address (string) (required) — Connection address. For Prometheus/Loki/VictoriaLogs: HTTP URL. For MySQL/Oracle/Postgres/ClickHouse: `host:port`. For SLS: endpoint without http/https prefix. Redis/MongoDB diagnostic types: one host:port, bracket IPv6; no URI, userinfo or query. Kafka: 1–32 unique comma-separated host:port bootstrap addresses; payload has no broker list. At most 4096 characters after normalization. (≤4096 chars)\n - alerting_enabled (boolean) (required) — Whether alert evaluation is allowed. Alerting also requires enabled=true and an alerting-capable type. Always false for diagnostic-only types; false does not block non-alerting queries or tools.\n - edge_cluster_name (string) (required) — Monitors edge cluster name responsible for evaluating rules using this datasource.\n - enabled (boolean) (required) — Whether business execution is enabled. Disabled datasources reject business queries and tools; enabling does not change alerting_enabled.\n - id (integer) (required) — Unique datasource ID.\n - name (string) (required) — Datasource display name.\n - note (string) (required) — Optional description.\n - payload (any) (required) — Type-specific configuration block; must contain the key matching `type_ident`. Always `null` in `/monit/datasource/list` responses (the list query does not read the payload column); populated in create/update/info responses. For `tencent_cls`, `secret_key` is masked to an empty string unless it is an `${env:...}` reference. For diagnostic types, password and Kafka tls_key are omitted from responses unless they are ${env:...} references. On update, omit those fields to preserve stored secrets; explicitly send an empty string to clear. Other configuration fields retain their existing behavior.\n - type_ident (string) (required) — Datasource type identifier. Allowed: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`。\n - updated_at (string) (required) — Last update timestamp, Unix epoch seconds. CLI `--json` renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null.\n", "DataSources.WriteUpdate": "Response fields (`data` envelope is unwrapped — these fields are at the top level):\n - account_id (integer) (required) — Account ID.\n - address (string) (required) — Connection address. For Prometheus/Loki/VictoriaLogs: HTTP URL. For MySQL/Oracle/Postgres/ClickHouse: `host:port`. For SLS: endpoint without http/https prefix. Redis/MongoDB diagnostic types: one host:port, bracket IPv6; no URI, userinfo or query. Kafka: 1–32 unique comma-separated host:port bootstrap addresses; payload has no broker list. At most 4096 characters after normalization. (≤4096 chars)\n - alerting_enabled (boolean) (required) — Whether alert evaluation is allowed. Alerting also requires enabled=true and an alerting-capable type. Always false for diagnostic-only types; false does not block non-alerting queries or tools.\n - edge_cluster_name (string) (required) — Monitors edge cluster name responsible for evaluating rules using this datasource.\n - enabled (boolean) (required) — Whether business execution is enabled. Disabled datasources reject business queries and tools; enabling does not change alerting_enabled.\n - id (integer) (required) — Unique datasource ID.\n - name (string) (required) — Datasource display name.\n - note (string) (required) — Optional description.\n - payload (any) (required) — Type-specific configuration block; must contain the key matching `type_ident`. Always `null` in `/monit/datasource/list` responses (the list query does not read the payload column); populated in create/update/info responses. For `tencent_cls`, `secret_key` is masked to an empty string unless it is an `${env:...}` reference. For diagnostic types, password and Kafka tls_key are omitted from responses unless they are ${env:...} references. On update, omit those fields to preserve stored secrets; explicitly send an empty string to clear. Other configuration fields retain their existing behavior.\n - type_ident (string) (required) — Datasource type identifier. Allowed: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`。\n - updated_at (string) (required) — Last update timestamp, Unix epoch seconds. CLI `--json` renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null.\n", + "DedicatedIntegrations.ReadInfo": "Response fields (`data` envelope is unwrapped — these fields are at the top level):\n - category (string) (required) — Integration category; dedicated integration creation accepts `event.alert` alert integrations.\n - channel_id (integer) (required) — ID of the channel that owns the dedicated integration.\n - created_at (string) (required) — Creation time as a Unix timestamp in seconds. CLI `--json` renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null.\n - description (string) (required) — Integration description; empty when unset.\n - exclusive_data_source_id (integer) (required) — Compatibility identifier for earlier integrations; `0` when absent. Use `integration_id` for this API group.\n - integration_id (integer) (required) — Dedicated integration ID; use this ID for subsequent API calls.\n - integration_key (string) (required) — Complete integration key for alert ingestion; separate from the management App Key.\n - last_source_time (string) (required) — Source time of the most recent event as a Unix timestamp in seconds; `0` when unavailable. CLI `--json` renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null.\n - last_time (string) (required) — Most recent received-event time as a Unix timestamp in seconds; `0` when no event has arrived. CLI `--json` renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null.\n - name (string) (required) — Integration name.\n - plugin_id (integer) (required) — Numeric integration type ID. Create uses the string `plugin_type` instead.\n - plugin_type (string) (required) — Integration type identifier, such as `standard.alert`.\n - plugin_type_name (string) (required) — Integration type display name, localized to the request language.\n - settings (object) (required) — Integration-type-specific configuration; saved secret values in responses are masked as `******`.\n - status (string) (required) — Lifecycle status: `enabled` accepts alerts; `disabled` pauses ingestion. [enabled, disabled]\n - updated_at (string) (required) — Last update time as a Unix timestamp in seconds. CLI `--json` renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null.\n", + "DedicatedIntegrations.ReadList": "Response fields (this command's `--json` is a TOP-LEVEL array of these row objects — pipe `jq '.[]'`, NOT `.items[]`):\n - category (string) (required) — Integration category; dedicated integration creation accepts `event.alert` alert integrations.\n - channel_id (integer) (required) — ID of the channel that owns the dedicated integration.\n - created_at (string) (required) — Creation time as a Unix timestamp in seconds. CLI `--json` renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null.\n - description (string) (required) — Integration description; empty when unset.\n - exclusive_data_source_id (integer) (required) — Compatibility identifier for earlier integrations; `0` when absent. Use `integration_id` for this API group.\n - integration_id (integer) (required) — Dedicated integration ID; use this ID for subsequent API calls.\n - integration_key (string) (required) — Complete integration key for alert ingestion; separate from the management App Key.\n - last_source_time (string) (required) — Source time of the most recent event as a Unix timestamp in seconds; `0` when unavailable. CLI `--json` renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null.\n - last_time (string) (required) — Most recent received-event time as a Unix timestamp in seconds; `0` when no event has arrived. CLI `--json` renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null.\n - name (string) (required) — Integration name.\n - plugin_id (integer) (required) — Numeric integration type ID. Create uses the string `plugin_type` instead.\n - plugin_type (string) (required) — Integration type identifier, such as `standard.alert`.\n - plugin_type_name (string) (required) — Integration type display name, localized to the request language.\n - settings (object) (required) — Integration-type-specific configuration; saved secret values in responses are masked as `******`.\n - status (string) (required) — Lifecycle status: `enabled` accepts alerts; `disabled` pauses ingestion. [enabled, disabled]\n - updated_at (string) (required) — Last update time as a Unix timestamp in seconds. CLI `--json` renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null.\n", + "DedicatedIntegrations.WriteCreate": "Response fields (`data` envelope is unwrapped — these fields are at the top level):\n - integration_id (integer) (required) — Created dedicated integration ID.\n - integration_key (string) (required) — Integration key for alert ingestion.\n", + "DedicatedIntegrations.WriteRotateKey": "Response fields (`data` envelope is unwrapped — these fields are at the top level):\n - integration_key (string) (required) — New integration key; the previous key stops working immediately.\n", + "DedicatedIntegrations.WriteUpdate": "Response fields (`data` envelope is unwrapped — these fields are at the top level):\n - category (string) (required) — Integration category; dedicated integration creation accepts `event.alert` alert integrations.\n - channel_id (integer) (required) — ID of the channel that owns the dedicated integration.\n - created_at (string) (required) — Creation time as a Unix timestamp in seconds. CLI `--json` renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null.\n - description (string) (required) — Integration description; empty when unset.\n - exclusive_data_source_id (integer) (required) — Compatibility identifier for earlier integrations; `0` when absent. Use `integration_id` for this API group.\n - integration_id (integer) (required) — Dedicated integration ID; use this ID for subsequent API calls.\n - integration_key (string) (required) — Complete integration key for alert ingestion; separate from the management App Key.\n - last_source_time (string) (required) — Source time of the most recent event as a Unix timestamp in seconds; `0` when unavailable. CLI `--json` renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null.\n - last_time (string) (required) — Most recent received-event time as a Unix timestamp in seconds; `0` when no event has arrived. CLI `--json` renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null.\n - name (string) (required) — Integration name.\n - plugin_id (integer) (required) — Numeric integration type ID. Create uses the string `plugin_type` instead.\n - plugin_type (string) (required) — Integration type identifier, such as `standard.alert`.\n - plugin_type_name (string) (required) — Integration type display name, localized to the request language.\n - settings (object) (required) — Integration-type-specific configuration; saved secret values in responses are masked as `******`.\n - status (string) (required) — Lifecycle status: `enabled` accepts alerts; `disabled` pauses ingestion. [enabled, disabled]\n - updated_at (string) (required) — Last update time as a Unix timestamp in seconds. CLI `--json` renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null.\n", "Diagnostics.QueryData": "Response fields (`data` envelope is unwrapped — these fields are at the top level):\n - format (string) (required) — Public result-contract version. It is independent of the internal monit-edge query protocol version. Fixed at `query_result.v1`, which defines the structure of the `result` field. [query_result.v1]\n - result (object) (required) — Exactly one natural result shape, selected by `kind`.\n - frames (array) — Typed table or time-series frames. A response can contain more than one frame.\n - fields (array) (required) — Columns of the frame; all fields share the same `values` length and row i is composed of each field's `values[i]`.\n - labels (object) — Series labels. Present on the float field of a time-series frame.\n - name (string) (required) — Column name; on a time-series float field, series are distinguished by `labels` and `name` is usually the metric name.\n - type (string) (required) — Value type governing `values` encoding: `string` = strings or null, `float` = numbers or `NaN`/`±Inf` strings or null, `time` = RFC 3339 Nano strings or null. [string, float, time]\n - values (array) (required) — All values of this column in row order; length matches the other fields in the frame.\n - kind (string) (required) — Frame type: `table` for a generic table, `time_series` for a series (exactly one time field and one float field). [table, time_series]\n - kind (string) (required) — Result-kind discriminator, always `frames`, indicating the `frames` payload of typed table/time-series frames. [frames, records, samples]\n - records (array) — Schema-flexible records. Records may have different fields, contain nested JSON, or be null. Integers outside JavaScript's safe range are encoded as decimal strings.\n - samples (array) — Instant samples with their complete label sets.\n - labels (object) (required) — The sample's full label set; may be an empty object but is always present.\n - value (any) (required) — Finite numeric value or a JSON-safe representation of a non-finite float.\n", "Diagnostics.QueryExplore": "Response fields (`data` envelope is unwrapped — these fields are at the top level):\n - execution (object) — Execution actually used, present when the data source returned a stepped result.\n - effective_step_seconds (integer) (required) — Step, in seconds, the query was executed with after applying `max_data_points` and `min_step_seconds`.\n - kind (string) (required) — Execution kind; always `range` when this object is present. [range]\n - format (string) (required) — Result contract version; always `explore_result.v1`. [explore_result.v1]\n - result (object) (required) — Result body. Exactly one of `frames`, `samples`, or `entries` is present and matches `kind`.\n - applied_limit (integer) — Entry limit applied to a logs result; at most 1000.\n - entries (array) — Log entries. Present when `kind` is `logs`; never longer than `applied_limit`.\n - fields (object) (required) — Log fields as raw JSON values. Integer literals outside JavaScript's safe integer range are returned as decimal strings.\n - timestamp_ns (string) (required) — Entry time as a canonical unsigned decimal string of Unix epoch nanoseconds, at most 20 digits.\n - frames (array) — Columnar frames. Present when `kind` is `frames`; at most 1,000 frames.\n - fields (array) (required) — Columns of the frame.\n - labels (object) — Label set of this column. Only `time_series` value fields may carry labels; a `table` field must not.\n - name (string) (required) — Column name, at most 1 MiB of UTF-8.\n - type (string) (required) — Column type. `string` is rejected inside a `time_series` frame; `float` holds numbers and `time` holds UTC RFC3339Nano strings. [string, float, time]\n - values (array) (required) — Column values in row order.\n - kind (string) (required) — Frame shape. `table` is an unlabeled table, while `time_series` carries exactly one time field and one float field. [table, time_series]\n - has_more (boolean) — Whether a logs result was truncated by `applied_limit`.\n - kind (string) (required) — Result shape. `frames` returns columnar tables or time series, `samples` returns instant values with labels, and `logs` returns log entries. [frames, samples, logs]\n - samples (array) — Instant samples. Present when `kind` is `samples`; at most 1,000 samples.\n - labels (object) (required) — Label set of the sample. May be empty but never null.\n - value (any) (required) — Sample value: a number, or one of the strings `NaN`, `+Inf`, and `-Inf`. Never null.\n", "ErrorIngestionRules.Create": "Response fields (`data` envelope is unwrapped — these fields are at the top level):\n - rule_id (string) (required) — ID assigned to the new rule.\n - rule_name (string) (required) — Echo of the created rule's name.\n", @@ -162,7 +167,7 @@ var responseHelpBySDKMethod = map[string]string{ "Integrations.IntegrationAPIReadList": "Response fields (this command's `--json` is a TOP-LEVEL array of these row objects — pipe `jq '.[]'`, NOT `.items[]`):\n - account_id (integer) (required) — ID of the account that owns the integration.\n - category (string) (required) — Category the integration belongs to: `event.alert` alert events, `event.change` change events, `im` IM bots, `webhook` custom webhooks. [event.alert, event.change, im, webhook]\n - created_at (string) (required) — Unix timestamp in seconds when the integration was created. CLI `--json` renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null.\n - creator_id (integer) (required) — ID of the member who created the integration.\n - data_source_id (integer) (required) — Legacy datasource ID, equal to `integration_id`.\n - description (string) (required) — Free-form description.\n - editable (boolean) (required) — Whether the current caller passes the integration object-permission check; write calls also require Integrations Manage.\n - exclusive_data_source_id (integer) (required) — Legacy compatibility field; `0` for items returned by this public-integration list.\n - integration_id (integer) (required) — Integration ID.\n - integration_key (string) (required) — Decrypted integration key for inbound pushes. Empty when no key is stored; distinct from the account `app_key`.\n - last_time (string) (required) — Unix timestamp in seconds of the most recent event received. `0` when no event has arrived yet. CLI `--json` renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null.\n - name (string) (required) — Integration name.\n - no_editable (boolean) (required) — Read-only flag. When true, the public APIs do not allow changes to this integration.\n - plugin_id (integer) (required) — Internal integration type ID; use `plugin_type`, not this ID, when creating an integration.\n - plugin_type (string) (required) — Integration type, for example `standard.alert` or `zabbix.alert`.\n - plugin_type_name (string) (required) — Display name of the integration type, in the language of the request.\n - ref_id (string) (required) — Source reference ID, normally `a_` for an account-level integration; legacy `w_` references may also exist. Channel-owned `c_` integrations are excluded.\n - settings (object) (required) — Stored type-specific configuration. Each saved secret (passwords, app secrets, tokens, encryption keys, webhook endpoints, HTTP pull URL and body, headers, custom bodies) is returned as `******`; unset values stay empty.\n - status (string) (required) — Lifecycle status: `enabled` while the integration accepts events, `disabled` when it is paused. [enabled, disabled]\n - team_id (integer) (required) — ID of the team that owns the integration. `0` when it is not assigned to a team.\n - updated_at (string) (required) — Unix timestamp in seconds when the integration was last updated. CLI `--json` renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null.\n - updated_by (integer) (required) — ID of the member who last updated the integration.\n", "Integrations.IntegrationAPIReadTypeList": "Response fields (this command's `--json` is a TOP-LEVEL array of these row objects — pipe `jq '.[]'`, NOT `.items[]`):\n - category (string) (required) — Category the type belongs to: `event.alert` alert events, `event.change` change events, `im` IM bots, `webhook` custom webhooks. [event.alert, event.change, im, webhook]\n - plugin_type (string) (required) — Type identifier to pass as `plugin_type` when creating an integration.\n - plugin_type_logo_url (string) (required) — Logo URL of the type.\n - plugin_type_name (string) (required) — Display name of the type.\n - status (string) (required) — Platform status of the type.\n - supports_api_create (boolean) (required) — Whether `POST /integration/create` accepts this type.\n", "Integrations.IntegrationAPIWriteCreate": "Response fields (`data` envelope is unwrapped — these fields are at the top level):\n - integration_id (integer) (required) — ID of the new integration.\n - integration_key (string) (required) — Integration key for inbound pushes; also readable from `/integration/list` and `/integration/info`.\n - test (object) — Plugin test result, returned only when a test is performed.\n - message (string) (required) — Test failure message; empty on success.\n - success (boolean) (required) — Whether the plugin test succeeded.\n", - "Integrations.IntegrationAPIWriteRotateKey": "Response fields (`data` envelope is unwrapped — these fields are at the top level):\n - integration_key (string) (required) — New integration key; the previous key stops working immediately. Also readable from `/integration/list` and `/integration/info`.\n", + "Integrations.IntegrationAPIWriteRotateKey": "Response fields (`data` envelope is unwrapped — these fields are at the top level):\n - integration_key (string) (required) — New integration key; the previous key stops working immediately.\n", "Integrations.IntegrationAPIWriteUpdate": "Response fields (`data` envelope is unwrapped — these fields are at the top level):\n - category (string) (required) — Category the integration belongs to: `event.alert` alert events, `event.change` change events, `im` IM bots, `webhook` custom webhooks. [event.alert, event.change, im, webhook]\n - created_at (string) (required) — Unix timestamp in seconds when the integration was created. CLI `--json` renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null.\n - creator_id (integer) (required) — ID of the member who created the integration.\n - description (string) (required) — Free-form description.\n - editable (boolean) (required) — Whether the current caller passes the integration object-permission check; write calls also require Integrations Manage.\n - integration_id (integer) (required) — Integration ID.\n - integration_key (string) (required) — Decrypted integration key for inbound pushes. Empty when no key is stored; distinct from the account `app_key`.\n - last_time (string) (required) — Unix timestamp in seconds of the most recent event received. `0` when no event has arrived yet. CLI `--json` renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null.\n - name (string) (required) — Integration name.\n - no_editable (boolean) (required) — Read-only flag. When true, the public APIs do not allow changes to this integration.\n - plugin_id (integer) (required) — Internal integration type ID; use `plugin_type`, not this ID, when creating an integration.\n - plugin_type (string) (required) — Integration type, for example `standard.alert` or `zabbix.alert`.\n - plugin_type_name (string) (required) — Display name of the integration type, in the language of the request.\n - ref_id (string) (required) — Source reference ID, normally `a_` for an account-level integration; legacy `w_` references may also exist. Channel-owned `c_` integrations are excluded.\n - settings (object) (required) — Stored type-specific configuration. Each saved secret (passwords, app secrets, tokens, encryption keys, webhook endpoints, HTTP pull URL and body, headers, custom bodies) is returned as `******`; unset values stay empty.\n - status (string) (required) — Lifecycle status: `enabled` while the integration accepts events, `disabled` when it is paused. [enabled, disabled]\n - team_id (integer) (required) — ID of the team that owns the integration. `0` when it is not assigned to a team.\n - test (object) — Plugin test result, returned only when a test is performed.\n - message (string) (required) — Test failure message; empty on success.\n - success (boolean) (required) — Whether the plugin test succeeded.\n - updated_at (string) (required) — Unix timestamp in seconds when the integration was last updated. CLI `--json` renders this as an RFC3339 string in the process's local timezone (NOT UTC, and NOT the wire integer); an unset value renders as null.\n - updated_by (integer) (required) — ID of the member who last updated the integration.\n", "Integrations.List": "Response fields (this command's `--json` is a TOP-LEVEL array of these row objects — pipe `jq '.[]'`, NOT `.items[]`):\n - attempt (integer) (required) — Attempt sequence number.\n - channel_id (integer) — Channel ID associated with the event, when applicable.\n - duration (integer) (required) — Total elapsed time of the attempt in milliseconds.\n - endpoint (string) (required) — Destination URL.\n - error_message (string) — Error message when delivery failed.\n - event_id (string) (required) — Unique event identifier for the delivery attempt.\n - event_time (string) (required) — Event time formatted as `YYYY-MM-DD HH:MM:SS.ffffff`.\n - event_type (string) (required) — Event type code. `i_*` values are incident events (for example `i_new` = incident created); `a_*` values are alert events (for example `a_new` = alert triggered).\n - integration_id (integer) (required) — Integration ID that triggered the webhook.\n - ref_id (string) — Source object ID (incident ID or alert ID).\n - request_body (string) — Outbound request body payload.\n - request_headers (string) — Serialized outbound request headers.\n - response_body (string) — Response body returned by the destination.\n - response_headers (string) — Serialized response headers from the destination.\n - status (string) (required) — Delivery outcome. [success, failed]\n - status_code (integer) (required) — HTTP status code returned by the destination.\n - webhook_type (string) (required) — Source object kind: `incident` or `alert`. [incident, alert]\n", "IssuePresetSeverityRules.Create": "Response fields (`data` envelope is unwrapped — these fields are at the top level):\n - priority (integer) (required) — Evaluation order assigned to the new rule (always the current lowest precedence, i.e. current max + 1).\n - rule_id (string) (required) — ID of the newly created rule.\n - rule_name (string) (required) — Echo of the rule's display name.\n", diff --git a/skills/flashduty/SKILL.md b/skills/flashduty/SKILL.md index 44d7c92..caaf6b1 100644 --- a/skills/flashduty/SKILL.md +++ b/skills/flashduty/SKILL.md @@ -1,6 +1,6 @@ --- name: flashduty -version: "3.0" +version: "3.1" description: "USE FIRST for Flashduty tasks — status pages, incidents, alerts, integrations, on-call, monitors, automations, RUM, sourcemaps, members. `flashduty` CLI = the whole API. ALWAYS load this skill + read reference/.md for exact verbs & flags BEFORE running flashduty. Don't guess or --help-dance." allowed-tools: bash, read hidden: true # internal-only: withheld from skills.sh public discovery (Safari embeds this skill directly). @@ -76,8 +76,8 @@ Some asks span several commands. For those the skill ships a script that fetches | datasource 数据源 = a system Flashmonit queries (Prometheus / Loki / SQL / SLS) / connect a datasource 连接数据源 / SLS project / logstore / Redis / MongoDB / Kafka / database overview 数据库概览 / locks 锁 / slowlog 慢日志 | **`reference/monit-datasource.md`** | | automation / 自动化 / 定时 AI SRE / scheduled AI task / daily brief / weekly report / webhook trigger / POST trigger / chat-created automation | **`reference/automation.md`** | | metric/log query / 指标查询 / 日志查询 / PromQL / LogsQL / SQL / trend 趋势 / log clustering 日志聚类 / datasource RCA 数据源排查 | **`reference/monit-query.md`** | -| public integration / 公共集成 / 集成中心 / integration 集成 / alert source 告警来源 / integration key 集成 Key / IM bot / webhook configuration | **`reference/integration.md`** | -| channel / 协作空间 / collaboration space / 频道 / channel-owned dedicated integration 协作空间专属集成 / alert grouping 告警分组 | **`reference/channel.md`** | +| public integration 公共集成 / dedicated integration 专属集成 / 集成中心 / integration 集成 / alert source 告警来源 / integration key 集成 Key / IM bot / webhook configuration | **`reference/integration.md`** | +| channel / 协作空间 / collaboration space / 频道 / alert grouping 告警分组 | **`reference/channel.md`** | | dispatch rule 分派策略 / 分派规则 / escalation rule 升级规则 / notify layers 通知层级 / who gets paged | **`reference/escalation.md`** | | silence 静默 / 屏蔽 / inhibit 抑制 / drop rule 丢弃 / noise reduction 降噪 / maintenance silence 维护窗口静默 | **`reference/noise.md`** | | enrichment / 数据加工 / 富化 / label mapping 字段映射 / extraction 提取 / mapping schema 集成 schema | **`reference/enrichment.md`** | diff --git a/skills/flashduty/reference/channel.md b/skills/flashduty/reference/channel.md index 8533e53..9dcf659 100644 --- a/skills/flashduty/reference/channel.md +++ b/skills/flashduty/reference/channel.md @@ -6,6 +6,8 @@ Prereq: `SKILL.md` read. Read verbs are free; `create`, `update`, `delete`, `dis "协作空间 / 频道 / 渠道 / 告警分组 / channel / collaboration space / alert grouping / flapping" → **channel**, NOT `incident` (incidents live _inside_ a channel) or `alert` (alerts are routed _into_ a channel). **`协作空间` (collaboration space) IS the `channel` API noun** — a naive translation would be "频道", but Flashduty's product surfaces it as 协作空间. Key ID: **`channel-id` (int)** from `channel list`. +Dedicated integrations owned by a channel use `channel integration-*`; read `reference/integration.md` to choose between dedicated and public integrations and check their different permissions. + Rules INSIDE a channel have their own cards: escalation / 分派策略 → `reference/escalation.md`; silence / inhibit / drop (静默 / 抑制 / 丢弃 / 降噪) → `reference/noise.md`. **Flashcat workspace exception.** When the user asks whether a "空间" is healthy, red/green, or specifically mentions **灭火图 / firemap**, do not assume they mean a Flashduty channel. In that context, "空间" may be a **Flashcat workspace**, and the answer must come from the Flashcat/firemap surface rather than channel incident stats. If you first resolved a name as a Flashduty `channel-id` and later resolve the same visible name as a Flashcat `workspace-id`, **do not silently switch** — tell the user these are different objects and state which ID/surface each conclusion uses. diff --git a/skills/flashduty/reference/integration.md b/skills/flashduty/reference/integration.md index d7a1301..e985b27 100644 --- a/skills/flashduty/reference/integration.md +++ b/skills/flashduty/reference/integration.md @@ -1,8 +1,21 @@ # flashduty integration — command card -Prereq: read `SKILL.md`. These commands manage **public/account-level integrations**, including supported alert, change, IM, and webhook types. They do not manage channel-owned dedicated integrations (`c_` references); use the console for those. For channel configuration and subscriptions, read `reference/channel.md`. +Prereq: read `SKILL.md`. Choose the command family from the integration's ownership before reading or changing it. For channel configuration, subscriptions, and routing, read `reference/channel.md`. -## Read before changing configuration +## Choose the integration scope + +| User intent or existing ownership | Command family | Permission boundary | +|---|---|---| +| Public integration managed in the integration center; shared ingestion connected to channels through subscriptions or routing | `integration *` | Integrations Read/Manage plus the integration's object permissions | +| Dedicated alert integration owned by one collaboration space (协作空间专属集成) | `channel integration-*` | Channels Read/Manage plus visibility or management of the owning channel; no integration-center permission required | + +For an existing integration, use its known ownership; an ID alone does not identify the scope. A target channel receiving alerts does not by itself mean the integration is dedicated: public integrations can also route there. For creation, use a dedicated integration when ingestion belongs to that one channel, or a public integration when the user wants shared ingestion managed in the integration center. If ownership or intended scope is unclear, ask before creating or changing configuration. + +Never retry a failed call through the other integration family, including on access denied or not found. Public does not mean anonymous: both families use the management App Key and its owner's permissions. An integration key is a separate credential for inbound events. + +## Public integrations + +### Read before changing configuration - Start with `type-list` and `list`. Create only a `plugin_type` whose type entry has `supports_api_create: true`. - List/info return stored `settings` with each saved secret as `******`, and `integration_key` as is. Prefer `--fields` projections for discovery; do not paste the integration key into a report or unrelated tool. An integration key authenticates inbound pushes; it is not the account App Key used by this CLI. @@ -11,7 +24,7 @@ Prereq: read `SKILL.md`. These commands manage **public/account-level integratio - Metadata-only updates preserve omitted fields. `--team-id 0` deliberately clears team ownership. Submitted `settings` replace type-specific configuration; known sensitive fields omitted or set to `******` preserve their stored value. A stored secret cannot be kept while its destination (such as `endpoint`, `url`, or a database host or port) changes; send the real secret with the new destination. An explicit `headers: {}` clears headers. - `--is-test` on create, or on update with `settings`, returns plugin test results. Inspect `test.success` and `test.message`: HTTP success is not plugin-test success. An absent `test` means no test result was returned, not a successful test. -## Discovery +### Discovery ```bash flashduty integration type-list --category event.alert --output-format toon @@ -19,7 +32,7 @@ flashduty integration list --fields integration_id,name,plugin_type,team_id,edit flashduty integration info 42 --fields integration_id,name,plugin_type,team_id,editable,no_editable --output-format toon ``` -## Approved configuration changes +### Approved configuration changes Use the exact type-specific settings provided for the target integration; do not guess credential keys. `--integration-key` is optional on create; omitting it generates a key. If provided, it must satisfy the account suffix, length, and uniqueness checks. @@ -35,7 +48,7 @@ Do not add `--is-test` to a metadata-only update expecting a plugin test; settin ### create -Create integration +Create public integration - `--description` string — Free-form description, at most 499 characters. (≤499 chars) - `--integration-key` string — Optional pre-generated key: 35 characters, ending with the account ID modulo 1000 padded to three digits; it must not already be in use. Omit to generate a key. (35-35 chars) - `--is-test` bool — Run the plugin test during creation; false when omitted. Inspect the returned 'test.success' for the test outcome. @@ -46,29 +59,29 @@ Create integration - response: single object (`data` unwrapped to the top level) — fields: integration_id (integer); integration_key (string); test (object) ### delete -Delete integration +Delete public integration - `` (positional, required) int64 — Integration ID. (min 1) ### disable -Disable integration +Disable public integration - `` (positional, required) int64 — Integration ID. (min 1) ### enable -Enable integration +Enable public integration - `` (positional, required) int64 — Integration ID. (min 1) ### info -Get integration detail +Get public integration detail - `` (positional, required) int64 — Integration ID. (min 1) - response: single object (`data` unwrapped to the top level) — fields: category (string); created_at (string); creator_id (integer); description (string); editable (boolean); integration_id (integer); integration_key (string); last_time (string); name (string); no_editable (boolean); plugin_id (integer); plugin_type (string); plugin_type_name (string); ref_id (string); settings (object); status (string); team_id (integer); test (object); updated_at (string); updated_by (integer) ### key-rotate -Rotate integration key +Rotate public integration key - `` (positional, required) int64 — Integration ID. (min 1) - response: single object (`data` unwrapped to the top level) — fields: integration_key (string) ### list -List integrations +List public integrations - `--asc` bool — Sort ascending when true, descending when false. - `--category` string — Filter by category. Accepts a comma-separated list. - `--is-my-team` bool — Limit the result to integrations owned by your teams. @@ -95,7 +108,7 @@ List integration types - response: `{items: [...], limit, p, total}` page wrapper — pipe `--json | jq '.items[]'` (NOT top-level `.[]`) — items fields: category (string); plugin_type (string); plugin_type_logo_url (string); plugin_type_name (string); status (string); supports_api_create (boolean) ### update -Update integration +Update public integration - `--description` string — New description, at most 499 characters. (≤499 chars) - `` (positional, required) int64 — Integration ID. (min 1) - `--is-test` bool — Run the plugin test when submitting 'settings'; no test is performed for a metadata-only update. @@ -105,3 +118,79 @@ Update integration - response: same shape as `info ` above + + +## Dedicated integrations + +Use the channel's `channel_id` to list or create dedicated integrations. Info, update, lifecycle, and key rotation use the returned `integration_id`; public integration IDs are not accepted. Creation requires an enabled channel and an enabled `event.alert` type allowed by the account's license. IM, change-event, and outbound webhook integrations use the public family. An alert-ingestion webhook type such as `webhook.alert` is still an `event.alert` type and can be dedicated. + +- Reads require Channels Read or Manage and visibility of the channel. Private channels remain restricted. +- Writes require Channels Manage and management of the owning channel. Creating an integration does not grant its creator channel management rights. +- List/info return the complete `integration_key` and masked settings. Use field projections for discovery and keep keys out of reports. App Key scopes may further restrict calls. +- Before update/delete, enable/disable, or key rotation, follow `SKILL.md`'s confirmation and protected-backup rules for the specific target. Before create, confirm the target channel and intended scope. For key rotation, confirm sender reconfiguration because the old key stops working immediately. Remove references before deletion. +- Dedicated updates accept name, description, and settings. Omitted or null fields retain their value; `--description ""` clears the description. `settings: {}` is an explicit replacement, subject to type validation. Known secrets omitted or set to `******` are preserved; changing their destination requires the real secret. Dedicated commands have no `--team-id` or `--is-test` option and cannot move an integration to another channel. + +```bash +# Discover only within the requested collaboration space. +flashduty channel integration-list --channel-id 20001 --fields integration_id,channel_id,name,plugin_type,status --output-format toon +flashduty channel integration-info 10001 --fields integration_id,channel_id,name,plugin_type,status --output-format toon +# Only after confirmation of this channel, scope, and type-specific settings. +flashduty channel integration-create --channel-id 20001 --plugin-type standard.alert --name "Primary alerts" --data '{"settings":{}}' --json +# Only after backing up integration 10001 and confirming this rename. +flashduty channel integration-update 10001 --name "Primary alerts (renamed)" --json +``` + + + +### integration-create +Create dedicated integration +- `` (positional, required) int64 — Target channel ID; the channel must be enabled. (min 1) +- `--description` string — Description, at most 499 characters. (≤499 chars) +- `--integration-key` string — Optional supplied integration key. A non-empty value must have 35 characters, match the account suffix, and be unique. (≤35 chars) +- `--name` string — Integration name, 2–49 characters when supplied; omitted or empty uses the integration type default. (≤49 chars) +- `--plugin-type` string (required) — Enabled alert integration type identifier, such as 'standard.alert'. +- body-only (`--data`): settings (object) +- response: single object (`data` unwrapped to the top level) — fields: integration_id (integer); integration_key (string) + +### integration-delete +Delete dedicated integration +- `` (positional, required) int64 — Dedicated integration ID returned by create, list, or info. Public integration IDs are not accepted. (min 1) + +### integration-disable +Disable dedicated integration +- `` (positional, required) int64 — Dedicated integration ID returned by create, list, or info. Public integration IDs are not accepted. (min 1) + +### integration-enable +Enable dedicated integration +- `` (positional, required) int64 — Dedicated integration ID returned by create, list, or info. Public integration IDs are not accepted. (min 1) + +### integration-info +Get dedicated integration detail +- `` (positional, required) int64 — Dedicated integration ID returned by create, list, or info. Public integration IDs are not accepted. (min 1) +- response: single object (`data` unwrapped to the top level) — fields: category (string); channel_id (integer); created_at (string); description (string); exclusive_data_source_id (integer); integration_id (integer); integration_key (string); last_source_time (string); last_time (string); name (string); plugin_id (integer); plugin_type (string); plugin_type_name (string); settings (object); status (string); updated_at (string) + +### integration-key-rotate +Rotate dedicated integration key +- `` (positional, required) int64 — Dedicated integration ID returned by create, list, or info. Public integration IDs are not accepted. (min 1) +- response: single object (`data` unwrapped to the top level) — fields: integration_key (string) + +### integration-list +List dedicated integrations +- `` (positional, required) int64 — Channel ID to list dedicated integrations for. (min 1) +- `--limit` int64 — Number of items per page, at most 100. (1-100) +- `--name` string — Filter by integration name. (≤49 chars) +- `--page` int64 — Page number, starting at 1. (min 1) +- `--plugin-type` string — Filter by one integration type. +- `--search-after-ctx` string +- `--status` string — Filter by 'enabled' integrations that accept alerts or 'disabled' integrations that pause ingestion. · enum: enabled | disabled +- response: `{items: [...], limit, p, total}` page wrapper — pipe `--json | jq '.items[]'` (NOT top-level `.[]`) — items fields: category (string); channel_id (integer); created_at (string); description (string); exclusive_data_source_id (integer); integration_id (integer); integration_key (string); last_source_time (string); last_time (string); name (string); plugin_id (integer); plugin_type (string); plugin_type_name (string); settings (object); status (string); updated_at (string) + +### integration-update +Update dedicated integration +- `--description` string — New description, at most 499 characters; empty clears it, omitted or null keeps it. (≤499 chars) +- `` (positional, required) int64 — Dedicated integration ID returned by create, list, or info. Public integration IDs are not accepted. (min 1) +- `--name` string — New name, 2–49 characters; omitted or null keeps the stored name. (2-49 chars) +- body-only (`--data`): settings (object) +- response: same shape as `integration-info ` above + +