diff --git a/cmd/other/ai.go b/cmd/other/ai.go deleted file mode 100644 index 6cdb163..0000000 --- a/cmd/other/ai.go +++ /dev/null @@ -1,277 +0,0 @@ -package other - -import ( - "bufio" - "context" - "errors" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - - "github.com/pterm/pterm" - openai "github.com/sashabaranov/go-openai" - "github.com/spf13/cobra" -) - -var ( - apiToken string - configPath = filepath.Join(os.Getenv("HOME"), ".cfctl", "config") - resourceDir = filepath.Join(os.Getenv("HOME"), ".cfctl", "training_data") -) - -// AiCmd represents the ai command -var AiCmd = &cobra.Command{ - Use: "ai", - Short: "Run AI-powered tasks", - Long: `Run various AI-powered tasks, including general text processing or natural language -queries using OpenAI's API.`, - Run: func(cmd *cobra.Command, args []string) { - inputText, _ := cmd.Flags().GetString("input") - isNaturalLanguage, _ := cmd.Flags().GetBool("natural") - - if inputText == "" { - cmd.Help() - return - } - - result, err := runAIWithOpenAI(inputText, isNaturalLanguage) - if err != nil { - fmt.Printf("Error: %v\n", err) - return - } - fmt.Println("AI Result:", result) - }, -} - -// aiConfigCmd represents the ai config command -var aiConfigCmd = &cobra.Command{ - Use: "config", - Short: "Set up OpenAI Secret Key", - Run: func(cmd *cobra.Command, args []string) { - pterm.Info.Println("Setting up OpenAI API key for AI commands...") - - // Prompt user for OpenAI API key - apiKey, err := pterm.DefaultInteractiveTextInput.WithMultiLine(false).Show("Enter your OpenAI API Key") - if err != nil { - pterm.Error.Println("Failed to read API key:", err) - return - } - - // Write to config file - if err := saveAPIKeyToConfig(apiKey); err != nil { - pterm.Error.Println("Error saving API key:", err) - return - } - - pterm.Success.Println("OpenAI API key saved successfully to", configPath) - }, -} - -// aiChatCmd represents the ai chat command -var aiChatCmd = &cobra.Command{ - Use: "chat", - Short: "Ask questions about project resources", - Run: func(cmd *cobra.Command, args []string) { - // Use the query flag instead of args[0] - chat, err := cmd.Flags().GetString("query") - if err != nil || chat == "" { - pterm.Error.Println("Please provide a query with the -q flag.") - return - } - - // Load resources context from directory - contextData, err := loadAPIResourcesContext(resourceDir) - if err != nil { - pterm.Error.Println("Failed to load resources context:", err) - return - } - - // Call AI function with query and context - result, err := queryAIWithContext(chat, contextData) - if err != nil { - pterm.Error.Println("Error querying AI:", err) - return - } - - pterm.Info.Println("AI Response:", result) - }, -} - -// runAIWithOpenAI processes input with OpenAI's streaming API -func runAIWithOpenAI(input string, natural bool) (string, error) { - // Load the API key from config if it's not set in the environment - apiToken = os.Getenv("OPENAI_API_TOKEN") - if apiToken == "" { - var err error - apiToken, err = readAPIKeyFromConfig() - if err != nil { - return "", errors.New("OpenAI API key is not set. Run `cfctl ai config` to configure it.") - } - } - - client := openai.NewClient(apiToken) - ctx := context.Background() - - // Set up the request based on the mode (natural language or standard) - model := openai.GPT3Babbage002 - if natural { - model = openai.GPT3Babbage002 - } - - req := openai.CompletionRequest{ - Model: model, - MaxTokens: 5, - Prompt: input, - Stream: true, - } - - stream, err := client.CreateCompletionStream(ctx, req) - if err != nil { - return "", fmt.Errorf("completion stream error: %v", err) - } - defer stream.Close() - - // Capture the streamed response - var responseText string - for { - response, err := stream.Recv() - if errors.Is(err, io.EOF) { - fmt.Println("Stream finished") - break - } - if err != nil { - return "", fmt.Errorf("stream error: %v", err) - } - responseText += response.Choices[0].Text - fmt.Printf("Stream response: %s", response.Choices[0].Text) - } - return responseText, nil -} - -// saveAPIKeyToConfig saves or updates the OpenAI API key in the config file -func saveAPIKeyToConfig(apiKey string) error { - // Read the existing config file content - content := "" - if _, err := os.Stat(configPath); err == nil { - data, err := os.ReadFile(configPath) - if err != nil { - return fmt.Errorf("failed to read config file: %v", err) - } - content = string(data) - } - - // Check if OPENAI_SECRET_KEY is already present - if strings.Contains(content, "OPENAI_SECRET_KEY=") { - // Update the existing key without adding an extra `=` character - content = strings.ReplaceAll(content, - "OPENAI_SECRET_KEY="+getAPIKeyFromContent(content), - "OPENAI_SECRET_KEY="+apiKey) - } else { - // Append the key if not present - content += "\nOPENAI_SECRET_KEY=" + apiKey - } - - // Write the updated content back to the config file - return os.WriteFile(configPath, []byte(content), 0600) -} - -// getAPIKeyFromContent extracts the existing API key from content if available -func getAPIKeyFromContent(content string) string { - scanner := bufio.NewScanner(strings.NewReader(content)) - for scanner.Scan() { - line := scanner.Text() - if strings.HasPrefix(line, "OPENAI_SECRET_KEY=") { - return line[17:] - } - } - return "" -} - -// readAPIKeyFromConfig reads the OpenAI API key from the config file and sets it to apiToken -func readAPIKeyFromConfig() (string, error) { - file, err := os.Open(configPath) - if err != nil { - return "", fmt.Errorf("failed to open config file: %v", err) - } - defer file.Close() - - scanner := bufio.NewScanner(file) - for scanner.Scan() { - line := scanner.Text() - line = strings.TrimSpace(line) // 공백 제거 - if strings.HasPrefix(line, "OPENAI_SECRET_KEY=") { - apiToken = strings.TrimPrefix(line, "OPENAI_SECRET_KEY=") - apiToken = strings.TrimSpace(apiToken) - return apiToken, nil - } - } - return "", errors.New("API key not found in config file") -} - -// loadAPIResourcesContext loads all files in the given directory and concatenates their content as context -func loadAPIResourcesContext(dirPath string) (string, error) { - files, err := ioutil.ReadDir(dirPath) - if err != nil { - return "", fmt.Errorf("failed to read resources directory: %v", err) - } - - var contentBuilder strings.Builder - for _, file := range files { - if !file.IsDir() { - filePath := filepath.Join(dirPath, file.Name()) - data, err := ioutil.ReadFile(filePath) - if err != nil { - return "", fmt.Errorf("failed to read file %s: %v", filePath, err) - } - contentBuilder.WriteString(string(data) + "\n") - } - } - - return contentBuilder.String(), nil -} - -// queryAIWithContext queries the OpenAI API with a specific context and user query -func queryAIWithContext(query, contextData string) (string, error) { - apiToken = os.Getenv("OPENAI_API_TOKEN") - if apiToken == "" { - apiToken, _ = readAPIKeyFromConfig() - } - if apiToken == "" { - return "", errors.New("OpenAI API token is not set. Run `cfctl ai config` to configure it.") - } - - client := openai.NewClient(apiToken) - ctx := context.Background() - - // Prompt with context for AI model - prompt := fmt.Sprintf("Context: %s\n\nQuestion: %s\nAnswer:", contextData, query) - - req := openai.CompletionRequest{ - Model: openai.GPT3Babbage002, - MaxTokens: 5, // Adjust as needed - Prompt: prompt, - Stream: false, - } - - resp, err := client.CreateCompletion(ctx, req) - if err != nil { - return "", fmt.Errorf("AI query error: %v", err) - } - - // Return the AI's response text - return strings.TrimSpace(resp.Choices[0].Text), nil -} - -func init() { - AiCmd.Flags().String("input", "", "Input text for the AI to process") - AiCmd.Flags().BoolP("natural", "n", false, "Enable natural language mode for the AI") - aiChatCmd.Flags().StringP("query", "q", "", "Query text for the AI to process") - aiChatCmd.MarkFlagRequired("query") - - // Add config command as a subcommand to AiCmd - AiCmd.AddCommand(aiConfigCmd) - AiCmd.AddCommand(aiChatCmd) -} diff --git a/cmd/other/exec.go b/cmd/other/exec.go deleted file mode 100644 index 16f798a..0000000 --- a/cmd/other/exec.go +++ /dev/null @@ -1,414 +0,0 @@ -package other - -import ( - "bytes" - "context" - "crypto/tls" - "encoding/csv" - "encoding/json" - "fmt" - "log" - "net/url" - "os" - "strings" - - "google.golang.org/grpc" - "google.golang.org/grpc/credentials" - "google.golang.org/grpc/credentials/insecure" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" - - "github.com/atotto/clipboard" - "github.com/jhump/protoreflect/dynamic" - "github.com/jhump/protoreflect/grpcreflect" - "github.com/pterm/pterm" - "github.com/spf13/cobra" - "gopkg.in/yaml.v3" -) - -var parameters []string -var jsonParameter string -var fileParameter string -var apiVersion string -var outputFormat string -var copyToClipboard bool - -// Config structure to parse environment files -type Config struct { - Environment string `yaml:"environment"` - Environments map[string]Environment `yaml:"environments"` -} - -type Environment struct { - Endpoint string `yaml:"endpoint"` - Proxy bool `yaml:"proxy"` - Token string `yaml:"token"` -} - -var ExecCmd = &cobra.Command{ - Use: "exec [rpc] [service].[resource]", - Short: "Execute a gRPC request to a specified service and message", - Long: `Executes a gRPC command to a given service and message based on environment configuration. - For example: cfctl exec list identity.User`, - Args: cobra.ExactArgs(2), - Run: runExecCommand, -} - -func runExecCommand(cmd *cobra.Command, args []string) { - config, err := loadConfig() - if err != nil { - log.Fatalf("Failed to load config: %v", err) - } - - currentEnv, err := fetchCurrentEnvironment(config) - if err != nil { - log.Fatalf("Failed to get current environment: %v", err) - } - - verbName := args[0] - serviceResource := args[1] - parts := strings.Split(serviceResource, ".") - if len(parts) != 2 { - log.Fatalf("Invalid service and resource format. Use [service].[resource]") - } - serviceName := parts[0] - resourceName := parts[1] - - // Fetch endpoints map - endpointsMap, err := fetchEndpointsMap(currentEnv.Endpoint) - if err != nil { - log.Fatalf("Failed to fetch endpoints map: %v", err) - } - - endpoint, ok := endpointsMap[serviceName] - if !ok { - log.Fatalf("Service endpoint not found for service: %s", serviceName) - } - - parsedURL, err := url.Parse(endpoint) - if err != nil { - log.Fatalf("Invalid endpoint URL %s: %v", endpoint, err) - } - grpcEndpoint := fmt.Sprintf("%s:%s", parsedURL.Hostname(), parsedURL.Port()) - - // Set up secure connection - var opts []grpc.DialOption - if parsedURL.Scheme == "grpc+ssl" { - tlsConfig := &tls.Config{ - InsecureSkipVerify: false, - } - creds := credentials.NewTLS(tlsConfig) - opts = append(opts, grpc.WithTransportCredentials(creds)) - } else { - opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) - } - - conn, err := grpc.Dial(grpcEndpoint, opts...) - if err != nil { - log.Fatalf("Failed to connect to gRPC server: %v", err) - } - defer conn.Close() - - ctx := metadata.AppendToOutgoingContext(context.Background(), "token", currentEnv.Token) - - // Use Reflection to discover services - refClient := grpcreflect.NewClient(ctx, grpc_reflection_v1alpha.NewServerReflectionClient(conn)) - defer refClient.Reset() - - // Construct the full service name - fullServiceName, err := discoverService(refClient, serviceName, resourceName) - if err != nil { - log.Fatalf("Failed to discover service: %v", err) - } - - // Resolve the service and method - serviceDesc, err := refClient.ResolveService(fullServiceName) - if err != nil { - log.Fatalf("Failed to resolve service %s: %v", fullServiceName, err) - } - - methodDesc := serviceDesc.FindMethodByName(verbName) - if methodDesc == nil { - log.Fatalf("Method %s not found in service %s", verbName, fullServiceName) - } - - // Create a dynamic message for the request - reqMsg := dynamic.NewMessage(methodDesc.GetInputType()) - - // Parse the input parameters into the request message - inputParams := parseParameters(fileParameter, jsonParameter, parameters) - for key, value := range inputParams { - if err := reqMsg.TrySetFieldByName(key, value); err != nil { - log.Fatalf("Failed to set field %s: %v", key, err) - } - } - - // Prepare response placeholder - respMsg := dynamic.NewMessage(methodDesc.GetOutputType()) - - // Make the RPC call - fullMethod := fmt.Sprintf("/%s/%s", fullServiceName, verbName) - err = conn.Invoke(ctx, fullMethod, reqMsg, respMsg) - if err != nil { - log.Fatalf("Failed to call method %s: %v", verbName, err) - } - - // Convert the response to a map - respMap, err := messageToMap(respMsg) - if err != nil { - log.Fatalf("Failed to convert response message to map: %v", err) - } - - jsonData, err := json.Marshal(respMap) - if err != nil { - log.Fatalf("Failed to marshal response to JSON: %v", err) - } - - var prettyMap map[string]interface{} - if err := json.Unmarshal(jsonData, &prettyMap); err != nil { - log.Fatalf("Failed to unmarshal JSON data: %v", err) - } - - printData(prettyMap, outputFormat) -} - -func loadConfig() (*Config, error) { - configPath := fmt.Sprintf("%s/.cfctl/config.yaml", os.Getenv("HOME")) - data, err := os.ReadFile(configPath) - if err != nil { - return nil, fmt.Errorf("could not read config file: %w", err) - } - - var config Config - if err := yaml.Unmarshal(data, &config); err != nil { - return nil, fmt.Errorf("could not unmarshal config: %w", err) - } - - return &config, nil -} - -func fetchCurrentEnvironment(config *Config) (*Environment, error) { - currentEnv, ok := config.Environments[config.Environment] - if !ok { - return nil, fmt.Errorf("current environment '%s' not found in config", config.Environment) - } - return ¤tEnv, nil -} - -func discoverService(refClient *grpcreflect.Client, serviceName, resourceName string) (string, error) { - possibleVersions := []string{"v1", "v2"} - - for _, version := range possibleVersions { - fullServiceName := fmt.Sprintf("spaceone.api.%s.%s.%s", serviceName, version, resourceName) - if _, err := refClient.ResolveService(fullServiceName); err == nil { - return fullServiceName, nil - } - } - - return "", fmt.Errorf("service not found for %s.%s", serviceName, resourceName) -} - -func parseParameters(fileParameter, jsonParameter string, params []string) map[string]interface{} { - parsed := make(map[string]interface{}) - - // Load from file parameter if provided - if fileParameter != "" { - data, err := os.ReadFile(fileParameter) - if err != nil { - log.Fatalf("Failed to read file parameter: %v", err) - } - - if err := yaml.Unmarshal(data, &parsed); err != nil { - log.Fatalf("Failed to unmarshal YAML file: %v", err) - } - } - - // Load from JSON parameter if provided - if jsonParameter != "" { - if err := json.Unmarshal([]byte(jsonParameter), &parsed); err != nil { - log.Fatalf("Failed to unmarshal JSON parameter: %v", err) - } - } - - // Parse key=value parameters - for _, param := range params { - parts := strings.SplitN(param, "=", 2) - if len(parts) != 2 { - log.Fatalf("Invalid parameter format. Use key=value") - } - parsed[parts[0]] = parts[1] - } - - return parsed -} - -func messageToMap(msg *dynamic.Message) (map[string]interface{}, error) { - result := make(map[string]interface{}) - fields := msg.GetKnownFields() - - for _, fd := range fields { - val := msg.GetField(fd) - - switch v := val.(type) { - case *dynamic.Message: - subMap, err := messageToMap(v) - if err != nil { - return nil, err - } - result[fd.GetName()] = subMap - case []*dynamic.Message: - var subList []map[string]interface{} - for _, subMsg := range v { - subMap, err := messageToMap(subMsg) - if err != nil { - return nil, err - } - subList = append(subList, subMap) - } - result[fd.GetName()] = subList - case map[interface{}]interface{}: - // Convert map[interface{}]interface{} to map[string]interface{} - formattedMap := make(map[string]interface{}) - for key, value := range v { - formattedMap[fmt.Sprintf("%v", key)] = value - } - result[fd.GetName()] = formattedMap - case string: - result[fd.GetName()] = v - default: - result[fd.GetName()] = v - } - } - - return result, nil -} - -func printData(data map[string]interface{}, format string) { - var output string - - switch format { - case "json": - dataBytes, err := json.MarshalIndent(data, "", " ") - if err != nil { - log.Fatalf("Failed to marshal response to JSON: %v", err) - } - output = string(dataBytes) - fmt.Println(output) - - case "yaml": - var buf bytes.Buffer - encoder := yaml.NewEncoder(&buf) - encoder.SetIndent(2) - err := encoder.Encode(data) - if err != nil { - log.Fatalf("Failed to marshal response to YAML: %v", err) - } - output = buf.String() - fmt.Printf("---\n%s\n", output) - - case "table": - output = printTable(data) - - case "csv": - output = printCSV(data) - - default: - log.Fatalf("Unsupported output format: %s", format) - } - - // Copy to clipboard if requested - if copyToClipboard && output != "" { - if err := clipboard.WriteAll(output); err != nil { - log.Fatalf("Failed to copy to clipboard: %v", err) - } - pterm.Success.Println("The output has been copied to your clipboard.") - } -} - -func printTable(data map[string]interface{}) string { - var output string - if results, ok := data["results"].([]interface{}); ok { - tableData := pterm.TableData{} - - // Extract headers - headers := []string{} - if len(results) > 0 { - if row, ok := results[0].(map[string]interface{}); ok { - for key := range row { - headers = append(headers, key) - } - } - } - - // Append headers to table data - tableData = append(tableData, headers) - - // Extract rows - for _, result := range results { - if row, ok := result.(map[string]interface{}); ok { - rowData := []string{} - for _, key := range headers { - rowData = append(rowData, fmt.Sprintf("%v", row[key])) - } - tableData = append(tableData, rowData) - } - } - - // Disable styling only for the table output - pterm.DisableStyling() - renderedOutput, err := pterm.DefaultTable.WithHasHeader(true).WithData(tableData).Srender() - pterm.EnableStyling() // Re-enable styling for other outputs - if err != nil { - log.Fatalf("Failed to render table: %v", err) - } - output = renderedOutput - fmt.Println(output) // Print to console - } - return output -} - -func printCSV(data map[string]interface{}) string { - var buf bytes.Buffer - if results, ok := data["results"].([]interface{}); ok { - writer := csv.NewWriter(&buf) - var headers []string - - // Extract headers - for _, result := range results { - if row, ok := result.(map[string]interface{}); ok { - if headers == nil { - for key := range row { - headers = append(headers, key) - } - writer.Write(headers) - } - - // Extract row values - var rowValues []string - for _, key := range headers { - if val, ok := row[key]; ok { - rowValues = append(rowValues, fmt.Sprintf("%v", val)) - } else { - rowValues = append(rowValues, "") - } - } - writer.Write(rowValues) - } - } - - writer.Flush() - output := buf.String() - fmt.Print(output) // Print to console - return output - } - return "" -} - -func init() { - ExecCmd.Flags().StringArrayVarP(¶meters, "parameter", "p", []string{}, "Input Parameter (-p = -p ...)") - ExecCmd.Flags().StringVarP(&jsonParameter, "json-parameter", "j", "", "JSON type parameter") - ExecCmd.Flags().StringVarP(&fileParameter, "file-parameter", "f", "", "YAML file parameter") - ExecCmd.Flags().StringVarP(&apiVersion, "api-version", "v", "v1", "API Version") - ExecCmd.Flags().StringVarP(&outputFormat, "output", "o", "yaml", "Output format (yaml, json, table, csv)") - ExecCmd.Flags().BoolVarP(©ToClipboard, "copy", "c", false, "Copy the output to the clipboard (copies any output format)") -} diff --git a/cmd/root.go b/cmd/root.go index 8ea24e1..8fc8c3b 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -20,6 +20,7 @@ var rootCmd = &cobra.Command{ Short: "cfctl controls the SpaceONE services.", Long: `cfctl controls the SpaceONE services. Find more information at: + - https://github.com/cloudforet-io/cfctl - https://docs.spaceone.megazone.io/developers/setup/cfctl (English) - https://docs.spaceone.megazone.io/ko/developers/setup/cfctl (Korean)`, // Uncomment the following line if your bare application @@ -50,10 +51,8 @@ func init() { Title: "Other Commands:", } rootCmd.AddGroup(OtherCommands) - rootCmd.AddCommand(other.AiCmd) rootCmd.AddCommand(other.ApiResourcesCmd) rootCmd.AddCommand(other.ConfigCmd) - rootCmd.AddCommand(other.ExecCmd) rootCmd.AddCommand(other.LoginCmd) for _, cmd := range rootCmd.Commands() { diff --git a/training/api-resources.txt b/training/api-resources.txt deleted file mode 100644 index ae612a3..0000000 --- a/training/api-resources.txt +++ /dev/null @@ -1,117 +0,0 @@ -Service | Resource | Short Names | Verb -board | Health | | Check, Watch -board | Post | | create, update, send, delete, get, list, stat -board | ServerInfo | | get_version -config | Health | | Check, Watch -config | ServerInfo | | get_version -config | UserConfig | | create, update, set, delete, get, list, stat -config | PublicConfig | | create, update, delete, get, list, stat -config | DomainConfig | | create, update, set, delete, get, list, stat -cost_analysis | ServerInfo | | get_version -cost_analysis | Job | | cancel, get, list, stat -cost_analysis | Cost | | create, delete, get, list, analyze, stat -cost_analysis | Budget | | create, update, set_notification, delete, get, list, stat -cost_analysis | Health | | Check, Watch -cost_analysis | CostQuerySet | | create, update, delete, get, list, stat -cost_analysis | CostReport | | send, get_url, get, list, stat -cost_analysis | CostReportConfig | | create, update, update_recipients, enable, disable, delete, run, get, list, stat -cost_analysis | CostReportData | | list, analyze, stat -cost_analysis | DataSource | | register, update, update_permissions, update_plugin, update_secret_data, verify_plugin, enable, disable, deregister, sync, get, list, stat -cost_analysis | DataSourceAccount | | update, reset, get, list, analyze, stat -cost_analysis | BudgetUsage | | list, analyze, stat -cost_analysis | DataSourceRule | | create, update, change_order, delete, get, list, stat -cost_analysis | UnifiedCost | | get, list, analyze, stat -cost_analysis | JobTask | | get, list, stat -dashboard | PrivateFolder | | create, update, delete, get, list, stat -dashboard | PublicWidget | | create, update, delete, load, get, list -dashboard | PublicFolder | | create, update, share, unshare, delete, get, list, stat -dashboard | PublicDataTable | | add, transform, update, delete, load, get, list -dashboard | PublicDashboard | | create, update, change_folder, share, unshare, delete, get, list, stat -dashboard | PrivateWidget | | create, update, delete, load, get, list -dashboard | Health | | Check, Watch -dashboard | PrivateDataTable | | add, transform, update, delete, load, get, list -dashboard | PrivateDashboard | | create, update, change_folder, delete, get, list, stat -dashboard | ServerInfo | | get_version -file_manager | Health | | Check, Watch -file_manager | File | | add, update, delete, get_download_url, get, list, stat -file_manager | ServerInfo | | get_version -identity | RoleBinding | | create, update_role, delete, get, list, stat -identity | ServerInfo | | get_version -identity | Agent | | create, enable, disable, regenerate, delete, get, list -identity | App | | create, update, generate_client_secret, enable, disable, delete, get, check, list, stat -identity | Domain | | create, update, delete, enable, disable, get, get_auth_info, get_public_key, list, stat -identity | Endpoint | | list -identity | ExternalAuth | | set, unset, get -identity | Job | | delete, get, list, stat -identity | Project | | create, update, update_project_type, change_project_group, delete, add_users, remove_users, get, list, stat -identity | ProjectGroup | | create, update, change_parent_group, delete, add_users, remove_users, get, list, stat -identity | Health | | Check, Watch -identity | Provider | | create, update, update_plugin, delete, get, list, stat -identity | Role | | create, update, enable, disable, delete, get, list, list_basic_role, stat -identity | System | | init -identity | Schema | | create, update, delete, get, list, stat -identity | ServiceAccount | | create, update, update_secret_data, delete_secret_data, delete, get, list, stat -identity | Token | it | issue, grant -identity | TrustedAccount | | create, update, update_secret_data, delete, sync, get, list, stat -identity | User | iu | create, update, verify_email, disable_mfa, set_required_actions, set_refresh_timeout, enable, disable, delete, get, list, stat -identity | UserGroup | | create, update, delete, add_users, remove_users, get, list, stat -identity | UserProfile | | update, verify_email, confirm_email, reset_password, enable_mfa, disable_mfa, confirm_mfa, get, get_workspaces, get_workspace_groups -identity | Workspace | | create, update, change_workspace_group, delete, enable, disable, get, check, list, stat -identity | WorkspaceGroup | | create, update, delete, add_users, remove_users, update_role, get, list, stat -identity | WorkspaceGroupUser | | add, remove, update_role, find, get, list, stat -identity | WorkspaceUser | | create, get, find, list, stat -inventory | MetricExample | | create, update, delete, get, list, stat -inventory | Note | | create, update, delete, get, list, stat -inventory | Region | | create, update, delete, get, list, stat -inventory | MetricData | | list, stat, analyze -inventory | Namespace | | create, update, delete, get, list, stat -inventory | Metric | | create, update, delete, run, test, get, list, stat -inventory | JobTask | | delete, get, list, stat -inventory | Job | | delete, get, list, analyze, stat -inventory | CollectorRule | | create, update, change_order, delete, get, list, stat -inventory | Collector | | create, update, update_plugin, verify_plugin, delete, get, list, stat, collect -inventory | CloudServiceType | | create, update, delete, get, list, stat -inventory | CloudServiceStats | | list, analyze, stat -inventory | Health | | Check, Watch -inventory | ServerInfo | | get_version -inventory | ChangeHistory | | list, stat -inventory | CloudService | | create, update, delete, get, list, export, analyze, stat -inventory | CloudServiceQuerySet | | create, update, delete, run, test, enable, disable, get, list, stat -inventory | CloudServiceReport | | create, update, delete, send, get, list, stat -monitoring | Health | | Check, Watch -monitoring | DataSource | | register, update, enable, disable, deregister, update_plugin, verify_plugin, get, list, stat -monitoring | EscalationPolicy | | create, update, set_default, delete, get, list, stat -monitoring | Event | | create, get, list, stat -monitoring | EventRule | | create, update, change_order, delete, get, list, stat -monitoring | Log | | list -monitoring | Metric | | list, get_data -monitoring | ServerInfo | | get_version -monitoring | Alert | | create, update, assign_user, update_state, delete, get, list, stat -monitoring | Note | | create, update, delete, get, list, stat -monitoring | ProjectAlertConfig | | create, update, delete, get, list, stat -monitoring | Webhook | | create, update, update_plugin, verify_plugin, enable, disable, delete, get, list, stat -notification | Health | | Check, Watch -notification | Protocol | | create, update, update_plugin, enable, disable, delete, get, list, stat -notification | ProjectChannel | | create, update, set_schedule, set_subscription, enable, disable, delete, get, list, stat -notification | Notification | | create, push, delete, set_read, get, list, stat -notification | ServerInfo | | get_version -notification | UserChannel | | create, update, set_schedule, set_subscription, enable, disable, delete, get, list, stat -plugin | Supervisor | | publish, register, update, deregister, enable, disable, recover_plugin, get, list, stat, list_plugins -plugin | Health | | Check, Watch -plugin | ServerInfo | | get_version -plugin | Plugin | | get_plugin_endpoint, get_plugin_metadata, notify_failure -repository | Health | | Check, Watch -repository | ServerInfo | | get_version -repository | Plugin | rp | register, update, deregister, enable, disable, get_versions, get, list -repository | DashboardTemplate | | register, update, deregister, enable, disable, get, list -repository | Repository | | list -secret | TrustedSecret | | create, update, delete, update_data, get_data, get, list, stat -secret | Health | | Check, Watch -secret | ServerInfo | | get_version -secret | Secret | | create, update, delete, enable, disable, update_data, get_data, get, list, stat -secret | UserSecret | | create, update, delete, update_data, get_data, get, list, stat -statistics | Schedule | | add, update, enable, disable, delete, get, list, stat -statistics | Health | | Check, Watch -statistics | ServerInfo | | get_version -statistics | History | | create, list, stat -statistics | Resource | | stat