diff --git a/.cursor/skills/create-ticloud-cli-command/SKILL.md b/.cursor/skills/create-ticloud-cli-command/SKILL.md deleted file mode 100644 index 1f1657d5..00000000 --- a/.cursor/skills/create-ticloud-cli-command/SKILL.md +++ /dev/null @@ -1,127 +0,0 @@ ---- -name: create-ticloud-cli-command -description: Builds TiDB Cloud CLI commands. Use when creating new commands. -license: Complete terms in LICENSE.txt -metadata: - author: shiyuhang0 ---- - -# Create TiCloud CLI Command - -This skill builds TiDB Cloud CLI commands, helping users create new commands with production-ready code. - -## When to use - -- The user asks to create new CLI commands or subcommands. -- Do not use when the agent does not support plan mode. - -## About TiDB Cloud CLI - -TiDB Cloud CLI (TiCloud CLI) is a command-line interface for interacting with TiDB Cloud, built on the Cobra library. - -Key design of TiDB Cloud CLI: -- Built on the Cobra library. -- Uses the TiDB Cloud Open API as the client and keeps the SDK inside the project. -- Every command supports both interactive and non-interactive modes. - -- More about TiDB Cloud CLI: `references/tidbcloud-cli.md`. -- More about Cobra: `references/cobra.md`. - -## Core Principles - -### Plan first - -The AI agent must switch to plan mode to collect information from the user and generate a plan first. - -Then use agent mode to generate the code. - -### Test first - -If the user requires testing, testing takes precedence over implementation. Write tests first, then implement, and finally validate against the tests. - -### Declarative - -The user must declare the command format; the implementation must comply with that declared format. - -## Workflow - -Must follow the workflow below: - -### Generate SDK phase - -Detect whether there are new or modified Swagger files under `/pkg/tidbcloud`. Skip this phase if none are found. - -If detection fails, prompt the user: "Do you need to update swagger and generate SDK?" Skip this phase if the user does not need it. - -Once in this phase, follow the guide in `references/sdk.md` to generate the SDK. - -### Plan phase - -The agent must switch to plan mode in this phase. - -The agent must ask the user for the following information during the plan phase: -1. **Command format**: If the user does not provide the command format, ask them to provide it first. See `assets/command.md` for the command format template. -2. **Tests**: Ask whether the user needs tests. Tests are recommended. -3. **Other necessary information** - -Generate the plan after the user confirms all the information. - -### Agent phase - -The agent must switch to agent mode in this phase. Follow the workflow below: - -1. **Write unit tests** -2. **Implement command** -3. **Run tests** - -#### Write unit tests - -Skip this step if the user does not need tests. - -Write unit tests following `references/ut.md`. If the tests need to invoke the command, create the empty command first. See `assets/empty.go`. - -#### Implement command - -Implement the command following the patterns in `assets/example`. - -The implementation must meet the following requirements: - -1. **Command definition**: Include name, aliases, example, and other necessary attributes. - -2. **Flags definition**: Include flag type, description, default value, etc. Infer flag information from the Swagger spec and SDK client parameters. See `references/flag.md` for more details. - -3. **Flags retrieval**: Implement retrieval logic for both interactive and non-interactive modes. For interactive mode, UI is required. The UI is based on the Bubbletea library. See `references/ui.md` for more details. - -4. **Dual mode support**: Support both interactive and non-interactive modes. Rules: - 1. **Detect mode** with `MarkInteractive`: - - Default to interactive. - - If any non-interactive flag is provided, switch to non-interactive and mark required flags. - 2. **Interactive constraints**: - - If `!h.IOStreams.CanPrompt`, return an error instructing the user to use non-interactive flags. - -5. **SDK calls**: Use the SDK client in `api_client.go` to call the corresponding method. Note that `assets/example` does not include this part (it is only a template); it must be included when implementing the actual command. - -#### Run the tests - -Skip this step if the user does not need tests. - -Run tests with: `go test -race -cover -count=1 path -v` - -For example, to run tests under `internal/cli/serverless/branch`: `go test -race -cover -count=1 ./internal/cli/serverless/branch -v`. - -Ensure all tests pass. If they do not pass, fix the implementation or the tests. - -## Final Code Structure - -The final code structure must follow the structure in `assets/example`: - -- Command Go files. -- UI Go files. -- Test files if needed. - -Command output should follow the patterns in `assets/example`: - -- **Human output**: Print a concise, user-friendly message; use `color.GreenString` for success. Avoid raw JSON in human mode. -- **JSON output**: Use `output.PrintJson` with a stable, predictable payload (e.g. keys like `message`, resource IDs, `items`). -- **No TTY**: Default to JSON output for list/describe-style commands (see `assets/example/list.go`). -- **Examples**: Include `Example` blocks for both interactive and non-interactive usage (see `assets/example/create.go` and `assets/example/list.go`). \ No newline at end of file diff --git a/.cursor/skills/update-ticloud-cli-command/SKILL.md b/.cursor/skills/update-ticloud-cli-command/SKILL.md deleted file mode 100644 index d4aee2df..00000000 --- a/.cursor/skills/update-ticloud-cli-command/SKILL.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -name: update-ticloud-cli-command -description: Update TiDB Cloud CLI commands. Use when adding new flags or updating existing commands. -license: Complete terms in LICENSE.txt -metadata: - author: shiyuhang0 ---- - -# Update TiCloud CLI Command - -This skill updates TiDB Cloud CLI existing commands, helping users update existing commands with production-ready code. - -## When to use - -- The user asks to add flags to existing commands. -- The user asks to update logic of existing commands. - -## About TiDB Cloud CLI - -TiDB Cloud CLI (TiCloud CLI) is a command-line interface for interacting with TiDB Cloud, built on the Cobra library. - -Key design of TiDB Cloud CLI: -- Built on the Cobra library. -- Uses the TiDB Cloud Open API as the client and keeps the SDK inside the project. -- Every command supports both interactive and non-interactive modes. - -- More about TiDB Cloud CLI: `references/tidbcloud-cli.md`. -- More about Cobra: `references/cobra.md`. - -## Workflow - -Must follow the workflow below: - -### Generate SDK phase - -Detect whether there are new or modified Swagger files under `/pkg/tidbcloud`. Skip this phase if none are found. - -If detection fails, prompt the user: "Do you need to update swagger and generate SDK?" Skip this phase if the user does not need it. - -Once in this phase, follow the guide in `references/sdk.md` to generate the SDK. - -### Plan phase - -The agent needs to switch to plan mode if supported. This phase can be skipped if user already provide enough informations. - -The agent must ask the user for the following information during the plan phase: -1. **Updating Information**: Ask the user for details of the update, including whether new flags need to be added (if yes, request the user to provide them), and whether existing logic needs to be modified (if yes, ask the user to provide a specific description of the logic). -2. **Other necessary information** - -Generate the plan after the user confirms all the information. - -### Agent phase - -The agent must switch to agent mode in this phase. Follow the workflow below: - -1. **Update command** -2. **Write and run tests** - -#### Update command - -Update the command according to user-provided information and current command code style. - -If new flags are added: -- Refer to `references/flag.md` for the flag definition. -- Refer to `references/ui.md` for the UI design. - -#### Write and run the tests - -Skip this step if the test file does not exist. Otherwise, write unit tests following `references/ut.md`. Then run tests with: `go test -race -cover -count=1 path -v` - -For example, to run tests under `internal/cli/serverless/branch`: `go test -race -cover -count=1 ./internal/cli/serverless/branch -v` - -Ensure all tests pass. If they do not pass, fix the implementation or the tests. \ No newline at end of file diff --git a/Makefile b/Makefile index 8a5f60c3..01037d0c 100644 --- a/Makefile +++ b/Makefile @@ -60,6 +60,9 @@ generate-v1beta1-serverless-client: install-openapi-generator ## Generate server rm -rf pkg/tidbcloud/v1beta1/serverless/migration cd tools/openapi-generator && npx openapi-generator-cli generate --inline-schema-options RESOLVE_INLINE_ENUMS=true --additional-properties=withGoMod=false,enumClassPrefix=true,disallowAdditionalPropertiesIfNotPresent=false --global-property=apiTests=false,apiDocs=false,modelDocs=false,modelTests=false -i ../../pkg/tidbcloud/v1beta1/serverless/dm.swagger.json -g go -o ../../pkg/tidbcloud/v1beta1/serverless/migration --package-name migration -c go/config.yaml cd pkg && go fmt ./tidbcloud/v1beta1/serverless/... && goimports -w . + @echo "==> Generating serverless privatelink client" + rm -rf pkg/tidbcloud/v1beta1/serverless/privatelink + cd tools/openapi-generator && npx openapi-generator-cli generate --inline-schema-options RESOLVE_INLINE_ENUMS=true --additional-properties=withGoMod=false,enumClassPrefix=true,disallowAdditionalPropertiesIfNotPresent=false --global-property=apiTests=false,apiDocs=false,modelDocs=false,modelTests=false -i ../../pkg/tidbcloud/v1beta1/serverless/privatelink.swagger.json -g go -o ../../pkg/tidbcloud/v1beta1/serverless/privatelink --package-name privatelink -c go/config.yaml .PHONY: generate-v1beta1-dedicated-client generate-v1beta1-dedicated-client: install-openapi-generator ## Generate dedicated client diff --git a/internal/cli/serverless/changefeed/changefeed.go b/internal/cli/serverless/changefeed/changefeed.go index fa9504c3..da822921 100644 --- a/internal/cli/serverless/changefeed/changefeed.go +++ b/internal/cli/serverless/changefeed/changefeed.go @@ -35,5 +35,6 @@ func ChangefeedCmd(h *internal.Helper) *cobra.Command { changefeedCmd.AddCommand(TemplateCmd(h)) changefeedCmd.AddCommand(PauseCmd(h)) changefeedCmd.AddCommand(ResumeCmd(h)) + changefeedCmd.AddCommand(PrivateLinkCmd(h)) return changefeedCmd } diff --git a/internal/cli/serverless/changefeed/private_link.go b/internal/cli/serverless/changefeed/private_link.go new file mode 100644 index 00000000..17f0efd1 --- /dev/null +++ b/internal/cli/serverless/changefeed/private_link.go @@ -0,0 +1,32 @@ +// Copyright 2026 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package changefeed + +import ( + "github.com/spf13/cobra" + "github.com/tidbcloud/tidbcloud-cli/internal" +) + +func PrivateLinkCmd(h *internal.Helper) *cobra.Command { + var privateLinkCmd = &cobra.Command{ + Use: "private-link", + Short: "Manage TiDB Cloud Serverless changefeed private link endpoints", + } + + privateLinkCmd.AddCommand(PrivateLinkCreateCmd(h)) + privateLinkCmd.AddCommand(PrivateLinkDescribeCmd(h)) + privateLinkCmd.AddCommand(PrivateLinkDeleteCmd(h)) + return privateLinkCmd +} diff --git a/internal/cli/serverless/changefeed/private_link_create.go b/internal/cli/serverless/changefeed/private_link_create.go new file mode 100644 index 00000000..7d98b884 --- /dev/null +++ b/internal/cli/serverless/changefeed/private_link_create.go @@ -0,0 +1,210 @@ +// Copyright 2026 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package changefeed + +import ( + "fmt" + "strings" + + "github.com/fatih/color" + "github.com/juju/errors" + "github.com/spf13/cobra" + + "github.com/tidbcloud/tidbcloud-cli/internal" + "github.com/tidbcloud/tidbcloud-cli/internal/config" + "github.com/tidbcloud/tidbcloud-cli/internal/flag" + "github.com/tidbcloud/tidbcloud-cli/internal/service/cloud" + "github.com/tidbcloud/tidbcloud-cli/internal/ui" + "github.com/tidbcloud/tidbcloud-cli/internal/util" + "github.com/tidbcloud/tidbcloud-cli/pkg/tidbcloud/v1beta1/serverless/cdc" + + "github.com/charmbracelet/bubbles/textinput" + tea "github.com/charmbracelet/bubbletea" +) + +type PrivateLinkCreateOpts struct { + interactive bool +} + +func (c PrivateLinkCreateOpts) NonInteractiveFlags() []string { + return []string{ + flag.ClusterID, + flag.PrivateLinkServiceName, + flag.ChangefeedType, + } +} + +func (c PrivateLinkCreateOpts) RequiredFlags() []string { + return []string{ + flag.ClusterID, + flag.PrivateLinkServiceName, + flag.ChangefeedType, + } +} + +func (c *PrivateLinkCreateOpts) MarkInteractive(cmd *cobra.Command) error { + flags := c.NonInteractiveFlags() + for _, fn := range flags { + f := cmd.Flags().Lookup(fn) + if f != nil && f.Changed { + c.interactive = false + break + } + } + if !c.interactive { + for _, fn := range c.RequiredFlags() { + if err := cmd.MarkFlagRequired(fn); err != nil { + return err + } + } + } + return nil +} + +func PrivateLinkCreateCmd(h *internal.Helper) *cobra.Command { + opts := PrivateLinkCreateOpts{ + interactive: true, + } + + var createCmd = &cobra.Command{ + Use: "create", + Short: "Create a changefeed private link endpoint", + Args: cobra.NoArgs, + Example: fmt.Sprintf(` Create a changefeed private link endpoint in interactive mode: + $ %[1]s serverless changefeed private-link create + + Create a changefeed private link endpoint in non-interactive mode: + $ %[1]s serverless changefeed private-link create -c --private-link-service-name --type `, + config.CliName), + PreRunE: func(cmd *cobra.Command, args []string) error { + return opts.MarkInteractive(cmd) + }, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + d, err := h.Client() + if err != nil { + return err + } + + var clusterID string + var privateLinkServiceName string + var changefeedTypeRaw string + if opts.interactive { + if !h.IOStreams.CanPrompt { + return errors.New("The terminal doesn't support interactive mode, please use non-interactive mode") + } + + project, err := cloud.GetSelectedProject(ctx, h.QueryPageSize, d) + if err != nil { + return err + } + cluster, err := cloud.GetSelectedCluster(ctx, project.ID, h.QueryPageSize, d) + if err != nil { + return err + } + clusterID = cluster.ID + + changefeedTypeRaw, err = cloud.GetSelectedField([]string{ + string(cdc.CHANGEFEEDTYPEENUM_KAFKA), + string(cdc.CHANGEFEEDTYPEENUM_MYSQL), + }, "Choose the changefeed type:") + if err != nil { + return err + } + + privateLinkServiceName, err = promptPrivateLinkServiceName() + if err != nil { + return err + } + } else { + clusterID, err = cmd.Flags().GetString(flag.ClusterID) + if err != nil { + return errors.Trace(err) + } + privateLinkServiceName, err = cmd.Flags().GetString(flag.PrivateLinkServiceName) + if err != nil { + return errors.Trace(err) + } + changefeedTypeRaw, err = cmd.Flags().GetString(flag.ChangefeedType) + if err != nil { + return errors.Trace(err) + } + } + + privateLinkServiceName = strings.TrimSpace(privateLinkServiceName) + if privateLinkServiceName == "" { + return errors.New("private link service name is required") + } + + changefeedType, err := normalizeChangefeedType(changefeedTypeRaw) + if err != nil { + return err + } + + body := cdc.NewChangefeedServiceCreatePrivateLinkEndpointBody(privateLinkServiceName, changefeedType) + _, err = d.CreatePrivateLinkEndpoint(ctx, clusterID, body) + if err != nil { + return errors.Trace(err) + } + + _, err = fmt.Fprintln(h.IOStreams.Out, color.GreenString("private link endpoint %s is created", privateLinkServiceName)) + if err != nil { + return err + } + return nil + }, + } + + createCmd.Flags().StringP(flag.ClusterID, flag.ClusterIDShort, "", "The ID of the cluster.") + createCmd.Flags().StringP(flag.PrivateLinkServiceName, "", "", "The private link service name.") + createCmd.Flags().StringP(flag.ChangefeedType, "", "", "The changefeed type, one of [\"KAFKA\" \"MYSQL\"].") + return createCmd +} + +func promptPrivateLinkServiceName() (string, error) { + model := ui.TextInputModel{ + Inputs: make([]textinput.Model, 1), + } + t := textinput.New() + t.Cursor.Style = config.CursorStyle + t.CharLimit = 64 + t.Placeholder = "Private Link Service Name" + t.Focus() + t.PromptStyle = config.FocusedStyle + t.TextStyle = config.FocusedStyle + model.Inputs[0] = t + + p := tea.NewProgram(model) + inputModel, err := p.Run() + if err != nil { + return "", errors.Trace(err) + } + if inputModel.(ui.TextInputModel).Interrupted { + return "", util.InterruptError + } + return inputModel.(ui.TextInputModel).Inputs[0].Value(), nil +} + +func normalizeChangefeedType(input string) (cdc.ChangefeedTypeEnum, error) { + value := strings.TrimSpace(strings.ToUpper(input)) + switch value { + case string(cdc.CHANGEFEEDTYPEENUM_KAFKA): + return cdc.CHANGEFEEDTYPEENUM_KAFKA, nil + case string(cdc.CHANGEFEEDTYPEENUM_MYSQL): + return cdc.CHANGEFEEDTYPEENUM_MYSQL, nil + default: + return "", fmt.Errorf("invalid changefeed type: %s", input) + } +} diff --git a/internal/cli/serverless/changefeed/private_link_delete.go b/internal/cli/serverless/changefeed/private_link_delete.go new file mode 100644 index 00000000..b3fc7882 --- /dev/null +++ b/internal/cli/serverless/changefeed/private_link_delete.go @@ -0,0 +1,138 @@ +// Copyright 2026 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package changefeed + +import ( + "fmt" + "strings" + + "github.com/fatih/color" + "github.com/juju/errors" + "github.com/spf13/cobra" + + "github.com/tidbcloud/tidbcloud-cli/internal" + "github.com/tidbcloud/tidbcloud-cli/internal/config" + "github.com/tidbcloud/tidbcloud-cli/internal/flag" + "github.com/tidbcloud/tidbcloud-cli/internal/service/cloud" +) + +type PrivateLinkDeleteOpts struct { + interactive bool +} + +func (c PrivateLinkDeleteOpts) NonInteractiveFlags() []string { + return []string{ + flag.ClusterID, + flag.PrivateLinkServiceName, + } +} + +func (c *PrivateLinkDeleteOpts) MarkInteractive(cmd *cobra.Command) error { + flags := c.NonInteractiveFlags() + for _, fn := range flags { + f := cmd.Flags().Lookup(fn) + if f != nil && f.Changed { + c.interactive = false + break + } + } + if !c.interactive { + for _, fn := range flags { + if err := cmd.MarkFlagRequired(fn); err != nil { + return err + } + } + } + return nil +} + +func PrivateLinkDeleteCmd(h *internal.Helper) *cobra.Command { + opts := PrivateLinkDeleteOpts{ + interactive: true, + } + + var deleteCmd = &cobra.Command{ + Use: "delete", + Short: "Delete a changefeed private link endpoint", + Args: cobra.NoArgs, + Example: fmt.Sprintf(` Delete a changefeed private link endpoint in interactive mode: + $ %[1]s serverless changefeed private-link delete + + Delete a changefeed private link endpoint in non-interactive mode: + $ %[1]s serverless changefeed private-link delete -c --private-link-service-name `, + config.CliName), + PreRunE: func(cmd *cobra.Command, args []string) error { + return opts.MarkInteractive(cmd) + }, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + d, err := h.Client() + if err != nil { + return err + } + + var clusterID, privateLinkServiceName string + if opts.interactive { + if !h.IOStreams.CanPrompt { + return errors.New("The terminal doesn't support interactive mode, please use non-interactive mode") + } + + project, err := cloud.GetSelectedProject(ctx, h.QueryPageSize, d) + if err != nil { + return err + } + cluster, err := cloud.GetSelectedCluster(ctx, project.ID, h.QueryPageSize, d) + if err != nil { + return err + } + clusterID = cluster.ID + + privateLinkServiceName, err = promptPrivateLinkServiceName() + if err != nil { + return err + } + } else { + clusterID, err = cmd.Flags().GetString(flag.ClusterID) + if err != nil { + return errors.Trace(err) + } + privateLinkServiceName, err = cmd.Flags().GetString(flag.PrivateLinkServiceName) + if err != nil { + return errors.Trace(err) + } + } + + privateLinkServiceName = strings.TrimSpace(privateLinkServiceName) + if privateLinkServiceName == "" { + return errors.New("private link service name is required") + } + + _, err = d.DeletePrivateLinkEndpoint(ctx, clusterID, privateLinkServiceName) + if err != nil { + return errors.Trace(err) + } + + _, err = fmt.Fprintln(h.IOStreams.Out, color.GreenString("private link endpoint %s is deleted", privateLinkServiceName)) + if err != nil { + return err + } + return nil + }, + } + + deleteCmd.Flags().StringP(flag.ClusterID, flag.ClusterIDShort, "", "The ID of the cluster.") + deleteCmd.Flags().StringP(flag.PrivateLinkServiceName, "", "", "The private link service name.") + return deleteCmd +} diff --git a/internal/cli/serverless/changefeed/private_link_describe.go b/internal/cli/serverless/changefeed/private_link_describe.go new file mode 100644 index 00000000..8ecd33a0 --- /dev/null +++ b/internal/cli/serverless/changefeed/private_link_describe.go @@ -0,0 +1,136 @@ +// Copyright 2026 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package changefeed + +import ( + "fmt" + "strings" + + "github.com/juju/errors" + "github.com/spf13/cobra" + + "github.com/tidbcloud/tidbcloud-cli/internal" + "github.com/tidbcloud/tidbcloud-cli/internal/config" + "github.com/tidbcloud/tidbcloud-cli/internal/flag" + "github.com/tidbcloud/tidbcloud-cli/internal/output" + "github.com/tidbcloud/tidbcloud-cli/internal/service/cloud" +) + +type PrivateLinkDescribeOpts struct { + interactive bool +} + +func (c PrivateLinkDescribeOpts) NonInteractiveFlags() []string { + return []string{ + flag.ClusterID, + flag.PrivateLinkServiceName, + } +} + +func (c *PrivateLinkDescribeOpts) MarkInteractive(cmd *cobra.Command) error { + flags := c.NonInteractiveFlags() + for _, fn := range flags { + f := cmd.Flags().Lookup(fn) + if f != nil && f.Changed { + c.interactive = false + break + } + } + if !c.interactive { + for _, fn := range flags { + if err := cmd.MarkFlagRequired(fn); err != nil { + return err + } + } + } + return nil +} + +func PrivateLinkDescribeCmd(h *internal.Helper) *cobra.Command { + opts := PrivateLinkDescribeOpts{ + interactive: true, + } + + var describeCmd = &cobra.Command{ + Use: "describe", + Short: "Describe a changefeed private link endpoint", + Aliases: []string{"get"}, + Args: cobra.NoArgs, + Example: fmt.Sprintf(` Get a changefeed private link endpoint in interactive mode: + $ %[1]s serverless changefeed private-link describe + + Get a changefeed private link endpoint in non-interactive mode: + $ %[1]s serverless changefeed private-link describe -c --private-link-service-name `, + config.CliName), + PreRunE: func(cmd *cobra.Command, args []string) error { + return opts.MarkInteractive(cmd) + }, + RunE: func(cmd *cobra.Command, args []string) error { + d, err := h.Client() + if err != nil { + return err + } + ctx := cmd.Context() + + var clusterID, privateLinkServiceName string + if opts.interactive { + if !h.IOStreams.CanPrompt { + return errors.New("The terminal doesn't support interactive mode, please use non-interactive mode") + } + + project, err := cloud.GetSelectedProject(ctx, h.QueryPageSize, d) + if err != nil { + return err + } + cluster, err := cloud.GetSelectedCluster(ctx, project.ID, h.QueryPageSize, d) + if err != nil { + return err + } + clusterID = cluster.ID + + privateLinkServiceName, err = promptPrivateLinkServiceName() + if err != nil { + return err + } + } else { + clusterID, err = cmd.Flags().GetString(flag.ClusterID) + if err != nil { + return errors.Trace(err) + } + privateLinkServiceName, err = cmd.Flags().GetString(flag.PrivateLinkServiceName) + if err != nil { + return errors.Trace(err) + } + } + + privateLinkServiceName = strings.TrimSpace(privateLinkServiceName) + if privateLinkServiceName == "" { + return errors.New("private link service name is required") + } + + endpoint, err := d.GetPrivateLinkEndpoint(ctx, clusterID, privateLinkServiceName) + if err != nil { + return errors.Trace(err) + } + + err = output.PrintJson(h.IOStreams.Out, endpoint) + return errors.Trace(err) + }, + } + + describeCmd.Flags().StringP(flag.ClusterID, flag.ClusterIDShort, "", "The ID of the cluster.") + describeCmd.Flags().StringP(flag.PrivateLinkServiceName, "", "", "The private link service name.") + return describeCmd +} diff --git a/internal/cli/serverless/cluster.go b/internal/cli/serverless/cluster.go index 25b74c74..bed923e5 100644 --- a/internal/cli/serverless/cluster.go +++ b/internal/cli/serverless/cluster.go @@ -23,6 +23,7 @@ import ( "github.com/tidbcloud/tidbcloud-cli/internal/cli/serverless/dataimport" "github.com/tidbcloud/tidbcloud-cli/internal/cli/serverless/export" "github.com/tidbcloud/tidbcloud-cli/internal/cli/serverless/migration" + "github.com/tidbcloud/tidbcloud-cli/internal/cli/serverless/privatelink" "github.com/tidbcloud/tidbcloud-cli/internal/cli/serverless/sqluser" "github.com/spf13/cobra" @@ -54,6 +55,7 @@ func Cmd(h *internal.Helper) *cobra.Command { serverlessCmd.AddCommand(authorizednetwork.AuthorizedNetworkCmd(h)) serverlessCmd.AddCommand(changefeed.ChangefeedCmd(h)) serverlessCmd.AddCommand(migration.MigrationCmd(h)) + serverlessCmd.AddCommand(privatelink.PrivateLinkConnectionCmd(h)) return serverlessCmd } diff --git a/internal/cli/serverless/privatelink/availability_zones.go b/internal/cli/serverless/privatelink/availability_zones.go new file mode 100644 index 00000000..28ce3636 --- /dev/null +++ b/internal/cli/serverless/privatelink/availability_zones.go @@ -0,0 +1,150 @@ +// Copyright 2026 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package privatelink + +import ( + "fmt" + "strings" + + "github.com/tidbcloud/tidbcloud-cli/internal" + "github.com/tidbcloud/tidbcloud-cli/internal/config" + "github.com/tidbcloud/tidbcloud-cli/internal/flag" + "github.com/tidbcloud/tidbcloud-cli/internal/output" + "github.com/tidbcloud/tidbcloud-cli/internal/service/cloud" + + "github.com/juju/errors" + "github.com/spf13/cobra" +) + +type AvailabilityZonesOpts struct { + interactive bool +} + +func (c AvailabilityZonesOpts) NonInteractiveFlags() []string { + return []string{ + flag.ClusterID, + } +} + +func (c *AvailabilityZonesOpts) MarkInteractive(cmd *cobra.Command) error { + flags := c.NonInteractiveFlags() + for _, fn := range flags { + f := cmd.Flags().Lookup(fn) + if f != nil && f.Changed { + c.interactive = false + break + } + } + if !c.interactive { + for _, fn := range flags { + if err := cmd.MarkFlagRequired(fn); err != nil { + return err + } + } + } + return nil +} + +func AvailabilityZonesCmd(h *internal.Helper) *cobra.Command { + opts := AvailabilityZonesOpts{ + interactive: true, + } + + var availabilityZonesCmd = &cobra.Command{ + Use: "availability-zones", + Short: "Get account and availability zones information", + Args: cobra.NoArgs, + Example: fmt.Sprintf(` Get availability zones in interactive mode: + $ %[1]s serverless private-link-connection availability-zones + + Get availability zones in non-interactive mode: + $ %[1]s serverless private-link-connection availability-zones -c `, + config.CliName), + PreRunE: func(cmd *cobra.Command, args []string) error { + return opts.MarkInteractive(cmd) + }, + RunE: func(cmd *cobra.Command, args []string) error { + d, err := h.Client() + if err != nil { + return err + } + ctx := cmd.Context() + + var clusterID string + if opts.interactive { + if !h.IOStreams.CanPrompt { + return errors.New("The terminal doesn't support interactive mode, please use non-interactive mode") + } + project, err := cloud.GetSelectedProject(ctx, h.QueryPageSize, d) + if err != nil { + return err + } + cluster, err := cloud.GetSelectedCluster(ctx, project.ID, h.QueryPageSize, d) + if err != nil { + return err + } + clusterID = cluster.ID + } else { + clusterID, err = cmd.Flags().GetString(flag.ClusterID) + if err != nil { + return errors.Trace(err) + } + } + + resp, err := d.GetPrivateLinkConnectionAvailabilityZones(ctx, clusterID) + if err != nil { + return errors.Trace(err) + } + + format, err := cmd.Flags().GetString(flag.Output) + if err != nil { + return errors.Trace(err) + } + if format == output.JsonFormat || !h.IOStreams.CanPrompt { + err = output.PrintJson(h.IOStreams.Out, resp) + if err != nil { + return errors.Trace(err) + } + return nil + } + if format != output.HumanFormat { + return fmt.Errorf("unsupported output format: %s", format) + } + + columns := []output.Column{"AccountID", "AvailabilityZones"} + availabilityZones := "" + if resp.AzIds != nil { + availabilityZones = strings.Join(resp.AzIds, ", ") + } + rows := []output.Row{{valueOrEmptyString(resp.AccountId), availabilityZones}} + err = output.PrintHumanTable(h.IOStreams.Out, columns, rows) + if err != nil { + return errors.Trace(err) + } + return nil + }, + } + + availabilityZonesCmd.Flags().StringP(flag.ClusterID, flag.ClusterIDShort, "", "The ID of the cluster.") + availabilityZonesCmd.Flags().StringP(flag.Output, flag.OutputShort, output.HumanFormat, flag.OutputHelp) + return availabilityZonesCmd +} + +func valueOrEmptyString(value *string) string { + if value == nil { + return "" + } + return *value +} diff --git a/internal/cli/serverless/privatelink/create.go b/internal/cli/serverless/privatelink/create.go new file mode 100644 index 00000000..0f791899 --- /dev/null +++ b/internal/cli/serverless/privatelink/create.go @@ -0,0 +1,269 @@ +// Copyright 2026 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package privatelink + +import ( + "fmt" + "strings" + + "github.com/tidbcloud/tidbcloud-cli/internal" + "github.com/tidbcloud/tidbcloud-cli/internal/config" + "github.com/tidbcloud/tidbcloud-cli/internal/flag" + "github.com/tidbcloud/tidbcloud-cli/internal/service/cloud" + "github.com/tidbcloud/tidbcloud-cli/internal/ui" + "github.com/tidbcloud/tidbcloud-cli/internal/util" + pl "github.com/tidbcloud/tidbcloud-cli/pkg/tidbcloud/v1beta1/serverless/privatelink" + + "github.com/charmbracelet/bubbles/textinput" + tea "github.com/charmbracelet/bubbletea" + "github.com/fatih/color" + "github.com/juju/errors" + "github.com/spf13/cobra" +) + +type CreateOpts struct { + interactive bool +} + +func (c CreateOpts) NonInteractiveFlags() []string { + return []string{ + flag.ClusterID, + flag.DisplayName, + flag.PrivateLinkConnectionType, + flag.EndpointServiceName, + flag.EndpointServiceRegion, + } +} + +func (c CreateOpts) RequiredFlags() []string { + return []string{ + flag.ClusterID, + flag.DisplayName, + flag.PrivateLinkConnectionType, + flag.EndpointServiceName, + } +} + +func (c *CreateOpts) MarkInteractive(cmd *cobra.Command) error { + flags := c.NonInteractiveFlags() + for _, fn := range flags { + f := cmd.Flags().Lookup(fn) + if f != nil && f.Changed { + c.interactive = false + break + } + } + if !c.interactive { + for _, fn := range c.RequiredFlags() { + if err := cmd.MarkFlagRequired(fn); err != nil { + return err + } + } + } + return nil +} + +func CreateCmd(h *internal.Helper) *cobra.Command { + opts := CreateOpts{ + interactive: true, + } + + var createCmd = &cobra.Command{ + Use: "create", + Short: "Create a private link connection", + Args: cobra.NoArgs, + Example: fmt.Sprintf(` Create a private link connection in interactive mode: + $ %[1]s serverless private-link-connection create + + Create a private link connection in non-interactive mode: + $ %[1]s serverless private-link-connection create --cluster-id --display-name --type --endpoint-service-name `, + config.CliName), + PreRunE: func(cmd *cobra.Command, args []string) error { + return opts.MarkInteractive(cmd) + }, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + d, err := h.Client() + if err != nil { + return err + } + + var clusterID string + var displayName string + var endpointServiceName string + var endpointServiceRegion string + var connectionTypeRaw string + if opts.interactive { + if !h.IOStreams.CanPrompt { + return errors.New("The terminal doesn't support interactive mode, please use non-interactive mode") + } + + project, err := cloud.GetSelectedProject(ctx, h.QueryPageSize, d) + if err != nil { + return err + } + + cluster, err := cloud.GetSelectedCluster(ctx, project.ID, h.QueryPageSize, d) + if err != nil { + return err + } + clusterID = cluster.ID + + connectionTypeRaw, err = cloud.GetSelectedField([]string{ + string(pl.PRIVATELINKCONNECTIONTYPEENUM_AWS_ENDPOINT_SERVICE), + string(pl.PRIVATELINKCONNECTIONTYPEENUM_ALICLOUD_ENDPOINT_SERVICE), + }, "Choose the private link connection type:") + if err != nil { + return err + } + + connectionType, err := normalizePrivateLinkConnectionType(connectionTypeRaw) + if err != nil { + return err + } + includeRegion := connectionType == pl.PRIVATELINKCONNECTIONTYPEENUM_AWS_ENDPOINT_SERVICE + + inputModel, err := getCreateInputModel(includeRegion) + if err != nil { + return err + } + displayName = strings.TrimSpace(inputModel.Inputs[0].Value()) + endpointServiceName = strings.TrimSpace(inputModel.Inputs[1].Value()) + if includeRegion { + endpointServiceRegion = strings.TrimSpace(inputModel.Inputs[2].Value()) + } + } else { + clusterID, err = cmd.Flags().GetString(flag.ClusterID) + if err != nil { + return errors.Trace(err) + } + displayName, err = cmd.Flags().GetString(flag.DisplayName) + if err != nil { + return errors.Trace(err) + } + endpointServiceName, err = cmd.Flags().GetString(flag.EndpointServiceName) + if err != nil { + return errors.Trace(err) + } + endpointServiceRegion, err = cmd.Flags().GetString(flag.EndpointServiceRegion) + if err != nil { + return errors.Trace(err) + } + connectionTypeRaw, err = cmd.Flags().GetString(flag.PrivateLinkConnectionType) + if err != nil { + return errors.Trace(err) + } + } + + displayName = strings.TrimSpace(displayName) + if displayName == "" { + return errors.New("display name is required") + } + endpointServiceName = strings.TrimSpace(endpointServiceName) + if endpointServiceName == "" { + return errors.New("endpoint service name is required") + } + + connectionType, err := normalizePrivateLinkConnectionType(connectionTypeRaw) + if err != nil { + return err + } + if endpointServiceRegion != "" && connectionType == pl.PRIVATELINKCONNECTIONTYPEENUM_ALICLOUD_ENDPOINT_SERVICE { + return errors.New("endpoint service region is only supported for AWS endpoint service") + } + + privateLinkConnection := pl.NewPrivateLinkConnection(clusterID, displayName, connectionType) + if connectionType == pl.PRIVATELINKCONNECTIONTYPEENUM_AWS_ENDPOINT_SERVICE { + awsService := pl.NewAwsEndpointService(endpointServiceName) + if strings.TrimSpace(endpointServiceRegion) != "" { + awsService.SetRegion(strings.TrimSpace(endpointServiceRegion)) + } + privateLinkConnection.SetAwsEndpointService(*awsService) + } else { + aliService := pl.NewAlicloudEndpointService(endpointServiceName) + privateLinkConnection.SetAlicloudEndpointService(*aliService) + } + + body := pl.NewPrivateLinkConnectionServiceCreatePrivateLinkConnectionBody(*privateLinkConnection) + _, err = d.CreatePrivateLinkConnection(ctx, clusterID, body) + if err != nil { + return errors.Trace(err) + } + + _, err = fmt.Fprintln(h.IOStreams.Out, color.GreenString("private link connection %s is created", displayName)) + if err != nil { + return err + } + return nil + }, + } + + createCmd.Flags().StringP(flag.ClusterID, flag.ClusterIDShort, "", "The ID of the cluster.") + createCmd.Flags().StringP(flag.DisplayName, flag.DisplayNameShort, "", "The display name of the private link connection.") + createCmd.Flags().StringP(flag.PrivateLinkConnectionType, "", "", "The type of the private link connection, one of [\"AWS_ENDPOINT_SERVICE\" \"ALICLOUD_ENDPOINT_SERVICE\"].") + createCmd.Flags().StringP(flag.EndpointServiceName, "", "", "The endpoint service name.") + createCmd.Flags().StringP(flag.EndpointServiceRegion, "", "", "The endpoint service region (AWS only).") + return createCmd +} + +func getCreateInputModel(includeRegion bool) (ui.TextInputModel, error) { + fieldCount := 2 + if includeRegion { + fieldCount = 3 + } + m := ui.TextInputModel{ + Inputs: make([]textinput.Model, fieldCount), + } + + for i := 0; i < fieldCount; i++ { + t := textinput.New() + t.Cursor.Style = config.CursorStyle + t.CharLimit = 64 + switch i { + case 0: + t.Placeholder = "Display Name" + t.Focus() + t.PromptStyle = config.FocusedStyle + t.TextStyle = config.FocusedStyle + case 1: + t.Placeholder = "Endpoint Service Name" + case 2: + t.Placeholder = "Endpoint Service Region (optional)" + } + m.Inputs[i] = t + } + + p := tea.NewProgram(m) + inputModel, err := p.Run() + if err != nil { + return ui.TextInputModel{}, errors.Trace(err) + } + if inputModel.(ui.TextInputModel).Interrupted { + return ui.TextInputModel{}, util.InterruptError + } + return inputModel.(ui.TextInputModel), nil +} + +func normalizePrivateLinkConnectionType(input string) (pl.PrivateLinkConnectionTypeEnum, error) { + value := strings.TrimSpace(strings.ToUpper(input)) + switch value { + case "AWS", string(pl.PRIVATELINKCONNECTIONTYPEENUM_AWS_ENDPOINT_SERVICE): + return pl.PRIVATELINKCONNECTIONTYPEENUM_AWS_ENDPOINT_SERVICE, nil + case "ALICLOUD", string(pl.PRIVATELINKCONNECTIONTYPEENUM_ALICLOUD_ENDPOINT_SERVICE): + return pl.PRIVATELINKCONNECTIONTYPEENUM_ALICLOUD_ENDPOINT_SERVICE, nil + default: + return "", fmt.Errorf("invalid private link connection type: %s", input) + } +} diff --git a/internal/cli/serverless/privatelink/delete.go b/internal/cli/serverless/privatelink/delete.go new file mode 100644 index 00000000..48302142 --- /dev/null +++ b/internal/cli/serverless/privatelink/delete.go @@ -0,0 +1,132 @@ +// Copyright 2026 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package privatelink + +import ( + "fmt" + + "github.com/fatih/color" + "github.com/juju/errors" + "github.com/spf13/cobra" + "github.com/tidbcloud/tidbcloud-cli/internal" + "github.com/tidbcloud/tidbcloud-cli/internal/config" + "github.com/tidbcloud/tidbcloud-cli/internal/flag" + "github.com/tidbcloud/tidbcloud-cli/internal/service/cloud" +) + +type DeleteOpts struct { + interactive bool +} + +func (c DeleteOpts) NonInteractiveFlags() []string { + return []string{ + flag.ClusterID, + flag.PrivateLinkConnectionID, + } +} + +func (c *DeleteOpts) MarkInteractive(cmd *cobra.Command) error { + flags := c.NonInteractiveFlags() + for _, fn := range flags { + f := cmd.Flags().Lookup(fn) + if f != nil && f.Changed { + c.interactive = false + break + } + } + if !c.interactive { + for _, fn := range flags { + if err := cmd.MarkFlagRequired(fn); err != nil { + return err + } + } + } + return nil +} + +func DeleteCmd(h *internal.Helper) *cobra.Command { + opts := DeleteOpts{ + interactive: true, + } + + var deleteCmd = &cobra.Command{ + Use: "delete", + Short: "Delete a private link connection", + Args: cobra.NoArgs, + Example: fmt.Sprintf(` Delete a private link connection in interactive mode: + $ %[1]s serverless private-link-connection delete + + Delete a private link connection in non-interactive mode: + $ %[1]s serverless private-link-connection delete -c --private-link-connection-id `, + config.CliName), + PreRunE: func(cmd *cobra.Command, args []string) error { + return opts.MarkInteractive(cmd) + }, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + d, err := h.Client() + if err != nil { + return err + } + + var clusterID, connectionID string + if opts.interactive { + if !h.IOStreams.CanPrompt { + return errors.New("The terminal doesn't support interactive mode, please use non-interactive mode") + } + + project, err := cloud.GetSelectedProject(ctx, h.QueryPageSize, d) + if err != nil { + return err + } + cluster, err := cloud.GetSelectedCluster(ctx, project.ID, h.QueryPageSize, d) + if err != nil { + return err + } + clusterID = cluster.ID + + connection, err := cloud.GetSelectedPrivateLinkConnection(ctx, clusterID, h.QueryPageSize, d) + if err != nil { + return err + } + connectionID = connection.ID + } else { + clusterID, err = cmd.Flags().GetString(flag.ClusterID) + if err != nil { + return errors.Trace(err) + } + connectionID, err = cmd.Flags().GetString(flag.PrivateLinkConnectionID) + if err != nil { + return errors.Trace(err) + } + } + + _, err = d.DeletePrivateLinkConnection(ctx, clusterID, connectionID) + if err != nil { + return errors.Trace(err) + } + + _, err = fmt.Fprintln(h.IOStreams.Out, color.GreenString("private link connection %s is deleted", connectionID)) + if err != nil { + return err + } + return nil + }, + } + + deleteCmd.Flags().StringP(flag.ClusterID, flag.ClusterIDShort, "", "The ID of the cluster.") + deleteCmd.Flags().StringP(flag.PrivateLinkConnectionID, "", "", "The private link connection ID.") + return deleteCmd +} diff --git a/internal/cli/serverless/privatelink/describe.go b/internal/cli/serverless/privatelink/describe.go new file mode 100644 index 00000000..879db5d9 --- /dev/null +++ b/internal/cli/serverless/privatelink/describe.go @@ -0,0 +1,130 @@ +// Copyright 2026 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package privatelink + +import ( + "fmt" + + "github.com/juju/errors" + "github.com/spf13/cobra" + "github.com/tidbcloud/tidbcloud-cli/internal" + "github.com/tidbcloud/tidbcloud-cli/internal/config" + "github.com/tidbcloud/tidbcloud-cli/internal/flag" + "github.com/tidbcloud/tidbcloud-cli/internal/output" + "github.com/tidbcloud/tidbcloud-cli/internal/service/cloud" +) + +type DescribeOpts struct { + interactive bool +} + +func (c DescribeOpts) NonInteractiveFlags() []string { + return []string{ + flag.ClusterID, + flag.PrivateLinkConnectionID, + } +} + +func (c *DescribeOpts) MarkInteractive(cmd *cobra.Command) error { + flags := c.NonInteractiveFlags() + for _, fn := range flags { + f := cmd.Flags().Lookup(fn) + if f != nil && f.Changed { + c.interactive = false + break + } + } + if !c.interactive { + for _, fn := range flags { + if err := cmd.MarkFlagRequired(fn); err != nil { + return err + } + } + } + return nil +} + +func DescribeCmd(h *internal.Helper) *cobra.Command { + opts := DescribeOpts{ + interactive: true, + } + + var describeCmd = &cobra.Command{ + Use: "describe", + Short: "Describe a private link connection", + Aliases: []string{"get"}, + Args: cobra.NoArgs, + Example: fmt.Sprintf(` Get a private link connection in interactive mode: + $ %[1]s serverless private-link-connection describe + + Get a private link connection in non-interactive mode: + $ %[1]s serverless private-link-connection describe -c --private-link-connection-id `, + config.CliName), + PreRunE: func(cmd *cobra.Command, args []string) error { + return opts.MarkInteractive(cmd) + }, + RunE: func(cmd *cobra.Command, args []string) error { + d, err := h.Client() + if err != nil { + return err + } + ctx := cmd.Context() + + var clusterID, connectionID string + if opts.interactive { + if !h.IOStreams.CanPrompt { + return errors.New("The terminal doesn't support interactive mode, please use non-interactive mode") + } + + project, err := cloud.GetSelectedProject(ctx, h.QueryPageSize, d) + if err != nil { + return err + } + cluster, err := cloud.GetSelectedCluster(ctx, project.ID, h.QueryPageSize, d) + if err != nil { + return err + } + clusterID = cluster.ID + + connection, err := cloud.GetSelectedPrivateLinkConnection(ctx, clusterID, h.QueryPageSize, d) + if err != nil { + return err + } + connectionID = connection.ID + } else { + clusterID, err = cmd.Flags().GetString(flag.ClusterID) + if err != nil { + return errors.Trace(err) + } + connectionID, err = cmd.Flags().GetString(flag.PrivateLinkConnectionID) + if err != nil { + return errors.Trace(err) + } + } + + connection, err := d.GetPrivateLinkConnection(ctx, clusterID, connectionID) + if err != nil { + return errors.Trace(err) + } + + err = output.PrintJson(h.IOStreams.Out, connection) + return errors.Trace(err) + }, + } + + describeCmd.Flags().StringP(flag.ClusterID, flag.ClusterIDShort, "", "The ID of the cluster.") + describeCmd.Flags().StringP(flag.PrivateLinkConnectionID, "", "", "The private link connection ID.") + return describeCmd +} diff --git a/internal/cli/serverless/privatelink/list.go b/internal/cli/serverless/privatelink/list.go new file mode 100644 index 00000000..0fac75f9 --- /dev/null +++ b/internal/cli/serverless/privatelink/list.go @@ -0,0 +1,238 @@ +// Copyright 2026 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package privatelink + +import ( + "fmt" + "strings" + "time" + + "github.com/tidbcloud/tidbcloud-cli/internal" + "github.com/tidbcloud/tidbcloud-cli/internal/config" + "github.com/tidbcloud/tidbcloud-cli/internal/flag" + "github.com/tidbcloud/tidbcloud-cli/internal/output" + "github.com/tidbcloud/tidbcloud-cli/internal/service/cloud" + pl "github.com/tidbcloud/tidbcloud-cli/pkg/tidbcloud/v1beta1/serverless/privatelink" + + "github.com/juju/errors" + "github.com/spf13/cobra" +) + +type ListOpts struct { + interactive bool +} + +func (c ListOpts) NonInteractiveFlags() []string { + return []string{ + flag.ClusterID, + flag.PrivateLinkConnectionState, + } +} + +func (c ListOpts) RequiredFlags() []string { + return []string{ + flag.ClusterID, + } +} + +func (c *ListOpts) MarkInteractive(cmd *cobra.Command) error { + flags := c.NonInteractiveFlags() + for _, fn := range flags { + f := cmd.Flags().Lookup(fn) + if f != nil && f.Changed { + c.interactive = false + break + } + } + if !c.interactive { + for _, fn := range c.RequiredFlags() { + if err := cmd.MarkFlagRequired(fn); err != nil { + return err + } + } + } + return nil +} + +func ListCmd(h *internal.Helper) *cobra.Command { + opts := ListOpts{ + interactive: true, + } + + var listCmd = &cobra.Command{ + Use: "list", + Short: "List private link connections", + Args: cobra.NoArgs, + Aliases: []string{"ls"}, + Example: fmt.Sprintf(` List private link connections in interactive mode: + $ %[1]s serverless private-link-connection list + + List private link connections in non-interactive mode: + $ %[1]s serverless private-link-connection list -c + + List private link connections with json format in non-interactive mode: + $ %[1]s serverless private-link-connection list -c -o json`, + config.CliName), + PreRunE: func(cmd *cobra.Command, args []string) error { + return opts.MarkInteractive(cmd) + }, + RunE: func(cmd *cobra.Command, args []string) error { + d, err := h.Client() + if err != nil { + return err + } + ctx := cmd.Context() + + var clusterID string + var stateFilter *pl.PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter + if opts.interactive { + if !h.IOStreams.CanPrompt { + return errors.New("The terminal doesn't support interactive mode, please use non-interactive mode") + } + project, err := cloud.GetSelectedProject(ctx, h.QueryPageSize, d) + if err != nil { + return err + } + cluster, err := cloud.GetSelectedCluster(ctx, project.ID, h.QueryPageSize, d) + if err != nil { + return err + } + clusterID = cluster.ID + } else { + clusterID, err = cmd.Flags().GetString(flag.ClusterID) + if err != nil { + return errors.Trace(err) + } + stateRaw, err := cmd.Flags().GetString(flag.PrivateLinkConnectionState) + if err != nil { + return errors.Trace(err) + } + if strings.TrimSpace(stateRaw) != "" { + parsedState, err := normalizePrivateLinkConnectionState(stateRaw) + if err != nil { + return err + } + stateFilter = &parsedState + } + } + + total, items, err := cloud.RetrievePrivateLinkConnections(ctx, clusterID, h.QueryPageSize, stateFilter, d) + if err != nil { + return err + } + + format, err := cmd.Flags().GetString(flag.Output) + if err != nil { + return errors.Trace(err) + } + + if format == output.JsonFormat || !h.IOStreams.CanPrompt { + res := &pl.ListPrivateLinkConnectionsResponse{ + PrivateLinkConnections: items, + TotalSize: &total, + } + err := output.PrintJson(h.IOStreams.Out, res) + if err != nil { + return errors.Trace(err) + } + return nil + } + if format != output.HumanFormat { + return fmt.Errorf("unsupported output format: %s", format) + } + + columns := []output.Column{ + "ID", + "DisplayName", + "Type", + "State", + "EndpointServiceName", + "EndpointServiceRegion", + "CreateTime", + } + + var rows []output.Row + for _, item := range items { + rows = append(rows, output.Row{ + valueOrEmpty(item.PrivateLinkConnectionId), + item.DisplayName, + string(item.Type), + privateLinkConnectionState(item.State), + endpointServiceName(item), + endpointServiceRegion(item), + privateLinkConnectionTime(item.CreateTime), + }) + } + + err = output.PrintHumanTable(h.IOStreams.Out, columns, rows) + if err != nil { + return errors.Trace(err) + } + return nil + }, + } + + listCmd.Flags().StringP(flag.ClusterID, flag.ClusterIDShort, "", "The ID of the cluster.") + listCmd.Flags().StringP(flag.PrivateLinkConnectionState, "", "", "Filter by private link connection state.") + listCmd.Flags().StringP(flag.Output, flag.OutputShort, output.HumanFormat, flag.OutputHelp) + return listCmd +} + +func normalizePrivateLinkConnectionState(input string) (pl.PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter, error) { + value := strings.TrimSpace(strings.ToUpper(input)) + state := pl.PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter(value) + if state.IsValid() { + return state, nil + } + return "", fmt.Errorf("invalid private link connection state: %s", input) +} + +func endpointServiceName(item pl.PrivateLinkConnection) string { + if item.AwsEndpointService != nil { + return item.AwsEndpointService.Name + } + if item.AlicloudEndpointService != nil { + return item.AlicloudEndpointService.Name + } + return "" +} + +func endpointServiceRegion(item pl.PrivateLinkConnection) string { + if item.AwsEndpointService != nil && item.AwsEndpointService.Region != nil { + return *item.AwsEndpointService.Region + } + return "" +} + +func privateLinkConnectionState(state *pl.PrivateLinkConnectionStateEnum) string { + if state == nil { + return "" + } + return string(*state) +} + +func privateLinkConnectionTime(t *time.Time) string { + if t == nil { + return "" + } + return t.Format(time.RFC3339) +} + +func valueOrEmpty(value *string) string { + if value == nil { + return "" + } + return *value +} diff --git a/internal/cli/serverless/privatelink/privatelink.go b/internal/cli/serverless/privatelink/privatelink.go new file mode 100644 index 00000000..74e733ec --- /dev/null +++ b/internal/cli/serverless/privatelink/privatelink.go @@ -0,0 +1,34 @@ +// Copyright 2026 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package privatelink + +import ( + "github.com/spf13/cobra" + "github.com/tidbcloud/tidbcloud-cli/internal" +) + +func PrivateLinkConnectionCmd(h *internal.Helper) *cobra.Command { + var privateLinkCmd = &cobra.Command{ + Use: "private-link-connection", + Short: "Manage TiDB Cloud Serverless private link connections", + } + + privateLinkCmd.AddCommand(CreateCmd(h)) + privateLinkCmd.AddCommand(DescribeCmd(h)) + privateLinkCmd.AddCommand(DeleteCmd(h)) + privateLinkCmd.AddCommand(ListCmd(h)) + privateLinkCmd.AddCommand(AvailabilityZonesCmd(h)) + return privateLinkCmd +} diff --git a/internal/flag/flag.go b/internal/flag/flag.go index 55397c9b..f6618042 100644 --- a/internal/flag/flag.go +++ b/internal/flag/flag.go @@ -109,16 +109,22 @@ const ( RotationIntervalMinutes string = "rotation-interval-minutes" RotationSizeMib string = "rotation-size-mib" - ChangefeedType string = "type" - ChangefeedKafka string = "kafka" - ChangefeedMySQL string = "mysql" - ChangefeedFilter string = "filter" - ChangefeedStartTSO string = "start-tso" - ChangefeedStartTime string = "start-time" - ChangefeedID string = "changefeed-id" - ChangefeedIDShort string = "f" - Explain string = "explain" - ChangefeedTemplateType string = "type" + ChangefeedType string = "type" + ChangefeedKafka string = "kafka" + ChangefeedMySQL string = "mysql" + ChangefeedFilter string = "filter" + ChangefeedStartTSO string = "start-tso" + ChangefeedStartTime string = "start-time" + ChangefeedID string = "changefeed-id" + ChangefeedIDShort string = "f" + Explain string = "explain" + ChangefeedTemplateType string = "type" + PrivateLinkServiceName string = "private-link-service-name" + PrivateLinkConnectionID string = "private-link-connection-id" + PrivateLinkConnectionType string = "type" + PrivateLinkConnectionState string = "state" + EndpointServiceName string = "endpoint-service-name" + EndpointServiceRegion string = "endpoint-service-region" MigrationID string = "migration-id" MigrationIDShort string = "m" diff --git a/internal/mock/api_client.go b/internal/mock/api_client.go index 61fcb2c0..60dfa126 100644 --- a/internal/mock/api_client.go +++ b/internal/mock/api_client.go @@ -22,6 +22,8 @@ import ( migration "github.com/tidbcloud/tidbcloud-cli/pkg/tidbcloud/v1beta1/serverless/migration" + privatelink "github.com/tidbcloud/tidbcloud-cli/pkg/tidbcloud/v1beta1/serverless/privatelink" + mock "github.com/stretchr/testify/mock" ) @@ -222,6 +224,246 @@ func (_m *TiDBCloudClient) CreateChangefeed(ctx context.Context, clusterId strin return r0, r1 } +// CreatePrivateLinkEndpoint provides a mock function with given fields: ctx, clusterId, body +func (_m *TiDBCloudClient) CreatePrivateLinkEndpoint(ctx context.Context, clusterId string, body *cdc.ChangefeedServiceCreatePrivateLinkEndpointBody) (*cdc.PrivateLinkEndpoint, error) { + ret := _m.Called(ctx, clusterId, body) + + if len(ret) == 0 { + panic("no return value specified for CreatePrivateLinkEndpoint") + } + + var r0 *cdc.PrivateLinkEndpoint + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, *cdc.ChangefeedServiceCreatePrivateLinkEndpointBody) (*cdc.PrivateLinkEndpoint, error)); ok { + return rf(ctx, clusterId, body) + } + if rf, ok := ret.Get(0).(func(context.Context, string, *cdc.ChangefeedServiceCreatePrivateLinkEndpointBody) *cdc.PrivateLinkEndpoint); ok { + r0 = rf(ctx, clusterId, body) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cdc.PrivateLinkEndpoint) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, *cdc.ChangefeedServiceCreatePrivateLinkEndpointBody) error); ok { + r1 = rf(ctx, clusterId, body) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeletePrivateLinkEndpoint provides a mock function with given fields: ctx, clusterId, privateLinkServiceName +func (_m *TiDBCloudClient) DeletePrivateLinkEndpoint(ctx context.Context, clusterId string, privateLinkServiceName string) (*cdc.PrivateLinkEndpoint, error) { + ret := _m.Called(ctx, clusterId, privateLinkServiceName) + + if len(ret) == 0 { + panic("no return value specified for DeletePrivateLinkEndpoint") + } + + var r0 *cdc.PrivateLinkEndpoint + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, string) (*cdc.PrivateLinkEndpoint, error)); ok { + return rf(ctx, clusterId, privateLinkServiceName) + } + if rf, ok := ret.Get(0).(func(context.Context, string, string) *cdc.PrivateLinkEndpoint); ok { + r0 = rf(ctx, clusterId, privateLinkServiceName) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cdc.PrivateLinkEndpoint) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok { + r1 = rf(ctx, clusterId, privateLinkServiceName) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetPrivateLinkEndpoint provides a mock function with given fields: ctx, clusterId, privateLinkServiceName +func (_m *TiDBCloudClient) GetPrivateLinkEndpoint(ctx context.Context, clusterId string, privateLinkServiceName string) (*cdc.PrivateLinkEndpoint, error) { + ret := _m.Called(ctx, clusterId, privateLinkServiceName) + + if len(ret) == 0 { + panic("no return value specified for GetPrivateLinkEndpoint") + } + + var r0 *cdc.PrivateLinkEndpoint + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, string) (*cdc.PrivateLinkEndpoint, error)); ok { + return rf(ctx, clusterId, privateLinkServiceName) + } + if rf, ok := ret.Get(0).(func(context.Context, string, string) *cdc.PrivateLinkEndpoint); ok { + r0 = rf(ctx, clusterId, privateLinkServiceName) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cdc.PrivateLinkEndpoint) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok { + r1 = rf(ctx, clusterId, privateLinkServiceName) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CreatePrivateLinkConnection provides a mock function with given fields: ctx, clusterId, body +func (_m *TiDBCloudClient) CreatePrivateLinkConnection(ctx context.Context, clusterId string, body *privatelink.PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) (*privatelink.PrivateLinkConnection, error) { + ret := _m.Called(ctx, clusterId, body) + + if len(ret) == 0 { + panic("no return value specified for CreatePrivateLinkConnection") + } + + var r0 *privatelink.PrivateLinkConnection + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, *privatelink.PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) (*privatelink.PrivateLinkConnection, error)); ok { + return rf(ctx, clusterId, body) + } + if rf, ok := ret.Get(0).(func(context.Context, string, *privatelink.PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) *privatelink.PrivateLinkConnection); ok { + r0 = rf(ctx, clusterId, body) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*privatelink.PrivateLinkConnection) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, *privatelink.PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) error); ok { + r1 = rf(ctx, clusterId, body) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeletePrivateLinkConnection provides a mock function with given fields: ctx, clusterId, privateLinkConnectionId +func (_m *TiDBCloudClient) DeletePrivateLinkConnection(ctx context.Context, clusterId string, privateLinkConnectionId string) (*privatelink.PrivateLinkConnection, error) { + ret := _m.Called(ctx, clusterId, privateLinkConnectionId) + + if len(ret) == 0 { + panic("no return value specified for DeletePrivateLinkConnection") + } + + var r0 *privatelink.PrivateLinkConnection + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, string) (*privatelink.PrivateLinkConnection, error)); ok { + return rf(ctx, clusterId, privateLinkConnectionId) + } + if rf, ok := ret.Get(0).(func(context.Context, string, string) *privatelink.PrivateLinkConnection); ok { + r0 = rf(ctx, clusterId, privateLinkConnectionId) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*privatelink.PrivateLinkConnection) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok { + r1 = rf(ctx, clusterId, privateLinkConnectionId) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetPrivateLinkConnection provides a mock function with given fields: ctx, clusterId, privateLinkConnectionId +func (_m *TiDBCloudClient) GetPrivateLinkConnection(ctx context.Context, clusterId string, privateLinkConnectionId string) (*privatelink.PrivateLinkConnection, error) { + ret := _m.Called(ctx, clusterId, privateLinkConnectionId) + + if len(ret) == 0 { + panic("no return value specified for GetPrivateLinkConnection") + } + + var r0 *privatelink.PrivateLinkConnection + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, string) (*privatelink.PrivateLinkConnection, error)); ok { + return rf(ctx, clusterId, privateLinkConnectionId) + } + if rf, ok := ret.Get(0).(func(context.Context, string, string) *privatelink.PrivateLinkConnection); ok { + r0 = rf(ctx, clusterId, privateLinkConnectionId) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*privatelink.PrivateLinkConnection) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok { + r1 = rf(ctx, clusterId, privateLinkConnectionId) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetPrivateLinkConnectionAvailabilityZones provides a mock function with given fields: ctx, clusterId +func (_m *TiDBCloudClient) GetPrivateLinkConnectionAvailabilityZones(ctx context.Context, clusterId string) (*privatelink.GetAvailabilityZonesResponse, error) { + ret := _m.Called(ctx, clusterId) + + if len(ret) == 0 { + panic("no return value specified for GetPrivateLinkConnectionAvailabilityZones") + } + + var r0 *privatelink.GetAvailabilityZonesResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) (*privatelink.GetAvailabilityZonesResponse, error)); ok { + return rf(ctx, clusterId) + } + if rf, ok := ret.Get(0).(func(context.Context, string) *privatelink.GetAvailabilityZonesResponse); ok { + r0 = rf(ctx, clusterId) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*privatelink.GetAvailabilityZonesResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, clusterId) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ListPrivateLinkConnections provides a mock function with given fields: ctx, clusterId, pageSize, pageToken, state +func (_m *TiDBCloudClient) ListPrivateLinkConnections(ctx context.Context, clusterId string, pageSize *int32, pageToken *string, state *privatelink.PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter) (*privatelink.ListPrivateLinkConnectionsResponse, error) { + ret := _m.Called(ctx, clusterId, pageSize, pageToken, state) + + if len(ret) == 0 { + panic("no return value specified for ListPrivateLinkConnections") + } + + var r0 *privatelink.ListPrivateLinkConnectionsResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, *int32, *string, *privatelink.PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter) (*privatelink.ListPrivateLinkConnectionsResponse, error)); ok { + return rf(ctx, clusterId, pageSize, pageToken, state) + } + if rf, ok := ret.Get(0).(func(context.Context, string, *int32, *string, *privatelink.PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter) *privatelink.ListPrivateLinkConnectionsResponse); ok { + r0 = rf(ctx, clusterId, pageSize, pageToken, state) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*privatelink.ListPrivateLinkConnectionsResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, *int32, *string, *privatelink.PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter) error); ok { + r1 = rf(ctx, clusterId, pageSize, pageToken, state) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // CreateCluster provides a mock function with given fields: ctx, body func (_m *TiDBCloudClient) CreateCluster(ctx context.Context, body *cluster.TidbCloudOpenApiserverlessv1beta1Cluster) (*cluster.TidbCloudOpenApiserverlessv1beta1Cluster, error) { ret := _m.Called(ctx, body) diff --git a/internal/service/cloud/api_client.go b/internal/service/cloud/api_client.go index a09b7206..0c78e465 100644 --- a/internal/service/cloud/api_client.go +++ b/internal/service/cloud/api_client.go @@ -35,6 +35,7 @@ import ( "github.com/tidbcloud/tidbcloud-cli/pkg/tidbcloud/v1beta1/serverless/export" "github.com/tidbcloud/tidbcloud-cli/pkg/tidbcloud/v1beta1/serverless/imp" "github.com/tidbcloud/tidbcloud-cli/pkg/tidbcloud/v1beta1/serverless/migration" + "github.com/tidbcloud/tidbcloud-cli/pkg/tidbcloud/v1beta1/serverless/privatelink" "github.com/icholy/digest" ) @@ -147,6 +148,15 @@ type TiDBCloudClient interface { StopChangefeed(ctx context.Context, clusterId, changefeedId string) (*cdc.Changefeed, error) TestChangefeed(ctx context.Context, clusterId string, body *cdc.ChangefeedServiceTestChangefeedBody) (map[string]interface{}, error) DescribeSchemaTable(ctx context.Context, clusterId string, body *cdc.ChangefeedServiceDescribeSchemaTableBody) (*cdc.DescribeSchemaTableResp, error) + CreatePrivateLinkEndpoint(ctx context.Context, clusterId string, body *cdc.ChangefeedServiceCreatePrivateLinkEndpointBody) (*cdc.PrivateLinkEndpoint, error) + GetPrivateLinkEndpoint(ctx context.Context, clusterId, privateLinkServiceName string) (*cdc.PrivateLinkEndpoint, error) + DeletePrivateLinkEndpoint(ctx context.Context, clusterId, privateLinkServiceName string) (*cdc.PrivateLinkEndpoint, error) + + CreatePrivateLinkConnection(ctx context.Context, clusterId string, body *privatelink.PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) (*privatelink.PrivateLinkConnection, error) + GetPrivateLinkConnection(ctx context.Context, clusterId, privateLinkConnectionId string) (*privatelink.PrivateLinkConnection, error) + DeletePrivateLinkConnection(ctx context.Context, clusterId, privateLinkConnectionId string) (*privatelink.PrivateLinkConnection, error) + ListPrivateLinkConnections(ctx context.Context, clusterId string, pageSize *int32, pageToken *string, state *privatelink.PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter) (*privatelink.ListPrivateLinkConnectionsResponse, error) + GetPrivateLinkConnectionAvailabilityZones(ctx context.Context, clusterId string) (*privatelink.GetAvailabilityZonesResponse, error) CreateAuditLogFilterRule(ctx context.Context, clusterID string, body *auditlog.DatabaseAuditLogServiceCreateAuditLogFilterRuleBody) (*auditlog.AuditLogFilterRule, error) @@ -173,11 +183,12 @@ type ClientDelegate struct { alc *auditlog.APIClient cdc *cdc.APIClient mc *migration.APIClient + plc *privatelink.APIClient } func NewClientDelegateWithToken(token string, serverlessEndpoint string, iamEndpoint string) (*ClientDelegate, error) { transport := NewBearTokenTransport(token) - bc, sc, brc, sic, ec, ic, alc, cdc, mc, err := NewApiClient(transport, serverlessEndpoint, iamEndpoint) + bc, sc, brc, sic, ec, ic, alc, cdc, mc, plc, err := NewApiClient(transport, serverlessEndpoint, iamEndpoint) if err != nil { return nil, err } @@ -191,12 +202,13 @@ func NewClientDelegateWithToken(token string, serverlessEndpoint string, iamEndp alc: alc, cdc: cdc, mc: mc, + plc: plc, }, nil } func NewClientDelegateWithApiKey(publicKey string, privateKey string, serverlessEndpoint string, iamEndpoint string) (*ClientDelegate, error) { transport := NewDigestTransport(publicKey, privateKey) - bc, sc, brc, sic, ec, ic, alc, cdc, mc, err := NewApiClient(transport, serverlessEndpoint, iamEndpoint) + bc, sc, brc, sic, ec, ic, alc, cdc, mc, plc, err := NewApiClient(transport, serverlessEndpoint, iamEndpoint) if err != nil { return nil, err } @@ -210,6 +222,7 @@ func NewClientDelegateWithApiKey(publicKey string, privateKey string, serverless alc: alc, cdc: cdc, mc: mc, + plc: plc, }, nil } @@ -668,7 +681,7 @@ func (d *ClientDelegate) GetAuditLogConfig(ctx context.Context, clusterID string return res, parseError(err, h) } -func NewApiClient(rt http.RoundTripper, serverlessEndpoint string, iamEndpoint string) (*branch.APIClient, *cluster.APIClient, *br.APIClient, *imp.APIClient, *export.APIClient, *iam.APIClient, *auditlog.APIClient, *cdc.APIClient, *migration.APIClient, error) { +func NewApiClient(rt http.RoundTripper, serverlessEndpoint string, iamEndpoint string) (*branch.APIClient, *cluster.APIClient, *br.APIClient, *imp.APIClient, *export.APIClient, *iam.APIClient, *auditlog.APIClient, *cdc.APIClient, *migration.APIClient, *privatelink.APIClient, error) { httpclient := &http.Client{ Transport: rt, } @@ -676,12 +689,12 @@ func NewApiClient(rt http.RoundTripper, serverlessEndpoint string, iamEndpoint s // v1beta1 api (serverless) serverlessURL, err := prop.ValidateApiUrl(serverlessEndpoint) if err != nil { - return nil, nil, nil, nil, nil, nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, err } iamURL, err := prop.ValidateApiUrl(iamEndpoint) if err != nil { - return nil, nil, nil, nil, nil, nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, err } userAgent := fmt.Sprintf("%s/%s", config.CliName, version.Version) @@ -731,11 +744,16 @@ func NewApiClient(rt http.RoundTripper, serverlessEndpoint string, iamEndpoint s migrationCfg.Host = serverlessURL.Host migrationCfg.UserAgent = userAgent + privateLinkCfg := privatelink.NewConfiguration() + privateLinkCfg.HTTPClient = httpclient + privateLinkCfg.Host = serverlessURL.Host + privateLinkCfg.UserAgent = userAgent + return branch.NewAPIClient(branchCfg), cluster.NewAPIClient(clusterCfg), br.NewAPIClient(backupRestoreCfg), imp.NewAPIClient(importCfg), export.NewAPIClient(exportCfg), iam.NewAPIClient(iamCfg), auditlog.NewAPIClient(auditLogCfg), cdc.NewAPIClient(cdcCfg), - migration.NewAPIClient(migrationCfg), nil + migration.NewAPIClient(migrationCfg), privatelink.NewAPIClient(privateLinkCfg), nil } func NewDigestTransport(publicKey, privateKey string) http.RoundTripper { @@ -903,3 +921,68 @@ func (d *ClientDelegate) DescribeSchemaTable(ctx context.Context, clusterId stri resp, h, err := r.Execute() return resp, parseError(err, h) } + +func (d *ClientDelegate) CreatePrivateLinkEndpoint(ctx context.Context, clusterId string, body *cdc.ChangefeedServiceCreatePrivateLinkEndpointBody) (*cdc.PrivateLinkEndpoint, error) { + r := d.cdc.ChangefeedServiceAPI.ChangefeedServiceCreatePrivateLinkEndpoint(ctx, clusterId) + if body != nil { + r = r.Body(*body) + } + resp, h, err := r.Execute() + return resp, parseError(err, h) +} + +func (d *ClientDelegate) GetPrivateLinkEndpoint(ctx context.Context, clusterId, privateLinkServiceName string) (*cdc.PrivateLinkEndpoint, error) { + r := d.cdc.ChangefeedServiceAPI.ChangefeedServiceGetPrivateLinkEndpoint(ctx, clusterId) + r = r.PrivateLinkServiceName(privateLinkServiceName) + resp, h, err := r.Execute() + return resp, parseError(err, h) +} + +func (d *ClientDelegate) DeletePrivateLinkEndpoint(ctx context.Context, clusterId, privateLinkServiceName string) (*cdc.PrivateLinkEndpoint, error) { + r := d.cdc.ChangefeedServiceAPI.ChangefeedServiceDeletePrivateLinkEndpoint(ctx, clusterId) + r = r.PrivateLinkServiceName(privateLinkServiceName) + resp, h, err := r.Execute() + return resp, parseError(err, h) +} + +func (d *ClientDelegate) CreatePrivateLinkConnection(ctx context.Context, clusterId string, body *privatelink.PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) (*privatelink.PrivateLinkConnection, error) { + r := d.plc.PrivateLinkConnectionServiceAPI.PrivateLinkConnectionServiceCreatePrivateLinkConnection(ctx, clusterId) + if body != nil { + r = r.Body(*body) + } + resp, h, err := r.Execute() + return resp, parseError(err, h) +} + +func (d *ClientDelegate) GetPrivateLinkConnection(ctx context.Context, clusterId, privateLinkConnectionId string) (*privatelink.PrivateLinkConnection, error) { + r := d.plc.PrivateLinkConnectionServiceAPI.PrivateLinkConnectionServiceGetPrivateLinkConnection(ctx, clusterId, privateLinkConnectionId) + resp, h, err := r.Execute() + return resp, parseError(err, h) +} + +func (d *ClientDelegate) DeletePrivateLinkConnection(ctx context.Context, clusterId, privateLinkConnectionId string) (*privatelink.PrivateLinkConnection, error) { + r := d.plc.PrivateLinkConnectionServiceAPI.PrivateLinkConnectionServiceDeletePrivateLinkConnection(ctx, clusterId, privateLinkConnectionId) + resp, h, err := r.Execute() + return resp, parseError(err, h) +} + +func (d *ClientDelegate) ListPrivateLinkConnections(ctx context.Context, clusterId string, pageSize *int32, pageToken *string, state *privatelink.PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter) (*privatelink.ListPrivateLinkConnectionsResponse, error) { + r := d.plc.PrivateLinkConnectionServiceAPI.PrivateLinkConnectionServiceListPrivateLinkConnections(ctx, clusterId) + if pageSize != nil { + r = r.PageSize(*pageSize) + } + if pageToken != nil { + r = r.PageToken(*pageToken) + } + if state != nil { + r = r.State(*state) + } + resp, h, err := r.Execute() + return resp, parseError(err, h) +} + +func (d *ClientDelegate) GetPrivateLinkConnectionAvailabilityZones(ctx context.Context, clusterId string) (*privatelink.GetAvailabilityZonesResponse, error) { + r := d.plc.PrivateLinkConnectionServiceAPI.PrivateLinkConnectionServiceGetAvailabilityZones(ctx, clusterId) + resp, h, err := r.Execute() + return resp, parseError(err, h) +} diff --git a/internal/service/cloud/logic.go b/internal/service/cloud/logic.go index b04c3d8a..70d7afe4 100644 --- a/internal/service/cloud/logic.go +++ b/internal/service/cloud/logic.go @@ -31,6 +31,7 @@ import ( "github.com/tidbcloud/tidbcloud-cli/pkg/tidbcloud/v1beta1/serverless/export" "github.com/tidbcloud/tidbcloud-cli/pkg/tidbcloud/v1beta1/serverless/imp" "github.com/tidbcloud/tidbcloud-cli/pkg/tidbcloud/v1beta1/serverless/migration" + "github.com/tidbcloud/tidbcloud-cli/pkg/tidbcloud/v1beta1/serverless/privatelink" tea "github.com/charmbracelet/bubbletea" "github.com/juju/errors" @@ -1064,6 +1065,75 @@ func GetSelectedChangefeed(ctx context.Context, clusterID string, pageSize int64 return changefeed.(*Changefeed), nil } +func RetrievePrivateLinkConnections(ctx context.Context, clusterID string, pageSize int64, state *privatelink.PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter, d TiDBCloudClient) (int64, []privatelink.PrivateLinkConnection, error) { + var items []privatelink.PrivateLinkConnection + pageSizeInt32 := int32(pageSize) + resp, err := d.ListPrivateLinkConnections(ctx, clusterID, &pageSizeInt32, nil, state) + if err != nil { + return 0, nil, errors.Trace(err) + } + items = append(items, resp.PrivateLinkConnections...) + total := resp.TotalSize + for resp.NextPageToken != nil && *resp.NextPageToken != "" { + resp, err = d.ListPrivateLinkConnections(ctx, clusterID, &pageSizeInt32, resp.NextPageToken, state) + if err != nil { + return 0, nil, errors.Trace(err) + } + items = append(items, resp.PrivateLinkConnections...) + } + if total != nil { + return *total, items, nil + } + return int64(len(items)), items, nil +} + +func GetSelectedPrivateLinkConnection(ctx context.Context, clusterID string, pageSize int64, client TiDBCloudClient) (*PrivateLinkConnection, error) { + _, connections, err := RetrievePrivateLinkConnections(ctx, clusterID, pageSize, nil, client) + if err != nil { + return nil, err + } + + var items = make([]interface{}, 0, len(connections)) + for _, item := range connections { + if item.PrivateLinkConnectionId == nil || *item.PrivateLinkConnectionId == "" { + continue + } + displayName := item.DisplayName + if displayName == "" { + displayName = *item.PrivateLinkConnectionId + } + items = append(items, &PrivateLinkConnection{ + ID: *item.PrivateLinkConnectionId, + DisplayName: displayName, + }) + } + if len(items) == 0 { + return nil, fmt.Errorf("no available private link connections found") + } + + model, err := ui.InitialSelectModel(items, "Choose the private link connection:") + if err != nil { + return nil, errors.Trace(err) + } + itemsPerPage := 6 + model.EnablePagination(itemsPerPage) + model.EnableFilter() + + p := tea.NewProgram(model) + connectionModel, err := p.Run() + if err != nil { + return nil, errors.Trace(err) + } + if m, _ := connectionModel.(ui.SelectModel); m.Interrupted { + return nil, util.InterruptError + } + selected := connectionModel.(ui.SelectModel).GetSelectedItem() + if selected == nil { + return nil, errors.New("no private link connection selected") + } + return selected.(*PrivateLinkConnection), nil +} + func GetSelectedMigration(ctx context.Context, clusterID string, pageSize int64, client TiDBCloudClient) (*MigrationTask, error) { var items = make([]interface{}, 0) pageSizeInt32 := int32(pageSize) diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink.swagger.json b/pkg/tidbcloud/v1beta1/serverless/privatelink.swagger.json new file mode 100644 index 00000000..1746e625 --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink.swagger.json @@ -0,0 +1,429 @@ +{ + "swagger": "2.0", + "info": { + "title": "TiDB Cloud Serverless Private Link Connection Open API", + "description": "TiDB Cloud Serverless Private Link Connection Open API", + "version": "v1beta1" + }, + "tags": [ + { + "name": "PrivateLinkConnectionService" + } + ], + "host": "serverless.tidbapi.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": { + "/v1beta1/clusters/{clusterId}/privateLinkConnections/{privateLinkConnectionId}": { + "get": { + "summary": "Get a private link connection.", + "operationId": "PrivateLinkConnectionService_GetPrivateLinkConnection", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/PrivateLinkConnection" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Status" + } + } + }, + "parameters": [ + { + "name": "clusterId", + "description": "The cluster ID.", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "privateLinkConnectionId", + "description": "The private link connection ID.", + "in": "path", + "required": true, + "type": "string" + } + ], + "tags": [ + "PrivateLinkConnectionService" + ] + }, + "delete": { + "summary": "Delete a private link connection.", + "operationId": "PrivateLinkConnectionService_DeletePrivateLinkConnection", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/PrivateLinkConnection" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Status" + } + } + }, + "parameters": [ + { + "name": "clusterId", + "description": "The cluster ID.", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "privateLinkConnectionId", + "description": "The private link connection ID.", + "in": "path", + "required": true, + "type": "string" + } + ], + "tags": [ + "PrivateLinkConnectionService" + ] + } + }, + "/v1beta1/clusters/{clusterId}/privateLinkConnections": { + "get": { + "summary": "List private link connections.", + "operationId": "PrivateLinkConnectionService_ListPrivateLinkConnections", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/ListPrivateLinkConnectionsResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Status" + } + } + }, + "parameters": [ + { + "name": "clusterId", + "description": "The cluster ID.", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "pageSize", + "description": "The maximum number to return.", + "in": "query", + "required": false, + "type": "integer", + "format": "int32" + }, + { + "name": "pageToken", + "description": "The page token for pagination.", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "state", + "description": " - CREATING: The private link connection is being created.\n - ACTIVE: The private link connection is active.\n - FAILED: The private link connection is in failed state.\n - PENDING_ACCEPTANCE: The private link connection is pending acceptance. only for AWS endpoint service and Alicloud endpoint service.\n - DELETING: The private link connection is being deleted.", + "in": "query", + "required": false, + "type": "string", + "enum": [ + "CREATING", + "ACTIVE", + "FAILED", + "PENDING_ACCEPTANCE", + "DELETING" + ] + } + ], + "tags": [ + "PrivateLinkConnectionService" + ] + }, + "post": { + "summary": "Create a private link connection.", + "operationId": "PrivateLinkConnectionService_CreatePrivateLinkConnection", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/PrivateLinkConnection" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Status" + } + } + }, + "parameters": [ + { + "name": "clusterId", + "description": "The cluster ID.", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/PrivateLinkConnectionService.CreatePrivateLinkConnectionBody" + } + } + ], + "tags": [ + "PrivateLinkConnectionService" + ] + } + }, + "/v1beta1/clusters/{clusterId}/privateLinkConnections:getAvailabilityZones": { + "get": { + "summary": "Get account and availability zones information for private link connection.", + "operationId": "PrivateLinkConnectionService_GetAvailabilityZones", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/GetAvailabilityZonesResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Status" + } + } + }, + "parameters": [ + { + "name": "clusterId", + "description": "The cluster ID.", + "in": "path", + "required": true, + "type": "string" + } + ], + "tags": [ + "PrivateLinkConnectionService" + ] + } + } + }, + "definitions": { + "AlicloudEndpointService": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The endpoint service name." + } + }, + "required": [ + "name" + ] + }, + "Any": { + "type": "object", + "properties": { + "@type": { + "type": "string" + } + }, + "additionalProperties": {} + }, + "AwsEndpointService": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The endpoint service name." + }, + "region": { + "type": "string", + "title": "The region of endpoint service name, default to cluster's region" + } + }, + "required": [ + "name" + ] + }, + "GetAvailabilityZonesResponse": { + "type": "object", + "properties": { + "accountId": { + "type": "string", + "description": "The account ID." + }, + "azIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Availability zone ids." + } + } + }, + "ListPrivateLinkConnectionsResponse": { + "type": "object", + "properties": { + "privateLinkConnections": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/PrivateLinkConnection" + } + }, + "nextPageToken": { + "type": "string" + }, + "totalSize": { + "type": "integer", + "format": "int64" + } + } + }, + "PrivateLinkConnection": { + "type": "object", + "properties": { + "privateLinkConnectionId": { + "type": "string", + "title": "The private link connection ID, format: plc-xxx", + "readOnly": true + }, + "clusterId": { + "type": "string", + "description": "The ID of the cluster." + }, + "displayName": { + "type": "string", + "description": "Display name for the private link connection." + }, + "state": { + "description": "The state of the private link connection.", + "readOnly": true, + "allOf": [ + { + "$ref": "#/definitions/PrivateLinkConnectionState.Enum" + } + ] + }, + "message": { + "type": "string", + "description": "The message describing fail reason.", + "readOnly": true + }, + "createdBy": { + "type": "string", + "description": "The user who created the private link connection.", + "readOnly": true + }, + "createTime": { + "type": "string", + "format": "date-time", + "description": "Timestamp when the private link connection was created.", + "readOnly": true + }, + "updateTime": { + "type": "string", + "format": "date-time", + "x-nullable": true, + "description": "Timestamp when the private link connection was updated.", + "readOnly": true + }, + "type": { + "title": "The type of the private link connection", + "allOf": [ + { + "$ref": "#/definitions/PrivateLinkConnectionType.Enum" + } + ] + }, + "awsEndpointService": { + "$ref": "#/definitions/AwsEndpointService" + }, + "alicloudEndpointService": { + "$ref": "#/definitions/AlicloudEndpointService" + } + }, + "required": [ + "clusterId", + "displayName", + "type" + ] + }, + "PrivateLinkConnectionService.CreatePrivateLinkConnectionBody": { + "type": "object", + "properties": { + "privateLinkConnection": { + "description": "The private link connection to create.", + "allOf": [ + { + "$ref": "#/definitions/PrivateLinkConnection" + } + ] + } + }, + "required": [ + "privateLinkConnection" + ] + }, + "PrivateLinkConnectionState.Enum": { + "type": "string", + "enum": [ + "CREATING", + "ACTIVE", + "FAILED", + "PENDING_ACCEPTANCE", + "DELETING" + ], + "description": " - CREATING: The private link connection is being created.\n - ACTIVE: The private link connection is active.\n - FAILED: The private link connection is in failed state.\n - PENDING_ACCEPTANCE: The private link connection is pending acceptance. only for AWS endpoint service and Alicloud endpoint service.\n - DELETING: The private link connection is being deleted." + }, + "PrivateLinkConnectionType.Enum": { + "type": "string", + "enum": [ + "AWS_ENDPOINT_SERVICE", + "ALICLOUD_ENDPOINT_SERVICE" + ], + "description": " - AWS_ENDPOINT_SERVICE: AWS endpoint service type.\n - ALICLOUD_ENDPOINT_SERVICE: Alicloud endpoint service type." + }, + "Status": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + }, + "details": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/Any" + } + } + } + } + } +} diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/.gitignore b/pkg/tidbcloud/v1beta1/serverless/privatelink/.gitignore new file mode 100644 index 00000000..daf913b1 --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/.openapi-generator-ignore b/pkg/tidbcloud/v1beta1/serverless/privatelink/.openapi-generator-ignore new file mode 100644 index 00000000..7484ee59 --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/.openapi-generator/FILES b/pkg/tidbcloud/v1beta1/serverless/privatelink/.openapi-generator/FILES new file mode 100644 index 00000000..5ed50fe8 --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/.openapi-generator/FILES @@ -0,0 +1,22 @@ +.gitignore +.openapi-generator-ignore +.travis.yml +README.md +api/openapi.yaml +api_private_link_connection_service.go +client.go +configuration.go +git_push.sh +model_alicloud_endpoint_service.go +model_any.go +model_aws_endpoint_service.go +model_get_availability_zones_response.go +model_list_private_link_connections_response.go +model_private_link_connection.go +model_private_link_connection_service_create_private_link_connection_body.go +model_private_link_connection_service_list_private_link_connections_state_parameter.go +model_private_link_connection_state_enum.go +model_private_link_connection_type_enum.go +model_status.go +response.go +utils.go diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/.openapi-generator/VERSION b/pkg/tidbcloud/v1beta1/serverless/privatelink/.openapi-generator/VERSION new file mode 100644 index 00000000..5f84a81d --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/.openapi-generator/VERSION @@ -0,0 +1 @@ +7.12.0 diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/.travis.yml b/pkg/tidbcloud/v1beta1/serverless/privatelink/.travis.yml new file mode 100644 index 00000000..f5cb2ce9 --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/.travis.yml @@ -0,0 +1,8 @@ +language: go + +install: + - go get -d -v . + +script: + - go build -v ./ + diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/README.md b/pkg/tidbcloud/v1beta1/serverless/privatelink/README.md new file mode 100644 index 00000000..3ca389ac --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/README.md @@ -0,0 +1,127 @@ +# Go API client for privatelink + +TiDB Cloud Serverless Private Link Connection Open API + +## Overview +This API client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. By using the [OpenAPI-spec](https://www.openapis.org/) from a remote server, you can easily generate an API client. + +- API version: v1beta1 +- Package version: 1.0.0 +- Generator version: 7.12.0 +- Build package: org.openapitools.codegen.languages.GoClientCodegen + +## Installation + +Install the following dependencies: + +```sh +go get github.com/stretchr/testify/assert +go get golang.org/x/net/context +``` + +Put the package under your project folder and add the following in import: + +```go +import privatelink "github.com/GIT_USER_ID/GIT_REPO_ID" +``` + +To use a proxy, set the environment variable `HTTP_PROXY`: + +```go +os.Setenv("HTTP_PROXY", "http://proxy_name:proxy_port") +``` + +## Configuration of Server URL + +Default configuration comes with `Servers` field that contains server objects as defined in the OpenAPI specification. + +### Select Server Configuration + +For using other server than the one defined on index 0 set context value `privatelink.ContextServerIndex` of type `int`. + +```go +ctx := context.WithValue(context.Background(), privatelink.ContextServerIndex, 1) +``` + +### Templated Server URL + +Templated server URL is formatted using default variables from configuration or from context value `privatelink.ContextServerVariables` of type `map[string]string`. + +```go +ctx := context.WithValue(context.Background(), privatelink.ContextServerVariables, map[string]string{ + "basePath": "v2", +}) +``` + +Note, enum values are always validated and all unused variables are silently ignored. + +### URLs Configuration per Operation + +Each operation can use different server URL defined using `OperationServers` map in the `Configuration`. +An operation is uniquely identified by `"{classname}Service.{nickname}"` string. +Similar rules for overriding default operation server index and variables applies by using `privatelink.ContextOperationServerIndices` and `privatelink.ContextOperationServerVariables` context maps. + +```go +ctx := context.WithValue(context.Background(), privatelink.ContextOperationServerIndices, map[string]int{ + "{classname}Service.{nickname}": 2, +}) +ctx = context.WithValue(context.Background(), privatelink.ContextOperationServerVariables, map[string]map[string]string{ + "{classname}Service.{nickname}": { + "port": "8443", + }, +}) +``` + +## Documentation for API Endpoints + +All URIs are relative to *https://serverless.tidbapi.com* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +*PrivateLinkConnectionServiceAPI* | [**PrivateLinkConnectionServiceCreatePrivateLinkConnection**](docs/PrivateLinkConnectionServiceAPI.md#privatelinkconnectionservicecreateprivatelinkconnection) | **Post** /v1beta1/clusters/{clusterId}/privateLinkConnections | Create a private link connection. +*PrivateLinkConnectionServiceAPI* | [**PrivateLinkConnectionServiceDeletePrivateLinkConnection**](docs/PrivateLinkConnectionServiceAPI.md#privatelinkconnectionservicedeleteprivatelinkconnection) | **Delete** /v1beta1/clusters/{clusterId}/privateLinkConnections/{privateLinkConnectionId} | Delete a private link connection. +*PrivateLinkConnectionServiceAPI* | [**PrivateLinkConnectionServiceGetAvailabilityZones**](docs/PrivateLinkConnectionServiceAPI.md#privatelinkconnectionservicegetavailabilityzones) | **Get** /v1beta1/clusters/{clusterId}/privateLinkConnections:getAvailabilityZones | Get account and availability zones information for private link connection. +*PrivateLinkConnectionServiceAPI* | [**PrivateLinkConnectionServiceGetPrivateLinkConnection**](docs/PrivateLinkConnectionServiceAPI.md#privatelinkconnectionservicegetprivatelinkconnection) | **Get** /v1beta1/clusters/{clusterId}/privateLinkConnections/{privateLinkConnectionId} | Get a private link connection. +*PrivateLinkConnectionServiceAPI* | [**PrivateLinkConnectionServiceListPrivateLinkConnections**](docs/PrivateLinkConnectionServiceAPI.md#privatelinkconnectionservicelistprivatelinkconnections) | **Get** /v1beta1/clusters/{clusterId}/privateLinkConnections | List private link connections. + + +## Documentation For Models + + - [AlicloudEndpointService](docs/AlicloudEndpointService.md) + - [Any](docs/Any.md) + - [AwsEndpointService](docs/AwsEndpointService.md) + - [GetAvailabilityZonesResponse](docs/GetAvailabilityZonesResponse.md) + - [ListPrivateLinkConnectionsResponse](docs/ListPrivateLinkConnectionsResponse.md) + - [PrivateLinkConnection](docs/PrivateLinkConnection.md) + - [PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody](docs/PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody.md) + - [PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter](docs/PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter.md) + - [PrivateLinkConnectionStateEnum](docs/PrivateLinkConnectionStateEnum.md) + - [PrivateLinkConnectionTypeEnum](docs/PrivateLinkConnectionTypeEnum.md) + - [Status](docs/Status.md) + + +## Documentation For Authorization + +Endpoints do not require authorization. + + +## Documentation for Utility Methods + +Due to the fact that model structure members are all pointers, this package contains +a number of utility functions to easily obtain pointers to values of basic types. +Each of these functions takes a value of the given basic type and returns a pointer to it: + +* `PtrBool` +* `PtrInt` +* `PtrInt32` +* `PtrInt64` +* `PtrFloat` +* `PtrFloat32` +* `PtrFloat64` +* `PtrString` +* `PtrTime` + +## Author + + + diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/api/openapi.yaml b/pkg/tidbcloud/v1beta1/serverless/privatelink/api/openapi.yaml new file mode 100644 index 00000000..63e5471a --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/api/openapi.yaml @@ -0,0 +1,397 @@ +openapi: 3.0.1 +info: + description: TiDB Cloud Serverless Private Link Connection Open API + title: TiDB Cloud Serverless Private Link Connection Open API + version: v1beta1 +servers: +- url: https://serverless.tidbapi.com/ +tags: +- name: PrivateLinkConnectionService +paths: + /v1beta1/clusters/{clusterId}/privateLinkConnections/{privateLinkConnectionId}: + delete: + operationId: PrivateLinkConnectionService_DeletePrivateLinkConnection + parameters: + - description: The cluster ID. + in: path + name: clusterId + required: true + schema: + type: string + - description: The private link connection ID. + in: path + name: privateLinkConnectionId + required: true + schema: + type: string + responses: + "200": + content: + application/json: + schema: + $ref: '#/components/schemas/PrivateLinkConnection' + description: A successful response. + default: + content: + application/json: + schema: + $ref: '#/components/schemas/Status' + description: An unexpected error response. + summary: Delete a private link connection. + tags: + - PrivateLinkConnectionService + get: + operationId: PrivateLinkConnectionService_GetPrivateLinkConnection + parameters: + - description: The cluster ID. + in: path + name: clusterId + required: true + schema: + type: string + - description: The private link connection ID. + in: path + name: privateLinkConnectionId + required: true + schema: + type: string + responses: + "200": + content: + application/json: + schema: + $ref: '#/components/schemas/PrivateLinkConnection' + description: A successful response. + default: + content: + application/json: + schema: + $ref: '#/components/schemas/Status' + description: An unexpected error response. + summary: Get a private link connection. + tags: + - PrivateLinkConnectionService + /v1beta1/clusters/{clusterId}/privateLinkConnections: + get: + operationId: PrivateLinkConnectionService_ListPrivateLinkConnections + parameters: + - description: The cluster ID. + in: path + name: clusterId + required: true + schema: + type: string + - description: The maximum number to return. + in: query + name: pageSize + schema: + format: int32 + type: integer + - description: The page token for pagination. + in: query + name: pageToken + schema: + type: string + - description: |2- + - CREATING: The private link connection is being created. + - ACTIVE: The private link connection is active. + - FAILED: The private link connection is in failed state. + - PENDING_ACCEPTANCE: The private link connection is pending acceptance. only for AWS endpoint service and Alicloud endpoint service. + - DELETING: The private link connection is being deleted. + in: query + name: state + schema: + $ref: '#/components/schemas/PrivateLinkConnectionService_ListPrivateLinkConnections_state_parameter' + responses: + "200": + content: + application/json: + schema: + $ref: '#/components/schemas/ListPrivateLinkConnectionsResponse' + description: A successful response. + default: + content: + application/json: + schema: + $ref: '#/components/schemas/Status' + description: An unexpected error response. + summary: List private link connections. + tags: + - PrivateLinkConnectionService + post: + operationId: PrivateLinkConnectionService_CreatePrivateLinkConnection + parameters: + - description: The cluster ID. + in: path + name: clusterId + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PrivateLinkConnectionService.CreatePrivateLinkConnectionBody' + required: true + responses: + "200": + content: + application/json: + schema: + $ref: '#/components/schemas/PrivateLinkConnection' + description: A successful response. + default: + content: + application/json: + schema: + $ref: '#/components/schemas/Status' + description: An unexpected error response. + summary: Create a private link connection. + tags: + - PrivateLinkConnectionService + x-codegen-request-body-name: body + /v1beta1/clusters/{clusterId}/privateLinkConnections:getAvailabilityZones: + get: + operationId: PrivateLinkConnectionService_GetAvailabilityZones + parameters: + - description: The cluster ID. + in: path + name: clusterId + required: true + schema: + type: string + responses: + "200": + content: + application/json: + schema: + $ref: '#/components/schemas/GetAvailabilityZonesResponse' + description: A successful response. + default: + content: + application/json: + schema: + $ref: '#/components/schemas/Status' + description: An unexpected error response. + summary: Get account and availability zones information for private link connection. + tags: + - PrivateLinkConnectionService +components: + schemas: + AlicloudEndpointService: + example: + name: name + properties: + name: + description: The endpoint service name. + type: string + required: + - name + type: object + Any: + additionalProperties: + type: object + example: + '@type': '@type' + properties: + '@type': + type: string + type: object + AwsEndpointService: + example: + name: name + region: region + properties: + name: + description: The endpoint service name. + type: string + region: + title: "The region of endpoint service name, default to cluster's region" + type: string + required: + - name + type: object + GetAvailabilityZonesResponse: + example: + azIds: + - azIds + - azIds + accountId: accountId + properties: + accountId: + description: The account ID. + type: string + azIds: + description: Availability zone ids. + items: + type: string + type: array + type: object + ListPrivateLinkConnectionsResponse: + example: + totalSize: 0 + nextPageToken: nextPageToken + privateLinkConnections: + - awsEndpointService: + name: name + region: region + createdBy: createdBy + createTime: 2000-01-23T04:56:07.000+00:00 + displayName: displayName + privateLinkConnectionId: privateLinkConnectionId + updateTime: 2000-01-23T04:56:07.000+00:00 + clusterId: clusterId + state: "{}" + message: message + type: "{}" + alicloudEndpointService: + name: name + - awsEndpointService: + name: name + region: region + createdBy: createdBy + createTime: 2000-01-23T04:56:07.000+00:00 + displayName: displayName + privateLinkConnectionId: privateLinkConnectionId + updateTime: 2000-01-23T04:56:07.000+00:00 + clusterId: clusterId + state: "{}" + message: message + type: "{}" + alicloudEndpointService: + name: name + properties: + privateLinkConnections: + items: + $ref: '#/components/schemas/PrivateLinkConnection' + type: array + nextPageToken: + type: string + totalSize: + format: int64 + type: integer + type: object + PrivateLinkConnection: + example: + awsEndpointService: + name: name + region: region + createdBy: createdBy + createTime: 2000-01-23T04:56:07.000+00:00 + displayName: displayName + privateLinkConnectionId: privateLinkConnectionId + updateTime: 2000-01-23T04:56:07.000+00:00 + clusterId: clusterId + state: "{}" + message: message + type: "{}" + alicloudEndpointService: + name: name + properties: + privateLinkConnectionId: + readOnly: true + title: "The private link connection ID, format: plc-xxx" + type: string + clusterId: + description: The ID of the cluster. + type: string + displayName: + description: Display name for the private link connection. + type: string + state: + allOf: + - $ref: '#/components/schemas/PrivateLinkConnectionState.Enum' + description: The state of the private link connection. + type: object + message: + description: The message describing fail reason. + readOnly: true + type: string + createdBy: + description: The user who created the private link connection. + readOnly: true + type: string + createTime: + description: Timestamp when the private link connection was created. + format: date-time + readOnly: true + type: string + updateTime: + description: Timestamp when the private link connection was updated. + format: date-time + nullable: true + readOnly: true + type: string + type: + allOf: + - $ref: '#/components/schemas/PrivateLinkConnectionType.Enum' + title: The type of the private link connection + type: object + awsEndpointService: + $ref: '#/components/schemas/AwsEndpointService' + alicloudEndpointService: + $ref: '#/components/schemas/AlicloudEndpointService' + required: + - clusterId + - displayName + - type + type: object + PrivateLinkConnectionService.CreatePrivateLinkConnectionBody: + properties: + privateLinkConnection: + allOf: + - $ref: '#/components/schemas/PrivateLinkConnection' + description: The private link connection to create. + type: object + required: + - privateLinkConnection + type: object + PrivateLinkConnectionState.Enum: + description: |2- + - CREATING: The private link connection is being created. + - ACTIVE: The private link connection is active. + - FAILED: The private link connection is in failed state. + - PENDING_ACCEPTANCE: The private link connection is pending acceptance. only for AWS endpoint service and Alicloud endpoint service. + - DELETING: The private link connection is being deleted. + enum: + - CREATING + - ACTIVE + - FAILED + - PENDING_ACCEPTANCE + - DELETING + type: string + PrivateLinkConnectionType.Enum: + description: |2- + - AWS_ENDPOINT_SERVICE: AWS endpoint service type. + - ALICLOUD_ENDPOINT_SERVICE: Alicloud endpoint service type. + enum: + - AWS_ENDPOINT_SERVICE + - ALICLOUD_ENDPOINT_SERVICE + type: string + Status: + example: + code: 0 + details: + - '@type': '@type' + - '@type': '@type' + message: message + properties: + code: + format: int32 + type: integer + message: + type: string + details: + items: + $ref: '#/components/schemas/Any' + type: array + type: object + PrivateLinkConnectionService_ListPrivateLinkConnections_state_parameter: + enum: + - CREATING + - ACTIVE + - FAILED + - PENDING_ACCEPTANCE + - DELETING + type: string +x-original-swagger-version: "2.0" diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/api_private_link_connection_service.go b/pkg/tidbcloud/v1beta1/serverless/privatelink/api_private_link_connection_service.go new file mode 100644 index 00000000..bae8113e --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/api_private_link_connection_service.go @@ -0,0 +1,618 @@ +/* +TiDB Cloud Serverless Private Link Connection Open API + +TiDB Cloud Serverless Private Link Connection Open API + +API version: v1beta1 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package privatelink + +import ( + "bytes" + "context" + "io" + "net/http" + "net/url" + "strings" +) + + +// PrivateLinkConnectionServiceAPIService PrivateLinkConnectionServiceAPI service +type PrivateLinkConnectionServiceAPIService service + +type ApiPrivateLinkConnectionServiceCreatePrivateLinkConnectionRequest struct { + ctx context.Context + ApiService *PrivateLinkConnectionServiceAPIService + clusterId string + body *PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody +} + +func (r ApiPrivateLinkConnectionServiceCreatePrivateLinkConnectionRequest) Body(body PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) ApiPrivateLinkConnectionServiceCreatePrivateLinkConnectionRequest { + r.body = &body + return r +} + +func (r ApiPrivateLinkConnectionServiceCreatePrivateLinkConnectionRequest) Execute() (*PrivateLinkConnection, *http.Response, error) { + return r.ApiService.PrivateLinkConnectionServiceCreatePrivateLinkConnectionExecute(r) +} + +/* +PrivateLinkConnectionServiceCreatePrivateLinkConnection Create a private link connection. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param clusterId The cluster ID. + @return ApiPrivateLinkConnectionServiceCreatePrivateLinkConnectionRequest +*/ +func (a *PrivateLinkConnectionServiceAPIService) PrivateLinkConnectionServiceCreatePrivateLinkConnection(ctx context.Context, clusterId string) ApiPrivateLinkConnectionServiceCreatePrivateLinkConnectionRequest { + return ApiPrivateLinkConnectionServiceCreatePrivateLinkConnectionRequest{ + ApiService: a, + ctx: ctx, + clusterId: clusterId, + } +} + +// Execute executes the request +// @return PrivateLinkConnection +func (a *PrivateLinkConnectionServiceAPIService) PrivateLinkConnectionServiceCreatePrivateLinkConnectionExecute(r ApiPrivateLinkConnectionServiceCreatePrivateLinkConnectionRequest) (*PrivateLinkConnection, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *PrivateLinkConnection + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "PrivateLinkConnectionServiceAPIService.PrivateLinkConnectionServiceCreatePrivateLinkConnection") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/v1beta1/clusters/{clusterId}/privateLinkConnections" + localVarPath = strings.Replace(localVarPath, "{"+"clusterId"+"}", url.PathEscape(parameterValueToString(r.clusterId, "clusterId")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.body == nil { + return localVarReturnValue, nil, reportError("body is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.body + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + var v Status + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPrivateLinkConnectionServiceDeletePrivateLinkConnectionRequest struct { + ctx context.Context + ApiService *PrivateLinkConnectionServiceAPIService + clusterId string + privateLinkConnectionId string +} + +func (r ApiPrivateLinkConnectionServiceDeletePrivateLinkConnectionRequest) Execute() (*PrivateLinkConnection, *http.Response, error) { + return r.ApiService.PrivateLinkConnectionServiceDeletePrivateLinkConnectionExecute(r) +} + +/* +PrivateLinkConnectionServiceDeletePrivateLinkConnection Delete a private link connection. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param clusterId The cluster ID. + @param privateLinkConnectionId The private link connection ID. + @return ApiPrivateLinkConnectionServiceDeletePrivateLinkConnectionRequest +*/ +func (a *PrivateLinkConnectionServiceAPIService) PrivateLinkConnectionServiceDeletePrivateLinkConnection(ctx context.Context, clusterId string, privateLinkConnectionId string) ApiPrivateLinkConnectionServiceDeletePrivateLinkConnectionRequest { + return ApiPrivateLinkConnectionServiceDeletePrivateLinkConnectionRequest{ + ApiService: a, + ctx: ctx, + clusterId: clusterId, + privateLinkConnectionId: privateLinkConnectionId, + } +} + +// Execute executes the request +// @return PrivateLinkConnection +func (a *PrivateLinkConnectionServiceAPIService) PrivateLinkConnectionServiceDeletePrivateLinkConnectionExecute(r ApiPrivateLinkConnectionServiceDeletePrivateLinkConnectionRequest) (*PrivateLinkConnection, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *PrivateLinkConnection + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "PrivateLinkConnectionServiceAPIService.PrivateLinkConnectionServiceDeletePrivateLinkConnection") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/v1beta1/clusters/{clusterId}/privateLinkConnections/{privateLinkConnectionId}" + localVarPath = strings.Replace(localVarPath, "{"+"clusterId"+"}", url.PathEscape(parameterValueToString(r.clusterId, "clusterId")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"privateLinkConnectionId"+"}", url.PathEscape(parameterValueToString(r.privateLinkConnectionId, "privateLinkConnectionId")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + var v Status + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPrivateLinkConnectionServiceGetAvailabilityZonesRequest struct { + ctx context.Context + ApiService *PrivateLinkConnectionServiceAPIService + clusterId string +} + +func (r ApiPrivateLinkConnectionServiceGetAvailabilityZonesRequest) Execute() (*GetAvailabilityZonesResponse, *http.Response, error) { + return r.ApiService.PrivateLinkConnectionServiceGetAvailabilityZonesExecute(r) +} + +/* +PrivateLinkConnectionServiceGetAvailabilityZones Get account and availability zones information for private link connection. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param clusterId The cluster ID. + @return ApiPrivateLinkConnectionServiceGetAvailabilityZonesRequest +*/ +func (a *PrivateLinkConnectionServiceAPIService) PrivateLinkConnectionServiceGetAvailabilityZones(ctx context.Context, clusterId string) ApiPrivateLinkConnectionServiceGetAvailabilityZonesRequest { + return ApiPrivateLinkConnectionServiceGetAvailabilityZonesRequest{ + ApiService: a, + ctx: ctx, + clusterId: clusterId, + } +} + +// Execute executes the request +// @return GetAvailabilityZonesResponse +func (a *PrivateLinkConnectionServiceAPIService) PrivateLinkConnectionServiceGetAvailabilityZonesExecute(r ApiPrivateLinkConnectionServiceGetAvailabilityZonesRequest) (*GetAvailabilityZonesResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *GetAvailabilityZonesResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "PrivateLinkConnectionServiceAPIService.PrivateLinkConnectionServiceGetAvailabilityZones") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/v1beta1/clusters/{clusterId}/privateLinkConnections:getAvailabilityZones" + localVarPath = strings.Replace(localVarPath, "{"+"clusterId"+"}", url.PathEscape(parameterValueToString(r.clusterId, "clusterId")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + var v Status + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPrivateLinkConnectionServiceGetPrivateLinkConnectionRequest struct { + ctx context.Context + ApiService *PrivateLinkConnectionServiceAPIService + clusterId string + privateLinkConnectionId string +} + +func (r ApiPrivateLinkConnectionServiceGetPrivateLinkConnectionRequest) Execute() (*PrivateLinkConnection, *http.Response, error) { + return r.ApiService.PrivateLinkConnectionServiceGetPrivateLinkConnectionExecute(r) +} + +/* +PrivateLinkConnectionServiceGetPrivateLinkConnection Get a private link connection. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param clusterId The cluster ID. + @param privateLinkConnectionId The private link connection ID. + @return ApiPrivateLinkConnectionServiceGetPrivateLinkConnectionRequest +*/ +func (a *PrivateLinkConnectionServiceAPIService) PrivateLinkConnectionServiceGetPrivateLinkConnection(ctx context.Context, clusterId string, privateLinkConnectionId string) ApiPrivateLinkConnectionServiceGetPrivateLinkConnectionRequest { + return ApiPrivateLinkConnectionServiceGetPrivateLinkConnectionRequest{ + ApiService: a, + ctx: ctx, + clusterId: clusterId, + privateLinkConnectionId: privateLinkConnectionId, + } +} + +// Execute executes the request +// @return PrivateLinkConnection +func (a *PrivateLinkConnectionServiceAPIService) PrivateLinkConnectionServiceGetPrivateLinkConnectionExecute(r ApiPrivateLinkConnectionServiceGetPrivateLinkConnectionRequest) (*PrivateLinkConnection, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *PrivateLinkConnection + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "PrivateLinkConnectionServiceAPIService.PrivateLinkConnectionServiceGetPrivateLinkConnection") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/v1beta1/clusters/{clusterId}/privateLinkConnections/{privateLinkConnectionId}" + localVarPath = strings.Replace(localVarPath, "{"+"clusterId"+"}", url.PathEscape(parameterValueToString(r.clusterId, "clusterId")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"privateLinkConnectionId"+"}", url.PathEscape(parameterValueToString(r.privateLinkConnectionId, "privateLinkConnectionId")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + var v Status + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPrivateLinkConnectionServiceListPrivateLinkConnectionsRequest struct { + ctx context.Context + ApiService *PrivateLinkConnectionServiceAPIService + clusterId string + pageSize *int32 + pageToken *string + state *PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter +} + +// The maximum number to return. +func (r ApiPrivateLinkConnectionServiceListPrivateLinkConnectionsRequest) PageSize(pageSize int32) ApiPrivateLinkConnectionServiceListPrivateLinkConnectionsRequest { + r.pageSize = &pageSize + return r +} + +// The page token for pagination. +func (r ApiPrivateLinkConnectionServiceListPrivateLinkConnectionsRequest) PageToken(pageToken string) ApiPrivateLinkConnectionServiceListPrivateLinkConnectionsRequest { + r.pageToken = &pageToken + return r +} + +// - CREATING: The private link connection is being created. - ACTIVE: The private link connection is active. - FAILED: The private link connection is in failed state. - PENDING_ACCEPTANCE: The private link connection is pending acceptance. only for AWS endpoint service and Alicloud endpoint service. - DELETING: The private link connection is being deleted. +func (r ApiPrivateLinkConnectionServiceListPrivateLinkConnectionsRequest) State(state PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter) ApiPrivateLinkConnectionServiceListPrivateLinkConnectionsRequest { + r.state = &state + return r +} + +func (r ApiPrivateLinkConnectionServiceListPrivateLinkConnectionsRequest) Execute() (*ListPrivateLinkConnectionsResponse, *http.Response, error) { + return r.ApiService.PrivateLinkConnectionServiceListPrivateLinkConnectionsExecute(r) +} + +/* +PrivateLinkConnectionServiceListPrivateLinkConnections List private link connections. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param clusterId The cluster ID. + @return ApiPrivateLinkConnectionServiceListPrivateLinkConnectionsRequest +*/ +func (a *PrivateLinkConnectionServiceAPIService) PrivateLinkConnectionServiceListPrivateLinkConnections(ctx context.Context, clusterId string) ApiPrivateLinkConnectionServiceListPrivateLinkConnectionsRequest { + return ApiPrivateLinkConnectionServiceListPrivateLinkConnectionsRequest{ + ApiService: a, + ctx: ctx, + clusterId: clusterId, + } +} + +// Execute executes the request +// @return ListPrivateLinkConnectionsResponse +func (a *PrivateLinkConnectionServiceAPIService) PrivateLinkConnectionServiceListPrivateLinkConnectionsExecute(r ApiPrivateLinkConnectionServiceListPrivateLinkConnectionsRequest) (*ListPrivateLinkConnectionsResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ListPrivateLinkConnectionsResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "PrivateLinkConnectionServiceAPIService.PrivateLinkConnectionServiceListPrivateLinkConnections") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/v1beta1/clusters/{clusterId}/privateLinkConnections" + localVarPath = strings.Replace(localVarPath, "{"+"clusterId"+"}", url.PathEscape(parameterValueToString(r.clusterId, "clusterId")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.pageSize != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "pageSize", r.pageSize, "", "") + } + if r.pageToken != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "pageToken", r.pageToken, "", "") + } + if r.state != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "state", r.state, "", "") + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + var v Status + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/client.go b/pkg/tidbcloud/v1beta1/serverless/privatelink/client.go new file mode 100644 index 00000000..c74b9758 --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/client.go @@ -0,0 +1,656 @@ +/* +TiDB Cloud Serverless Private Link Connection Open API + +TiDB Cloud Serverless Private Link Connection Open API + +API version: v1beta1 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package privatelink + +import ( + "bytes" + "context" + "encoding/json" + "encoding/xml" + "errors" + "fmt" + "io" + "log" + "mime/multipart" + "net/http" + "net/http/httputil" + "net/url" + "os" + "path/filepath" + "reflect" + "regexp" + "strconv" + "strings" + "time" + "unicode/utf8" + +) + +var ( + JsonCheck = regexp.MustCompile(`(?i:(?:application|text)/(?:[^;]+\+)?json)`) + XmlCheck = regexp.MustCompile(`(?i:(?:application|text)/(?:[^;]+\+)?xml)`) + queryParamSplit = regexp.MustCompile(`(^|&)([^&]+)`) + queryDescape = strings.NewReplacer( "%5B", "[", "%5D", "]" ) +) + +// APIClient manages communication with the TiDB Cloud Serverless Private Link Connection Open API API vv1beta1 +// In most cases there should be only one, shared, APIClient. +type APIClient struct { + cfg *Configuration + common service // Reuse a single struct instead of allocating one for each service on the heap. + + // API Services + + PrivateLinkConnectionServiceAPI *PrivateLinkConnectionServiceAPIService +} + +type service struct { + client *APIClient +} + +// NewAPIClient creates a new API client. Requires a userAgent string describing your application. +// optionally a custom http.Client to allow for advanced features such as caching. +func NewAPIClient(cfg *Configuration) *APIClient { + if cfg.HTTPClient == nil { + cfg.HTTPClient = http.DefaultClient + } + + c := &APIClient{} + c.cfg = cfg + c.common.client = c + + // API Services + c.PrivateLinkConnectionServiceAPI = (*PrivateLinkConnectionServiceAPIService)(&c.common) + + return c +} + +func atoi(in string) (int, error) { + return strconv.Atoi(in) +} + +// selectHeaderContentType select a content type from the available list. +func selectHeaderContentType(contentTypes []string) string { + if len(contentTypes) == 0 { + return "" + } + if contains(contentTypes, "application/json") { + return "application/json" + } + return contentTypes[0] // use the first content type specified in 'consumes' +} + +// selectHeaderAccept join all accept types and return +func selectHeaderAccept(accepts []string) string { + if len(accepts) == 0 { + return "" + } + + if contains(accepts, "application/json") { + return "application/json" + } + + return strings.Join(accepts, ",") +} + +// contains is a case insensitive match, finding needle in a haystack +func contains(haystack []string, needle string) bool { + for _, a := range haystack { + if strings.EqualFold(a, needle) { + return true + } + } + return false +} + +// Verify optional parameters are of the correct type. +func typeCheckParameter(obj interface{}, expected string, name string) error { + // Make sure there is an object. + if obj == nil { + return nil + } + + // Check the type is as expected. + if reflect.TypeOf(obj).String() != expected { + return fmt.Errorf("expected %s to be of type %s but received %s", name, expected, reflect.TypeOf(obj).String()) + } + return nil +} + +func parameterValueToString( obj interface{}, key string ) string { + if reflect.TypeOf(obj).Kind() != reflect.Ptr { + if actualObj, ok := obj.(interface{ GetActualInstanceValue() interface{} }); ok { + return fmt.Sprintf("%v", actualObj.GetActualInstanceValue()) + } + + return fmt.Sprintf("%v", obj) + } + var param,ok = obj.(MappedNullable) + if !ok { + return "" + } + dataMap,err := param.ToMap() + if err != nil { + return "" + } + return fmt.Sprintf("%v", dataMap[key]) +} + +// parameterAddToHeaderOrQuery adds the provided object to the request header or url query +// supporting deep object syntax +func parameterAddToHeaderOrQuery(headerOrQueryParams interface{}, keyPrefix string, obj interface{}, style string, collectionType string) { + var v = reflect.ValueOf(obj) + var value = "" + if v == reflect.ValueOf(nil) { + value = "null" + } else { + switch v.Kind() { + case reflect.Invalid: + value = "invalid" + + case reflect.Struct: + if t,ok := obj.(MappedNullable); ok { + dataMap,err := t.ToMap() + if err != nil { + return + } + parameterAddToHeaderOrQuery(headerOrQueryParams, keyPrefix, dataMap, style, collectionType) + return + } + if t, ok := obj.(time.Time); ok { + parameterAddToHeaderOrQuery(headerOrQueryParams, keyPrefix, t.Format(time.RFC3339Nano), style, collectionType) + return + } + value = v.Type().String() + " value" + case reflect.Slice: + var indValue = reflect.ValueOf(obj) + if indValue == reflect.ValueOf(nil) { + return + } + var lenIndValue = indValue.Len() + for i:=0;i 0 || (len(formFiles) > 0) { + if body != nil { + return nil, errors.New("Cannot specify postBody and multipart form at the same time.") + } + body = &bytes.Buffer{} + w := multipart.NewWriter(body) + + for k, v := range formParams { + for _, iv := range v { + if strings.HasPrefix(k, "@") { // file + err = addFile(w, k[1:], iv) + if err != nil { + return nil, err + } + } else { // form value + w.WriteField(k, iv) + } + } + } + for _, formFile := range formFiles { + if len(formFile.fileBytes) > 0 && formFile.fileName != "" { + w.Boundary() + part, err := w.CreateFormFile(formFile.formFileName, filepath.Base(formFile.fileName)) + if err != nil { + return nil, err + } + _, err = part.Write(formFile.fileBytes) + if err != nil { + return nil, err + } + } + } + + // Set the Boundary in the Content-Type + headerParams["Content-Type"] = w.FormDataContentType() + + // Set Content-Length + headerParams["Content-Length"] = fmt.Sprintf("%d", body.Len()) + w.Close() + } + + if strings.HasPrefix(headerParams["Content-Type"], "application/x-www-form-urlencoded") && len(formParams) > 0 { + if body != nil { + return nil, errors.New("Cannot specify postBody and x-www-form-urlencoded form at the same time.") + } + body = &bytes.Buffer{} + body.WriteString(formParams.Encode()) + // Set Content-Length + headerParams["Content-Length"] = fmt.Sprintf("%d", body.Len()) + } + + // Setup path and query parameters + url, err := url.Parse(path) + if err != nil { + return nil, err + } + + // Override request host, if applicable + if c.cfg.Host != "" { + url.Host = c.cfg.Host + } + + // Override request scheme, if applicable + if c.cfg.Scheme != "" { + url.Scheme = c.cfg.Scheme + } + + // Adding Query Param + query := url.Query() + for k, v := range queryParams { + for _, iv := range v { + query.Add(k, iv) + } + } + + // Encode the parameters. + url.RawQuery = queryParamSplit.ReplaceAllStringFunc(query.Encode(), func(s string) string { + pieces := strings.Split(s, "=") + pieces[0] = queryDescape.Replace(pieces[0]) + return strings.Join(pieces, "=") + }) + + // Generate a new request + if body != nil { + localVarRequest, err = http.NewRequest(method, url.String(), body) + } else { + localVarRequest, err = http.NewRequest(method, url.String(), nil) + } + if err != nil { + return nil, err + } + + // add header parameters, if any + if len(headerParams) > 0 { + headers := http.Header{} + for h, v := range headerParams { + headers[h] = []string{v} + } + localVarRequest.Header = headers + } + + // Add the user agent to the request. + localVarRequest.Header.Add("User-Agent", c.cfg.UserAgent) + + if ctx != nil { + // add context to the request + localVarRequest = localVarRequest.WithContext(ctx) + + // Walk through any authentication. + + } + + for header, value := range c.cfg.DefaultHeader { + localVarRequest.Header.Add(header, value) + } + return localVarRequest, nil +} + +func (c *APIClient) decode(v interface{}, b []byte, contentType string) (err error) { + if len(b) == 0 { + return nil + } + if s, ok := v.(*string); ok { + *s = string(b) + return nil + } + if f, ok := v.(*os.File); ok { + f, err = os.CreateTemp("", "HttpClientFile") + if err != nil { + return + } + _, err = f.Write(b) + if err != nil { + return + } + _, err = f.Seek(0, io.SeekStart) + return + } + if f, ok := v.(**os.File); ok { + *f, err = os.CreateTemp("", "HttpClientFile") + if err != nil { + return + } + _, err = (*f).Write(b) + if err != nil { + return + } + _, err = (*f).Seek(0, io.SeekStart) + return + } + if XmlCheck.MatchString(contentType) { + if err = xml.Unmarshal(b, v); err != nil { + return err + } + return nil + } + if JsonCheck.MatchString(contentType) { + if actualObj, ok := v.(interface{ GetActualInstance() interface{} }); ok { // oneOf, anyOf schemas + if unmarshalObj, ok := actualObj.(interface{ UnmarshalJSON([]byte) error }); ok { // make sure it has UnmarshalJSON defined + if err = unmarshalObj.UnmarshalJSON(b); err != nil { + return err + } + } else { + return errors.New("Unknown type with GetActualInstance but no unmarshalObj.UnmarshalJSON defined") + } + } else if err = json.Unmarshal(b, v); err != nil { // simple model + return err + } + return nil + } + return errors.New("undefined response type") +} + +// Add a file to the multipart request +func addFile(w *multipart.Writer, fieldName, path string) error { + file, err := os.Open(filepath.Clean(path)) + if err != nil { + return err + } + err = file.Close() + if err != nil { + return err + } + + part, err := w.CreateFormFile(fieldName, filepath.Base(path)) + if err != nil { + return err + } + _, err = io.Copy(part, file) + + return err +} + +// Set request body from an interface{} +func setBody(body interface{}, contentType string) (bodyBuf *bytes.Buffer, err error) { + if bodyBuf == nil { + bodyBuf = &bytes.Buffer{} + } + + if reader, ok := body.(io.Reader); ok { + _, err = bodyBuf.ReadFrom(reader) + } else if fp, ok := body.(*os.File); ok { + _, err = bodyBuf.ReadFrom(fp) + } else if b, ok := body.([]byte); ok { + _, err = bodyBuf.Write(b) + } else if s, ok := body.(string); ok { + _, err = bodyBuf.WriteString(s) + } else if s, ok := body.(*string); ok { + _, err = bodyBuf.WriteString(*s) + } else if JsonCheck.MatchString(contentType) { + err = json.NewEncoder(bodyBuf).Encode(body) + } else if XmlCheck.MatchString(contentType) { + var bs []byte + bs, err = xml.Marshal(body) + if err == nil { + bodyBuf.Write(bs) + } + } + + if err != nil { + return nil, err + } + + if bodyBuf.Len() == 0 { + err = fmt.Errorf("invalid body type %s\n", contentType) + return nil, err + } + return bodyBuf, nil +} + +// detectContentType method is used to figure out `Request.Body` content type for request header +func detectContentType(body interface{}) string { + contentType := "text/plain; charset=utf-8" + kind := reflect.TypeOf(body).Kind() + + switch kind { + case reflect.Struct, reflect.Map, reflect.Ptr: + contentType = "application/json; charset=utf-8" + case reflect.String: + contentType = "text/plain; charset=utf-8" + default: + if b, ok := body.([]byte); ok { + contentType = http.DetectContentType(b) + } else if kind == reflect.Slice { + contentType = "application/json; charset=utf-8" + } + } + + return contentType +} + +// Ripped from https://github.com/gregjones/httpcache/blob/master/httpcache.go +type cacheControl map[string]string + +func parseCacheControl(headers http.Header) cacheControl { + cc := cacheControl{} + ccHeader := headers.Get("Cache-Control") + for _, part := range strings.Split(ccHeader, ",") { + part = strings.Trim(part, " ") + if part == "" { + continue + } + if strings.ContainsRune(part, '=') { + keyval := strings.Split(part, "=") + cc[strings.Trim(keyval[0], " ")] = strings.Trim(keyval[1], ",") + } else { + cc[part] = "" + } + } + return cc +} + +// CacheExpires helper function to determine remaining time before repeating a request. +func CacheExpires(r *http.Response) time.Time { + // Figure out when the cache expires. + var expires time.Time + now, err := time.Parse(time.RFC1123, r.Header.Get("date")) + if err != nil { + return time.Now() + } + respCacheControl := parseCacheControl(r.Header) + + if maxAge, ok := respCacheControl["max-age"]; ok { + lifetime, err := time.ParseDuration(maxAge + "s") + if err != nil { + expires = now + } else { + expires = now.Add(lifetime) + } + } else { + expiresHeader := r.Header.Get("Expires") + if expiresHeader != "" { + expires, err = time.Parse(time.RFC1123, expiresHeader) + if err != nil { + expires = now + } + } + } + return expires +} + +func strlen(s string) int { + return utf8.RuneCountInString(s) +} + +// GenericOpenAPIError Provides access to the body, error and model on returned errors. +type GenericOpenAPIError struct { + body []byte + error string + model interface{} +} + +// Error returns non-empty string if there was an error. +func (e GenericOpenAPIError) Error() string { + return e.error +} + +// Body returns the raw bytes of the response +func (e GenericOpenAPIError) Body() []byte { + return e.body +} + +// Model returns the unpacked model of the error +func (e GenericOpenAPIError) Model() interface{} { + return e.model +} + +// format error message using title and detail when model implements rfc7807 +func formatErrorMessage(status string, v interface{}) string { + str := "" + metaValue := reflect.ValueOf(v).Elem() + + if metaValue.Kind() == reflect.Struct { + field := metaValue.FieldByName("Title") + if field != (reflect.Value{}) { + str = fmt.Sprintf("%s", field.Interface()) + } + + field = metaValue.FieldByName("Detail") + if field != (reflect.Value{}) { + str = fmt.Sprintf("%s (%s)", str, field.Interface()) + } + } + + return strings.TrimSpace(fmt.Sprintf("%s %s", status, str)) +} diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/configuration.go b/pkg/tidbcloud/v1beta1/serverless/privatelink/configuration.go new file mode 100644 index 00000000..45f0e0d4 --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/configuration.go @@ -0,0 +1,215 @@ +/* +TiDB Cloud Serverless Private Link Connection Open API + +TiDB Cloud Serverless Private Link Connection Open API + +API version: v1beta1 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package privatelink + +import ( + "context" + "fmt" + "net/http" + "strings" +) + +// contextKeys are used to identify the type of value in the context. +// Since these are string, it is possible to get a short description of the +// context key for logging and debugging using key.String(). + +type contextKey string + +func (c contextKey) String() string { + return "auth " + string(c) +} + +var ( + // ContextServerIndex uses a server configuration from the index. + ContextServerIndex = contextKey("serverIndex") + + // ContextOperationServerIndices uses a server configuration from the index mapping. + ContextOperationServerIndices = contextKey("serverOperationIndices") + + // ContextServerVariables overrides a server configuration variables. + ContextServerVariables = contextKey("serverVariables") + + // ContextOperationServerVariables overrides a server configuration variables using operation specific values. + ContextOperationServerVariables = contextKey("serverOperationVariables") +) + +// BasicAuth provides basic http authentication to a request passed via context using ContextBasicAuth +type BasicAuth struct { + UserName string `json:"userName,omitempty"` + Password string `json:"password,omitempty"` +} + +// APIKey provides API key based authentication to a request passed via context using ContextAPIKey +type APIKey struct { + Key string + Prefix string +} + +// ServerVariable stores the information about a server variable +type ServerVariable struct { + Description string + DefaultValue string + EnumValues []string +} + +// ServerConfiguration stores the information about a server +type ServerConfiguration struct { + URL string + Description string + Variables map[string]ServerVariable +} + +// ServerConfigurations stores multiple ServerConfiguration items +type ServerConfigurations []ServerConfiguration + +// Configuration stores the configuration of the API client +type Configuration struct { + Host string `json:"host,omitempty"` + Scheme string `json:"scheme,omitempty"` + DefaultHeader map[string]string `json:"defaultHeader,omitempty"` + UserAgent string `json:"userAgent,omitempty"` + Debug bool `json:"debug,omitempty"` + Servers ServerConfigurations + OperationServers map[string]ServerConfigurations + HTTPClient *http.Client +} + +// NewConfiguration returns a new Configuration object +func NewConfiguration() *Configuration { + cfg := &Configuration{ + DefaultHeader: make(map[string]string), + UserAgent: "OpenAPI-Generator/1.0.0/go", + Debug: false, + Servers: ServerConfigurations{ + { + URL: "https://serverless.tidbapi.com", + Description: "No description provided", + }, + }, + OperationServers: map[string]ServerConfigurations{ + }, + } + return cfg +} + +// AddDefaultHeader adds a new HTTP header to the default header in the request +func (c *Configuration) AddDefaultHeader(key string, value string) { + c.DefaultHeader[key] = value +} + +// URL formats template on a index using given variables +func (sc ServerConfigurations) URL(index int, variables map[string]string) (string, error) { + if index < 0 || len(sc) <= index { + return "", fmt.Errorf("index %v out of range %v", index, len(sc)-1) + } + server := sc[index] + url := server.URL + + // go through variables and replace placeholders + for name, variable := range server.Variables { + if value, ok := variables[name]; ok { + found := bool(len(variable.EnumValues) == 0) + for _, enumValue := range variable.EnumValues { + if value == enumValue { + found = true + } + } + if !found { + return "", fmt.Errorf("the variable %s in the server URL has invalid value %v. Must be %v", name, value, variable.EnumValues) + } + url = strings.Replace(url, "{"+name+"}", value, -1) + } else { + url = strings.Replace(url, "{"+name+"}", variable.DefaultValue, -1) + } + } + return url, nil +} + +// ServerURL returns URL based on server settings +func (c *Configuration) ServerURL(index int, variables map[string]string) (string, error) { + return c.Servers.URL(index, variables) +} + +func getServerIndex(ctx context.Context) (int, error) { + si := ctx.Value(ContextServerIndex) + if si != nil { + if index, ok := si.(int); ok { + return index, nil + } + return 0, reportError("Invalid type %T should be int", si) + } + return 0, nil +} + +func getServerOperationIndex(ctx context.Context, endpoint string) (int, error) { + osi := ctx.Value(ContextOperationServerIndices) + if osi != nil { + if operationIndices, ok := osi.(map[string]int); !ok { + return 0, reportError("Invalid type %T should be map[string]int", osi) + } else { + index, ok := operationIndices[endpoint] + if ok { + return index, nil + } + } + } + return getServerIndex(ctx) +} + +func getServerVariables(ctx context.Context) (map[string]string, error) { + sv := ctx.Value(ContextServerVariables) + if sv != nil { + if variables, ok := sv.(map[string]string); ok { + return variables, nil + } + return nil, reportError("ctx value of ContextServerVariables has invalid type %T should be map[string]string", sv) + } + return nil, nil +} + +func getServerOperationVariables(ctx context.Context, endpoint string) (map[string]string, error) { + osv := ctx.Value(ContextOperationServerVariables) + if osv != nil { + if operationVariables, ok := osv.(map[string]map[string]string); !ok { + return nil, reportError("ctx value of ContextOperationServerVariables has invalid type %T should be map[string]map[string]string", osv) + } else { + variables, ok := operationVariables[endpoint] + if ok { + return variables, nil + } + } + } + return getServerVariables(ctx) +} + +// ServerURLWithContext returns a new server URL given an endpoint +func (c *Configuration) ServerURLWithContext(ctx context.Context, endpoint string) (string, error) { + sc, ok := c.OperationServers[endpoint] + if !ok { + sc = c.Servers + } + + if ctx == nil { + return sc.URL(0, nil) + } + + index, err := getServerOperationIndex(ctx, endpoint) + if err != nil { + return "", err + } + + variables, err := getServerOperationVariables(ctx, endpoint) + if err != nil { + return "", err + } + + return sc.URL(index, variables) +} diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/git_push.sh b/pkg/tidbcloud/v1beta1/serverless/privatelink/git_push.sh new file mode 100644 index 00000000..f53a75d4 --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/git_push.sh @@ -0,0 +1,57 @@ +#!/bin/sh +# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ +# +# Usage example: /bin/sh ./git_push.sh wing328 openapi-petstore-perl "minor update" "gitlab.com" + +git_user_id=$1 +git_repo_id=$2 +release_note=$3 +git_host=$4 + +if [ "$git_host" = "" ]; then + git_host="github.com" + echo "[INFO] No command line input provided. Set \$git_host to $git_host" +fi + +if [ "$git_user_id" = "" ]; then + git_user_id="GIT_USER_ID" + echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id" +fi + +if [ "$git_repo_id" = "" ]; then + git_repo_id="GIT_REPO_ID" + echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id" +fi + +if [ "$release_note" = "" ]; then + release_note="Minor update" + echo "[INFO] No command line input provided. Set \$release_note to $release_note" +fi + +# Initialize the local directory as a Git repository +git init + +# Adds the files in the local repository and stages them for commit. +git add . + +# Commits the tracked changes and prepares them to be pushed to a remote repository. +git commit -m "$release_note" + +# Sets the new remote +git_remote=$(git remote) +if [ "$git_remote" = "" ]; then # git remote not defined + + if [ "$GIT_TOKEN" = "" ]; then + echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." + git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git + else + git remote add origin https://${git_user_id}:"${GIT_TOKEN}"@${git_host}/${git_user_id}/${git_repo_id}.git + fi + +fi + +git pull origin master + +# Pushes (Forces) the changes in the local repository up to the remote repository +echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git" +git push origin master 2>&1 | grep -v 'To https' diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/model_alicloud_endpoint_service.go b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_alicloud_endpoint_service.go new file mode 100644 index 00000000..af54fed8 --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_alicloud_endpoint_service.go @@ -0,0 +1,169 @@ +/* +TiDB Cloud Serverless Private Link Connection Open API + +TiDB Cloud Serverless Private Link Connection Open API + +API version: v1beta1 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package privatelink + +import ( + "encoding/json" + "fmt" +) + +// checks if the AlicloudEndpointService type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &AlicloudEndpointService{} + +// AlicloudEndpointService struct for AlicloudEndpointService +type AlicloudEndpointService struct { + // The endpoint service name. + Name string `json:"name"` + AdditionalProperties map[string]interface{} +} + +type _AlicloudEndpointService AlicloudEndpointService + +// NewAlicloudEndpointService instantiates a new AlicloudEndpointService object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAlicloudEndpointService(name string) *AlicloudEndpointService { + this := AlicloudEndpointService{} + this.Name = name + return &this +} + +// NewAlicloudEndpointServiceWithDefaults instantiates a new AlicloudEndpointService object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAlicloudEndpointServiceWithDefaults() *AlicloudEndpointService { + this := AlicloudEndpointService{} + return &this +} + +// GetName returns the Name field value +func (o *AlicloudEndpointService) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *AlicloudEndpointService) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *AlicloudEndpointService) SetName(v string) { + o.Name = v +} + +func (o AlicloudEndpointService) MarshalJSON() ([]byte, error) { + toSerialize,err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o AlicloudEndpointService) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + toSerialize["name"] = o.Name + + for key, value := range o.AdditionalProperties { + toSerialize[key] = value + } + + return toSerialize, nil +} + +func (o *AlicloudEndpointService) UnmarshalJSON(data []byte) (err error) { + // This validates that all required properties are included in the JSON object + // by unmarshalling the object into a generic map with string keys and checking + // that every required field exists as a key in the generic map. + requiredProperties := []string{ + "name", + } + + allProperties := make(map[string]interface{}) + + err = json.Unmarshal(data, &allProperties) + + if err != nil { + return err; + } + + for _, requiredProperty := range(requiredProperties) { + if _, exists := allProperties[requiredProperty]; !exists { + return fmt.Errorf("no value given for required property %v", requiredProperty) + } + } + + varAlicloudEndpointService := _AlicloudEndpointService{} + + err = json.Unmarshal(data, &varAlicloudEndpointService) + + if err != nil { + return err + } + + *o = AlicloudEndpointService(varAlicloudEndpointService) + + additionalProperties := make(map[string]interface{}) + + if err = json.Unmarshal(data, &additionalProperties); err == nil { + delete(additionalProperties, "name") + o.AdditionalProperties = additionalProperties + } + + return err +} + +type NullableAlicloudEndpointService struct { + value *AlicloudEndpointService + isSet bool +} + +func (v NullableAlicloudEndpointService) Get() *AlicloudEndpointService { + return v.value +} + +func (v *NullableAlicloudEndpointService) Set(val *AlicloudEndpointService) { + v.value = val + v.isSet = true +} + +func (v NullableAlicloudEndpointService) IsSet() bool { + return v.isSet +} + +func (v *NullableAlicloudEndpointService) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAlicloudEndpointService(val *AlicloudEndpointService) *NullableAlicloudEndpointService { + return &NullableAlicloudEndpointService{value: val, isSet: true} +} + +func (v NullableAlicloudEndpointService) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAlicloudEndpointService) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/model_any.go b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_any.go new file mode 100644 index 00000000..1502f8ea --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_any.go @@ -0,0 +1,155 @@ +/* +TiDB Cloud Serverless Private Link Connection Open API + +TiDB Cloud Serverless Private Link Connection Open API + +API version: v1beta1 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package privatelink + +import ( + "encoding/json" +) + +// checks if the Any type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &Any{} + +// Any struct for Any +type Any struct { + Type *string `json:"@type,omitempty"` + AdditionalProperties map[string]interface{} +} + +type _Any Any + +// NewAny instantiates a new Any object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAny() *Any { + this := Any{} + return &this +} + +// NewAnyWithDefaults instantiates a new Any object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAnyWithDefaults() *Any { + this := Any{} + return &this +} + +// GetType returns the Type field value if set, zero value otherwise. +func (o *Any) GetType() string { + if o == nil || IsNil(o.Type) { + var ret string + return ret + } + return *o.Type +} + +// GetTypeOk returns a tuple with the Type field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Any) GetTypeOk() (*string, bool) { + if o == nil || IsNil(o.Type) { + return nil, false + } + return o.Type, true +} + +// HasType returns a boolean if a field has been set. +func (o *Any) HasType() bool { + if o != nil && !IsNil(o.Type) { + return true + } + + return false +} + +// SetType gets a reference to the given string and assigns it to the Type field. +func (o *Any) SetType(v string) { + o.Type = &v +} + +func (o Any) MarshalJSON() ([]byte, error) { + toSerialize,err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o Any) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + if !IsNil(o.Type) { + toSerialize["@type"] = o.Type + } + + for key, value := range o.AdditionalProperties { + toSerialize[key] = value + } + + return toSerialize, nil +} + +func (o *Any) UnmarshalJSON(data []byte) (err error) { + varAny := _Any{} + + err = json.Unmarshal(data, &varAny) + + if err != nil { + return err + } + + *o = Any(varAny) + + additionalProperties := make(map[string]interface{}) + + if err = json.Unmarshal(data, &additionalProperties); err == nil { + delete(additionalProperties, "@type") + o.AdditionalProperties = additionalProperties + } + + return err +} + +type NullableAny struct { + value *Any + isSet bool +} + +func (v NullableAny) Get() *Any { + return v.value +} + +func (v *NullableAny) Set(val *Any) { + v.value = val + v.isSet = true +} + +func (v NullableAny) IsSet() bool { + return v.isSet +} + +func (v *NullableAny) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAny(val *Any) *NullableAny { + return &NullableAny{value: val, isSet: true} +} + +func (v NullableAny) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAny) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/model_aws_endpoint_service.go b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_aws_endpoint_service.go new file mode 100644 index 00000000..60e3920d --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_aws_endpoint_service.go @@ -0,0 +1,206 @@ +/* +TiDB Cloud Serverless Private Link Connection Open API + +TiDB Cloud Serverless Private Link Connection Open API + +API version: v1beta1 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package privatelink + +import ( + "encoding/json" + "fmt" +) + +// checks if the AwsEndpointService type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &AwsEndpointService{} + +// AwsEndpointService struct for AwsEndpointService +type AwsEndpointService struct { + // The endpoint service name. + Name string `json:"name"` + Region *string `json:"region,omitempty"` + AdditionalProperties map[string]interface{} +} + +type _AwsEndpointService AwsEndpointService + +// NewAwsEndpointService instantiates a new AwsEndpointService object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAwsEndpointService(name string) *AwsEndpointService { + this := AwsEndpointService{} + this.Name = name + return &this +} + +// NewAwsEndpointServiceWithDefaults instantiates a new AwsEndpointService object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAwsEndpointServiceWithDefaults() *AwsEndpointService { + this := AwsEndpointService{} + return &this +} + +// GetName returns the Name field value +func (o *AwsEndpointService) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *AwsEndpointService) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *AwsEndpointService) SetName(v string) { + o.Name = v +} + +// GetRegion returns the Region field value if set, zero value otherwise. +func (o *AwsEndpointService) GetRegion() string { + if o == nil || IsNil(o.Region) { + var ret string + return ret + } + return *o.Region +} + +// GetRegionOk returns a tuple with the Region field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AwsEndpointService) GetRegionOk() (*string, bool) { + if o == nil || IsNil(o.Region) { + return nil, false + } + return o.Region, true +} + +// HasRegion returns a boolean if a field has been set. +func (o *AwsEndpointService) HasRegion() bool { + if o != nil && !IsNil(o.Region) { + return true + } + + return false +} + +// SetRegion gets a reference to the given string and assigns it to the Region field. +func (o *AwsEndpointService) SetRegion(v string) { + o.Region = &v +} + +func (o AwsEndpointService) MarshalJSON() ([]byte, error) { + toSerialize,err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o AwsEndpointService) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + toSerialize["name"] = o.Name + if !IsNil(o.Region) { + toSerialize["region"] = o.Region + } + + for key, value := range o.AdditionalProperties { + toSerialize[key] = value + } + + return toSerialize, nil +} + +func (o *AwsEndpointService) UnmarshalJSON(data []byte) (err error) { + // This validates that all required properties are included in the JSON object + // by unmarshalling the object into a generic map with string keys and checking + // that every required field exists as a key in the generic map. + requiredProperties := []string{ + "name", + } + + allProperties := make(map[string]interface{}) + + err = json.Unmarshal(data, &allProperties) + + if err != nil { + return err; + } + + for _, requiredProperty := range(requiredProperties) { + if _, exists := allProperties[requiredProperty]; !exists { + return fmt.Errorf("no value given for required property %v", requiredProperty) + } + } + + varAwsEndpointService := _AwsEndpointService{} + + err = json.Unmarshal(data, &varAwsEndpointService) + + if err != nil { + return err + } + + *o = AwsEndpointService(varAwsEndpointService) + + additionalProperties := make(map[string]interface{}) + + if err = json.Unmarshal(data, &additionalProperties); err == nil { + delete(additionalProperties, "name") + delete(additionalProperties, "region") + o.AdditionalProperties = additionalProperties + } + + return err +} + +type NullableAwsEndpointService struct { + value *AwsEndpointService + isSet bool +} + +func (v NullableAwsEndpointService) Get() *AwsEndpointService { + return v.value +} + +func (v *NullableAwsEndpointService) Set(val *AwsEndpointService) { + v.value = val + v.isSet = true +} + +func (v NullableAwsEndpointService) IsSet() bool { + return v.isSet +} + +func (v *NullableAwsEndpointService) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAwsEndpointService(val *AwsEndpointService) *NullableAwsEndpointService { + return &NullableAwsEndpointService{value: val, isSet: true} +} + +func (v NullableAwsEndpointService) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAwsEndpointService) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/model_get_availability_zones_response.go b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_get_availability_zones_response.go new file mode 100644 index 00000000..45ab7d32 --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_get_availability_zones_response.go @@ -0,0 +1,194 @@ +/* +TiDB Cloud Serverless Private Link Connection Open API + +TiDB Cloud Serverless Private Link Connection Open API + +API version: v1beta1 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package privatelink + +import ( + "encoding/json" +) + +// checks if the GetAvailabilityZonesResponse type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &GetAvailabilityZonesResponse{} + +// GetAvailabilityZonesResponse struct for GetAvailabilityZonesResponse +type GetAvailabilityZonesResponse struct { + // The account ID. + AccountId *string `json:"accountId,omitempty"` + // Availability zone ids. + AzIds []string `json:"azIds,omitempty"` + AdditionalProperties map[string]interface{} +} + +type _GetAvailabilityZonesResponse GetAvailabilityZonesResponse + +// NewGetAvailabilityZonesResponse instantiates a new GetAvailabilityZonesResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewGetAvailabilityZonesResponse() *GetAvailabilityZonesResponse { + this := GetAvailabilityZonesResponse{} + return &this +} + +// NewGetAvailabilityZonesResponseWithDefaults instantiates a new GetAvailabilityZonesResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewGetAvailabilityZonesResponseWithDefaults() *GetAvailabilityZonesResponse { + this := GetAvailabilityZonesResponse{} + return &this +} + +// GetAccountId returns the AccountId field value if set, zero value otherwise. +func (o *GetAvailabilityZonesResponse) GetAccountId() string { + if o == nil || IsNil(o.AccountId) { + var ret string + return ret + } + return *o.AccountId +} + +// GetAccountIdOk returns a tuple with the AccountId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *GetAvailabilityZonesResponse) GetAccountIdOk() (*string, bool) { + if o == nil || IsNil(o.AccountId) { + return nil, false + } + return o.AccountId, true +} + +// HasAccountId returns a boolean if a field has been set. +func (o *GetAvailabilityZonesResponse) HasAccountId() bool { + if o != nil && !IsNil(o.AccountId) { + return true + } + + return false +} + +// SetAccountId gets a reference to the given string and assigns it to the AccountId field. +func (o *GetAvailabilityZonesResponse) SetAccountId(v string) { + o.AccountId = &v +} + +// GetAzIds returns the AzIds field value if set, zero value otherwise. +func (o *GetAvailabilityZonesResponse) GetAzIds() []string { + if o == nil || IsNil(o.AzIds) { + var ret []string + return ret + } + return o.AzIds +} + +// GetAzIdsOk returns a tuple with the AzIds field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *GetAvailabilityZonesResponse) GetAzIdsOk() ([]string, bool) { + if o == nil || IsNil(o.AzIds) { + return nil, false + } + return o.AzIds, true +} + +// HasAzIds returns a boolean if a field has been set. +func (o *GetAvailabilityZonesResponse) HasAzIds() bool { + if o != nil && !IsNil(o.AzIds) { + return true + } + + return false +} + +// SetAzIds gets a reference to the given []string and assigns it to the AzIds field. +func (o *GetAvailabilityZonesResponse) SetAzIds(v []string) { + o.AzIds = v +} + +func (o GetAvailabilityZonesResponse) MarshalJSON() ([]byte, error) { + toSerialize,err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o GetAvailabilityZonesResponse) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + if !IsNil(o.AccountId) { + toSerialize["accountId"] = o.AccountId + } + if !IsNil(o.AzIds) { + toSerialize["azIds"] = o.AzIds + } + + for key, value := range o.AdditionalProperties { + toSerialize[key] = value + } + + return toSerialize, nil +} + +func (o *GetAvailabilityZonesResponse) UnmarshalJSON(data []byte) (err error) { + varGetAvailabilityZonesResponse := _GetAvailabilityZonesResponse{} + + err = json.Unmarshal(data, &varGetAvailabilityZonesResponse) + + if err != nil { + return err + } + + *o = GetAvailabilityZonesResponse(varGetAvailabilityZonesResponse) + + additionalProperties := make(map[string]interface{}) + + if err = json.Unmarshal(data, &additionalProperties); err == nil { + delete(additionalProperties, "accountId") + delete(additionalProperties, "azIds") + o.AdditionalProperties = additionalProperties + } + + return err +} + +type NullableGetAvailabilityZonesResponse struct { + value *GetAvailabilityZonesResponse + isSet bool +} + +func (v NullableGetAvailabilityZonesResponse) Get() *GetAvailabilityZonesResponse { + return v.value +} + +func (v *NullableGetAvailabilityZonesResponse) Set(val *GetAvailabilityZonesResponse) { + v.value = val + v.isSet = true +} + +func (v NullableGetAvailabilityZonesResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableGetAvailabilityZonesResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableGetAvailabilityZonesResponse(val *GetAvailabilityZonesResponse) *NullableGetAvailabilityZonesResponse { + return &NullableGetAvailabilityZonesResponse{value: val, isSet: true} +} + +func (v NullableGetAvailabilityZonesResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableGetAvailabilityZonesResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/model_list_private_link_connections_response.go b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_list_private_link_connections_response.go new file mode 100644 index 00000000..385c175c --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_list_private_link_connections_response.go @@ -0,0 +1,229 @@ +/* +TiDB Cloud Serverless Private Link Connection Open API + +TiDB Cloud Serverless Private Link Connection Open API + +API version: v1beta1 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package privatelink + +import ( + "encoding/json" +) + +// checks if the ListPrivateLinkConnectionsResponse type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &ListPrivateLinkConnectionsResponse{} + +// ListPrivateLinkConnectionsResponse struct for ListPrivateLinkConnectionsResponse +type ListPrivateLinkConnectionsResponse struct { + PrivateLinkConnections []PrivateLinkConnection `json:"privateLinkConnections,omitempty"` + NextPageToken *string `json:"nextPageToken,omitempty"` + TotalSize *int64 `json:"totalSize,omitempty"` + AdditionalProperties map[string]interface{} +} + +type _ListPrivateLinkConnectionsResponse ListPrivateLinkConnectionsResponse + +// NewListPrivateLinkConnectionsResponse instantiates a new ListPrivateLinkConnectionsResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewListPrivateLinkConnectionsResponse() *ListPrivateLinkConnectionsResponse { + this := ListPrivateLinkConnectionsResponse{} + return &this +} + +// NewListPrivateLinkConnectionsResponseWithDefaults instantiates a new ListPrivateLinkConnectionsResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewListPrivateLinkConnectionsResponseWithDefaults() *ListPrivateLinkConnectionsResponse { + this := ListPrivateLinkConnectionsResponse{} + return &this +} + +// GetPrivateLinkConnections returns the PrivateLinkConnections field value if set, zero value otherwise. +func (o *ListPrivateLinkConnectionsResponse) GetPrivateLinkConnections() []PrivateLinkConnection { + if o == nil || IsNil(o.PrivateLinkConnections) { + var ret []PrivateLinkConnection + return ret + } + return o.PrivateLinkConnections +} + +// GetPrivateLinkConnectionsOk returns a tuple with the PrivateLinkConnections field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ListPrivateLinkConnectionsResponse) GetPrivateLinkConnectionsOk() ([]PrivateLinkConnection, bool) { + if o == nil || IsNil(o.PrivateLinkConnections) { + return nil, false + } + return o.PrivateLinkConnections, true +} + +// HasPrivateLinkConnections returns a boolean if a field has been set. +func (o *ListPrivateLinkConnectionsResponse) HasPrivateLinkConnections() bool { + if o != nil && !IsNil(o.PrivateLinkConnections) { + return true + } + + return false +} + +// SetPrivateLinkConnections gets a reference to the given []PrivateLinkConnection and assigns it to the PrivateLinkConnections field. +func (o *ListPrivateLinkConnectionsResponse) SetPrivateLinkConnections(v []PrivateLinkConnection) { + o.PrivateLinkConnections = v +} + +// GetNextPageToken returns the NextPageToken field value if set, zero value otherwise. +func (o *ListPrivateLinkConnectionsResponse) GetNextPageToken() string { + if o == nil || IsNil(o.NextPageToken) { + var ret string + return ret + } + return *o.NextPageToken +} + +// GetNextPageTokenOk returns a tuple with the NextPageToken field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ListPrivateLinkConnectionsResponse) GetNextPageTokenOk() (*string, bool) { + if o == nil || IsNil(o.NextPageToken) { + return nil, false + } + return o.NextPageToken, true +} + +// HasNextPageToken returns a boolean if a field has been set. +func (o *ListPrivateLinkConnectionsResponse) HasNextPageToken() bool { + if o != nil && !IsNil(o.NextPageToken) { + return true + } + + return false +} + +// SetNextPageToken gets a reference to the given string and assigns it to the NextPageToken field. +func (o *ListPrivateLinkConnectionsResponse) SetNextPageToken(v string) { + o.NextPageToken = &v +} + +// GetTotalSize returns the TotalSize field value if set, zero value otherwise. +func (o *ListPrivateLinkConnectionsResponse) GetTotalSize() int64 { + if o == nil || IsNil(o.TotalSize) { + var ret int64 + return ret + } + return *o.TotalSize +} + +// GetTotalSizeOk returns a tuple with the TotalSize field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ListPrivateLinkConnectionsResponse) GetTotalSizeOk() (*int64, bool) { + if o == nil || IsNil(o.TotalSize) { + return nil, false + } + return o.TotalSize, true +} + +// HasTotalSize returns a boolean if a field has been set. +func (o *ListPrivateLinkConnectionsResponse) HasTotalSize() bool { + if o != nil && !IsNil(o.TotalSize) { + return true + } + + return false +} + +// SetTotalSize gets a reference to the given int64 and assigns it to the TotalSize field. +func (o *ListPrivateLinkConnectionsResponse) SetTotalSize(v int64) { + o.TotalSize = &v +} + +func (o ListPrivateLinkConnectionsResponse) MarshalJSON() ([]byte, error) { + toSerialize,err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o ListPrivateLinkConnectionsResponse) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + if !IsNil(o.PrivateLinkConnections) { + toSerialize["privateLinkConnections"] = o.PrivateLinkConnections + } + if !IsNil(o.NextPageToken) { + toSerialize["nextPageToken"] = o.NextPageToken + } + if !IsNil(o.TotalSize) { + toSerialize["totalSize"] = o.TotalSize + } + + for key, value := range o.AdditionalProperties { + toSerialize[key] = value + } + + return toSerialize, nil +} + +func (o *ListPrivateLinkConnectionsResponse) UnmarshalJSON(data []byte) (err error) { + varListPrivateLinkConnectionsResponse := _ListPrivateLinkConnectionsResponse{} + + err = json.Unmarshal(data, &varListPrivateLinkConnectionsResponse) + + if err != nil { + return err + } + + *o = ListPrivateLinkConnectionsResponse(varListPrivateLinkConnectionsResponse) + + additionalProperties := make(map[string]interface{}) + + if err = json.Unmarshal(data, &additionalProperties); err == nil { + delete(additionalProperties, "privateLinkConnections") + delete(additionalProperties, "nextPageToken") + delete(additionalProperties, "totalSize") + o.AdditionalProperties = additionalProperties + } + + return err +} + +type NullableListPrivateLinkConnectionsResponse struct { + value *ListPrivateLinkConnectionsResponse + isSet bool +} + +func (v NullableListPrivateLinkConnectionsResponse) Get() *ListPrivateLinkConnectionsResponse { + return v.value +} + +func (v *NullableListPrivateLinkConnectionsResponse) Set(val *ListPrivateLinkConnectionsResponse) { + v.value = val + v.isSet = true +} + +func (v NullableListPrivateLinkConnectionsResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableListPrivateLinkConnectionsResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableListPrivateLinkConnectionsResponse(val *ListPrivateLinkConnectionsResponse) *NullableListPrivateLinkConnectionsResponse { + return &NullableListPrivateLinkConnectionsResponse{value: val, isSet: true} +} + +func (v NullableListPrivateLinkConnectionsResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableListPrivateLinkConnectionsResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/model_private_link_connection.go b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_private_link_connection.go new file mode 100644 index 00000000..989e862b --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_private_link_connection.go @@ -0,0 +1,540 @@ +/* +TiDB Cloud Serverless Private Link Connection Open API + +TiDB Cloud Serverless Private Link Connection Open API + +API version: v1beta1 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package privatelink + +import ( + "encoding/json" + "time" + "fmt" +) + +// checks if the PrivateLinkConnection type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &PrivateLinkConnection{} + +// PrivateLinkConnection struct for PrivateLinkConnection +type PrivateLinkConnection struct { + PrivateLinkConnectionId *string `json:"privateLinkConnectionId,omitempty"` + // The ID of the cluster. + ClusterId string `json:"clusterId"` + // Display name for the private link connection. + DisplayName string `json:"displayName"` + // The state of the private link connection. + State *PrivateLinkConnectionStateEnum `json:"state,omitempty"` + // The message describing fail reason. + Message *string `json:"message,omitempty"` + // The user who created the private link connection. + CreatedBy *string `json:"createdBy,omitempty"` + // Timestamp when the private link connection was created. + CreateTime *time.Time `json:"createTime,omitempty"` + // Timestamp when the private link connection was updated. + UpdateTime NullableTime `json:"updateTime,omitempty"` + Type PrivateLinkConnectionTypeEnum `json:"type"` + AwsEndpointService *AwsEndpointService `json:"awsEndpointService,omitempty"` + AlicloudEndpointService *AlicloudEndpointService `json:"alicloudEndpointService,omitempty"` + AdditionalProperties map[string]interface{} +} + +type _PrivateLinkConnection PrivateLinkConnection + +// NewPrivateLinkConnection instantiates a new PrivateLinkConnection object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPrivateLinkConnection(clusterId string, displayName string, type_ PrivateLinkConnectionTypeEnum) *PrivateLinkConnection { + this := PrivateLinkConnection{} + this.ClusterId = clusterId + this.DisplayName = displayName + this.Type = type_ + return &this +} + +// NewPrivateLinkConnectionWithDefaults instantiates a new PrivateLinkConnection object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPrivateLinkConnectionWithDefaults() *PrivateLinkConnection { + this := PrivateLinkConnection{} + return &this +} + +// GetPrivateLinkConnectionId returns the PrivateLinkConnectionId field value if set, zero value otherwise. +func (o *PrivateLinkConnection) GetPrivateLinkConnectionId() string { + if o == nil || IsNil(o.PrivateLinkConnectionId) { + var ret string + return ret + } + return *o.PrivateLinkConnectionId +} + +// GetPrivateLinkConnectionIdOk returns a tuple with the PrivateLinkConnectionId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PrivateLinkConnection) GetPrivateLinkConnectionIdOk() (*string, bool) { + if o == nil || IsNil(o.PrivateLinkConnectionId) { + return nil, false + } + return o.PrivateLinkConnectionId, true +} + +// HasPrivateLinkConnectionId returns a boolean if a field has been set. +func (o *PrivateLinkConnection) HasPrivateLinkConnectionId() bool { + if o != nil && !IsNil(o.PrivateLinkConnectionId) { + return true + } + + return false +} + +// SetPrivateLinkConnectionId gets a reference to the given string and assigns it to the PrivateLinkConnectionId field. +func (o *PrivateLinkConnection) SetPrivateLinkConnectionId(v string) { + o.PrivateLinkConnectionId = &v +} + +// GetClusterId returns the ClusterId field value +func (o *PrivateLinkConnection) GetClusterId() string { + if o == nil { + var ret string + return ret + } + + return o.ClusterId +} + +// GetClusterIdOk returns a tuple with the ClusterId field value +// and a boolean to check if the value has been set. +func (o *PrivateLinkConnection) GetClusterIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ClusterId, true +} + +// SetClusterId sets field value +func (o *PrivateLinkConnection) SetClusterId(v string) { + o.ClusterId = v +} + +// GetDisplayName returns the DisplayName field value +func (o *PrivateLinkConnection) GetDisplayName() string { + if o == nil { + var ret string + return ret + } + + return o.DisplayName +} + +// GetDisplayNameOk returns a tuple with the DisplayName field value +// and a boolean to check if the value has been set. +func (o *PrivateLinkConnection) GetDisplayNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.DisplayName, true +} + +// SetDisplayName sets field value +func (o *PrivateLinkConnection) SetDisplayName(v string) { + o.DisplayName = v +} + +// GetState returns the State field value if set, zero value otherwise. +func (o *PrivateLinkConnection) GetState() PrivateLinkConnectionStateEnum { + if o == nil || IsNil(o.State) { + var ret PrivateLinkConnectionStateEnum + return ret + } + return *o.State +} + +// GetStateOk returns a tuple with the State field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PrivateLinkConnection) GetStateOk() (*PrivateLinkConnectionStateEnum, bool) { + if o == nil || IsNil(o.State) { + return nil, false + } + return o.State, true +} + +// HasState returns a boolean if a field has been set. +func (o *PrivateLinkConnection) HasState() bool { + if o != nil && !IsNil(o.State) { + return true + } + + return false +} + +// SetState gets a reference to the given PrivateLinkConnectionStateEnum and assigns it to the State field. +func (o *PrivateLinkConnection) SetState(v PrivateLinkConnectionStateEnum) { + o.State = &v +} + +// GetMessage returns the Message field value if set, zero value otherwise. +func (o *PrivateLinkConnection) GetMessage() string { + if o == nil || IsNil(o.Message) { + var ret string + return ret + } + return *o.Message +} + +// GetMessageOk returns a tuple with the Message field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PrivateLinkConnection) GetMessageOk() (*string, bool) { + if o == nil || IsNil(o.Message) { + return nil, false + } + return o.Message, true +} + +// HasMessage returns a boolean if a field has been set. +func (o *PrivateLinkConnection) HasMessage() bool { + if o != nil && !IsNil(o.Message) { + return true + } + + return false +} + +// SetMessage gets a reference to the given string and assigns it to the Message field. +func (o *PrivateLinkConnection) SetMessage(v string) { + o.Message = &v +} + +// GetCreatedBy returns the CreatedBy field value if set, zero value otherwise. +func (o *PrivateLinkConnection) GetCreatedBy() string { + if o == nil || IsNil(o.CreatedBy) { + var ret string + return ret + } + return *o.CreatedBy +} + +// GetCreatedByOk returns a tuple with the CreatedBy field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PrivateLinkConnection) GetCreatedByOk() (*string, bool) { + if o == nil || IsNil(o.CreatedBy) { + return nil, false + } + return o.CreatedBy, true +} + +// HasCreatedBy returns a boolean if a field has been set. +func (o *PrivateLinkConnection) HasCreatedBy() bool { + if o != nil && !IsNil(o.CreatedBy) { + return true + } + + return false +} + +// SetCreatedBy gets a reference to the given string and assigns it to the CreatedBy field. +func (o *PrivateLinkConnection) SetCreatedBy(v string) { + o.CreatedBy = &v +} + +// GetCreateTime returns the CreateTime field value if set, zero value otherwise. +func (o *PrivateLinkConnection) GetCreateTime() time.Time { + if o == nil || IsNil(o.CreateTime) { + var ret time.Time + return ret + } + return *o.CreateTime +} + +// GetCreateTimeOk returns a tuple with the CreateTime field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PrivateLinkConnection) GetCreateTimeOk() (*time.Time, bool) { + if o == nil || IsNil(o.CreateTime) { + return nil, false + } + return o.CreateTime, true +} + +// HasCreateTime returns a boolean if a field has been set. +func (o *PrivateLinkConnection) HasCreateTime() bool { + if o != nil && !IsNil(o.CreateTime) { + return true + } + + return false +} + +// SetCreateTime gets a reference to the given time.Time and assigns it to the CreateTime field. +func (o *PrivateLinkConnection) SetCreateTime(v time.Time) { + o.CreateTime = &v +} + +// GetUpdateTime returns the UpdateTime field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *PrivateLinkConnection) GetUpdateTime() time.Time { + if o == nil || IsNil(o.UpdateTime.Get()) { + var ret time.Time + return ret + } + return *o.UpdateTime.Get() +} + +// GetUpdateTimeOk returns a tuple with the UpdateTime field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *PrivateLinkConnection) GetUpdateTimeOk() (*time.Time, bool) { + if o == nil { + return nil, false + } + return o.UpdateTime.Get(), o.UpdateTime.IsSet() +} + +// HasUpdateTime returns a boolean if a field has been set. +func (o *PrivateLinkConnection) HasUpdateTime() bool { + if o != nil && o.UpdateTime.IsSet() { + return true + } + + return false +} + +// SetUpdateTime gets a reference to the given NullableTime and assigns it to the UpdateTime field. +func (o *PrivateLinkConnection) SetUpdateTime(v time.Time) { + o.UpdateTime.Set(&v) +} +// SetUpdateTimeNil sets the value for UpdateTime to be an explicit nil +func (o *PrivateLinkConnection) SetUpdateTimeNil() { + o.UpdateTime.Set(nil) +} + +// UnsetUpdateTime ensures that no value is present for UpdateTime, not even an explicit nil +func (o *PrivateLinkConnection) UnsetUpdateTime() { + o.UpdateTime.Unset() +} + +// GetType returns the Type field value +func (o *PrivateLinkConnection) GetType() PrivateLinkConnectionTypeEnum { + if o == nil { + var ret PrivateLinkConnectionTypeEnum + return ret + } + + return o.Type +} + +// GetTypeOk returns a tuple with the Type field value +// and a boolean to check if the value has been set. +func (o *PrivateLinkConnection) GetTypeOk() (*PrivateLinkConnectionTypeEnum, bool) { + if o == nil { + return nil, false + } + return &o.Type, true +} + +// SetType sets field value +func (o *PrivateLinkConnection) SetType(v PrivateLinkConnectionTypeEnum) { + o.Type = v +} + +// GetAwsEndpointService returns the AwsEndpointService field value if set, zero value otherwise. +func (o *PrivateLinkConnection) GetAwsEndpointService() AwsEndpointService { + if o == nil || IsNil(o.AwsEndpointService) { + var ret AwsEndpointService + return ret + } + return *o.AwsEndpointService +} + +// GetAwsEndpointServiceOk returns a tuple with the AwsEndpointService field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PrivateLinkConnection) GetAwsEndpointServiceOk() (*AwsEndpointService, bool) { + if o == nil || IsNil(o.AwsEndpointService) { + return nil, false + } + return o.AwsEndpointService, true +} + +// HasAwsEndpointService returns a boolean if a field has been set. +func (o *PrivateLinkConnection) HasAwsEndpointService() bool { + if o != nil && !IsNil(o.AwsEndpointService) { + return true + } + + return false +} + +// SetAwsEndpointService gets a reference to the given AwsEndpointService and assigns it to the AwsEndpointService field. +func (o *PrivateLinkConnection) SetAwsEndpointService(v AwsEndpointService) { + o.AwsEndpointService = &v +} + +// GetAlicloudEndpointService returns the AlicloudEndpointService field value if set, zero value otherwise. +func (o *PrivateLinkConnection) GetAlicloudEndpointService() AlicloudEndpointService { + if o == nil || IsNil(o.AlicloudEndpointService) { + var ret AlicloudEndpointService + return ret + } + return *o.AlicloudEndpointService +} + +// GetAlicloudEndpointServiceOk returns a tuple with the AlicloudEndpointService field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PrivateLinkConnection) GetAlicloudEndpointServiceOk() (*AlicloudEndpointService, bool) { + if o == nil || IsNil(o.AlicloudEndpointService) { + return nil, false + } + return o.AlicloudEndpointService, true +} + +// HasAlicloudEndpointService returns a boolean if a field has been set. +func (o *PrivateLinkConnection) HasAlicloudEndpointService() bool { + if o != nil && !IsNil(o.AlicloudEndpointService) { + return true + } + + return false +} + +// SetAlicloudEndpointService gets a reference to the given AlicloudEndpointService and assigns it to the AlicloudEndpointService field. +func (o *PrivateLinkConnection) SetAlicloudEndpointService(v AlicloudEndpointService) { + o.AlicloudEndpointService = &v +} + +func (o PrivateLinkConnection) MarshalJSON() ([]byte, error) { + toSerialize,err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o PrivateLinkConnection) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + if !IsNil(o.PrivateLinkConnectionId) { + toSerialize["privateLinkConnectionId"] = o.PrivateLinkConnectionId + } + toSerialize["clusterId"] = o.ClusterId + toSerialize["displayName"] = o.DisplayName + if !IsNil(o.State) { + toSerialize["state"] = o.State + } + if !IsNil(o.Message) { + toSerialize["message"] = o.Message + } + if !IsNil(o.CreatedBy) { + toSerialize["createdBy"] = o.CreatedBy + } + if !IsNil(o.CreateTime) { + toSerialize["createTime"] = o.CreateTime + } + if o.UpdateTime.IsSet() { + toSerialize["updateTime"] = o.UpdateTime.Get() + } + toSerialize["type"] = o.Type + if !IsNil(o.AwsEndpointService) { + toSerialize["awsEndpointService"] = o.AwsEndpointService + } + if !IsNil(o.AlicloudEndpointService) { + toSerialize["alicloudEndpointService"] = o.AlicloudEndpointService + } + + for key, value := range o.AdditionalProperties { + toSerialize[key] = value + } + + return toSerialize, nil +} + +func (o *PrivateLinkConnection) UnmarshalJSON(data []byte) (err error) { + // This validates that all required properties are included in the JSON object + // by unmarshalling the object into a generic map with string keys and checking + // that every required field exists as a key in the generic map. + requiredProperties := []string{ + "clusterId", + "displayName", + "type", + } + + allProperties := make(map[string]interface{}) + + err = json.Unmarshal(data, &allProperties) + + if err != nil { + return err; + } + + for _, requiredProperty := range(requiredProperties) { + if _, exists := allProperties[requiredProperty]; !exists { + return fmt.Errorf("no value given for required property %v", requiredProperty) + } + } + + varPrivateLinkConnection := _PrivateLinkConnection{} + + err = json.Unmarshal(data, &varPrivateLinkConnection) + + if err != nil { + return err + } + + *o = PrivateLinkConnection(varPrivateLinkConnection) + + additionalProperties := make(map[string]interface{}) + + if err = json.Unmarshal(data, &additionalProperties); err == nil { + delete(additionalProperties, "privateLinkConnectionId") + delete(additionalProperties, "clusterId") + delete(additionalProperties, "displayName") + delete(additionalProperties, "state") + delete(additionalProperties, "message") + delete(additionalProperties, "createdBy") + delete(additionalProperties, "createTime") + delete(additionalProperties, "updateTime") + delete(additionalProperties, "type") + delete(additionalProperties, "awsEndpointService") + delete(additionalProperties, "alicloudEndpointService") + o.AdditionalProperties = additionalProperties + } + + return err +} + +type NullablePrivateLinkConnection struct { + value *PrivateLinkConnection + isSet bool +} + +func (v NullablePrivateLinkConnection) Get() *PrivateLinkConnection { + return v.value +} + +func (v *NullablePrivateLinkConnection) Set(val *PrivateLinkConnection) { + v.value = val + v.isSet = true +} + +func (v NullablePrivateLinkConnection) IsSet() bool { + return v.isSet +} + +func (v *NullablePrivateLinkConnection) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePrivateLinkConnection(val *PrivateLinkConnection) *NullablePrivateLinkConnection { + return &NullablePrivateLinkConnection{value: val, isSet: true} +} + +func (v NullablePrivateLinkConnection) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePrivateLinkConnection) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/model_private_link_connection_service_create_private_link_connection_body.go b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_private_link_connection_service_create_private_link_connection_body.go new file mode 100644 index 00000000..1c4ade0a --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_private_link_connection_service_create_private_link_connection_body.go @@ -0,0 +1,169 @@ +/* +TiDB Cloud Serverless Private Link Connection Open API + +TiDB Cloud Serverless Private Link Connection Open API + +API version: v1beta1 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package privatelink + +import ( + "encoding/json" + "fmt" +) + +// checks if the PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody{} + +// PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody struct for PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody +type PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody struct { + // The private link connection to create. + PrivateLinkConnection PrivateLinkConnection `json:"privateLinkConnection"` + AdditionalProperties map[string]interface{} +} + +type _PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody + +// NewPrivateLinkConnectionServiceCreatePrivateLinkConnectionBody instantiates a new PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPrivateLinkConnectionServiceCreatePrivateLinkConnectionBody(privateLinkConnection PrivateLinkConnection) *PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody { + this := PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody{} + this.PrivateLinkConnection = privateLinkConnection + return &this +} + +// NewPrivateLinkConnectionServiceCreatePrivateLinkConnectionBodyWithDefaults instantiates a new PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPrivateLinkConnectionServiceCreatePrivateLinkConnectionBodyWithDefaults() *PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody { + this := PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody{} + return &this +} + +// GetPrivateLinkConnection returns the PrivateLinkConnection field value +func (o *PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) GetPrivateLinkConnection() PrivateLinkConnection { + if o == nil { + var ret PrivateLinkConnection + return ret + } + + return o.PrivateLinkConnection +} + +// GetPrivateLinkConnectionOk returns a tuple with the PrivateLinkConnection field value +// and a boolean to check if the value has been set. +func (o *PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) GetPrivateLinkConnectionOk() (*PrivateLinkConnection, bool) { + if o == nil { + return nil, false + } + return &o.PrivateLinkConnection, true +} + +// SetPrivateLinkConnection sets field value +func (o *PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) SetPrivateLinkConnection(v PrivateLinkConnection) { + o.PrivateLinkConnection = v +} + +func (o PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) MarshalJSON() ([]byte, error) { + toSerialize,err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + toSerialize["privateLinkConnection"] = o.PrivateLinkConnection + + for key, value := range o.AdditionalProperties { + toSerialize[key] = value + } + + return toSerialize, nil +} + +func (o *PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) UnmarshalJSON(data []byte) (err error) { + // This validates that all required properties are included in the JSON object + // by unmarshalling the object into a generic map with string keys and checking + // that every required field exists as a key in the generic map. + requiredProperties := []string{ + "privateLinkConnection", + } + + allProperties := make(map[string]interface{}) + + err = json.Unmarshal(data, &allProperties) + + if err != nil { + return err; + } + + for _, requiredProperty := range(requiredProperties) { + if _, exists := allProperties[requiredProperty]; !exists { + return fmt.Errorf("no value given for required property %v", requiredProperty) + } + } + + varPrivateLinkConnectionServiceCreatePrivateLinkConnectionBody := _PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody{} + + err = json.Unmarshal(data, &varPrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) + + if err != nil { + return err + } + + *o = PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody(varPrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) + + additionalProperties := make(map[string]interface{}) + + if err = json.Unmarshal(data, &additionalProperties); err == nil { + delete(additionalProperties, "privateLinkConnection") + o.AdditionalProperties = additionalProperties + } + + return err +} + +type NullablePrivateLinkConnectionServiceCreatePrivateLinkConnectionBody struct { + value *PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody + isSet bool +} + +func (v NullablePrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) Get() *PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody { + return v.value +} + +func (v *NullablePrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) Set(val *PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) { + v.value = val + v.isSet = true +} + +func (v NullablePrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) IsSet() bool { + return v.isSet +} + +func (v *NullablePrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePrivateLinkConnectionServiceCreatePrivateLinkConnectionBody(val *PrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) *NullablePrivateLinkConnectionServiceCreatePrivateLinkConnectionBody { + return &NullablePrivateLinkConnectionServiceCreatePrivateLinkConnectionBody{value: val, isSet: true} +} + +func (v NullablePrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePrivateLinkConnectionServiceCreatePrivateLinkConnectionBody) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/model_private_link_connection_service_list_private_link_connections_state_parameter.go b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_private_link_connection_service_list_private_link_connections_state_parameter.go new file mode 100644 index 00000000..214f8f88 --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_private_link_connection_service_list_private_link_connections_state_parameter.go @@ -0,0 +1,112 @@ +/* +TiDB Cloud Serverless Private Link Connection Open API + +TiDB Cloud Serverless Private Link Connection Open API + +API version: v1beta1 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package privatelink + +import ( + "encoding/json" +) + +// PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter the model 'PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter' +type PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter string + +// List of PrivateLinkConnectionService_ListPrivateLinkConnections_state_parameter +const ( + PRIVATELINKCONNECTIONSERVICELISTPRIVATELINKCONNECTIONSSTATEPARAMETER_CREATING PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter = "CREATING" + PRIVATELINKCONNECTIONSERVICELISTPRIVATELINKCONNECTIONSSTATEPARAMETER_ACTIVE PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter = "ACTIVE" + PRIVATELINKCONNECTIONSERVICELISTPRIVATELINKCONNECTIONSSTATEPARAMETER_FAILED PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter = "FAILED" + PRIVATELINKCONNECTIONSERVICELISTPRIVATELINKCONNECTIONSSTATEPARAMETER_PENDING_ACCEPTANCE PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter = "PENDING_ACCEPTANCE" + PRIVATELINKCONNECTIONSERVICELISTPRIVATELINKCONNECTIONSSTATEPARAMETER_DELETING PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter = "DELETING" +) + +// All allowed values of PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter enum +var AllowedPrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameterEnumValues = []PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter{ + "CREATING", + "ACTIVE", + "FAILED", + "PENDING_ACCEPTANCE", + "DELETING", +} + +func (v *PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter) UnmarshalJSON(src []byte) error { + var value string + err := json.Unmarshal(src, &value) + if err != nil { + return err + } + enumTypeValue := PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter(value) + for _, existing := range AllowedPrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameterEnumValues { + if existing == enumTypeValue { + *v = enumTypeValue + return nil + } + } + + *v = PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter(value) + return nil +} + +// NewPrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameterFromValue returns a pointer to a valid PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter for the value passed as argument +func NewPrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameterFromValue(v string) *PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter { + ev := PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter(v) + return &ev +} + +// IsValid return true if the value is valid for the enum, false otherwise +func (v PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter) IsValid() bool { + for _, existing := range AllowedPrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameterEnumValues { + if existing == v { + return true + } + } + return false +} + +// Ptr returns reference to PrivateLinkConnectionService_ListPrivateLinkConnections_state_parameter value +func (v PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter) Ptr() *PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter { + return &v +} + +type NullablePrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter struct { + value *PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter + isSet bool +} + +func (v NullablePrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter) Get() *PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter { + return v.value +} + +func (v *NullablePrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter) Set(val *PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter) { + v.value = val + v.isSet = true +} + +func (v NullablePrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter) IsSet() bool { + return v.isSet +} + +func (v *NullablePrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter(val *PrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter) *NullablePrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter { + return &NullablePrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter{value: val, isSet: true} +} + +func (v NullablePrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePrivateLinkConnectionServiceListPrivateLinkConnectionsStateParameter) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/model_private_link_connection_state_enum.go b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_private_link_connection_state_enum.go new file mode 100644 index 00000000..7c35be11 --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_private_link_connection_state_enum.go @@ -0,0 +1,112 @@ +/* +TiDB Cloud Serverless Private Link Connection Open API + +TiDB Cloud Serverless Private Link Connection Open API + +API version: v1beta1 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package privatelink + +import ( + "encoding/json" +) + +// PrivateLinkConnectionStateEnum - CREATING: The private link connection is being created. - ACTIVE: The private link connection is active. - FAILED: The private link connection is in failed state. - PENDING_ACCEPTANCE: The private link connection is pending acceptance. only for AWS endpoint service and Alicloud endpoint service. - DELETING: The private link connection is being deleted. +type PrivateLinkConnectionStateEnum string + +// List of PrivateLinkConnectionState.Enum +const ( + PRIVATELINKCONNECTIONSTATEENUM_CREATING PrivateLinkConnectionStateEnum = "CREATING" + PRIVATELINKCONNECTIONSTATEENUM_ACTIVE PrivateLinkConnectionStateEnum = "ACTIVE" + PRIVATELINKCONNECTIONSTATEENUM_FAILED PrivateLinkConnectionStateEnum = "FAILED" + PRIVATELINKCONNECTIONSTATEENUM_PENDING_ACCEPTANCE PrivateLinkConnectionStateEnum = "PENDING_ACCEPTANCE" + PRIVATELINKCONNECTIONSTATEENUM_DELETING PrivateLinkConnectionStateEnum = "DELETING" +) + +// All allowed values of PrivateLinkConnectionStateEnum enum +var AllowedPrivateLinkConnectionStateEnumEnumValues = []PrivateLinkConnectionStateEnum{ + "CREATING", + "ACTIVE", + "FAILED", + "PENDING_ACCEPTANCE", + "DELETING", +} + +func (v *PrivateLinkConnectionStateEnum) UnmarshalJSON(src []byte) error { + var value string + err := json.Unmarshal(src, &value) + if err != nil { + return err + } + enumTypeValue := PrivateLinkConnectionStateEnum(value) + for _, existing := range AllowedPrivateLinkConnectionStateEnumEnumValues { + if existing == enumTypeValue { + *v = enumTypeValue + return nil + } + } + + *v = PrivateLinkConnectionStateEnum(value) + return nil +} + +// NewPrivateLinkConnectionStateEnumFromValue returns a pointer to a valid PrivateLinkConnectionStateEnum for the value passed as argument +func NewPrivateLinkConnectionStateEnumFromValue(v string) *PrivateLinkConnectionStateEnum { + ev := PrivateLinkConnectionStateEnum(v) + return &ev +} + +// IsValid return true if the value is valid for the enum, false otherwise +func (v PrivateLinkConnectionStateEnum) IsValid() bool { + for _, existing := range AllowedPrivateLinkConnectionStateEnumEnumValues { + if existing == v { + return true + } + } + return false +} + +// Ptr returns reference to PrivateLinkConnectionState.Enum value +func (v PrivateLinkConnectionStateEnum) Ptr() *PrivateLinkConnectionStateEnum { + return &v +} + +type NullablePrivateLinkConnectionStateEnum struct { + value *PrivateLinkConnectionStateEnum + isSet bool +} + +func (v NullablePrivateLinkConnectionStateEnum) Get() *PrivateLinkConnectionStateEnum { + return v.value +} + +func (v *NullablePrivateLinkConnectionStateEnum) Set(val *PrivateLinkConnectionStateEnum) { + v.value = val + v.isSet = true +} + +func (v NullablePrivateLinkConnectionStateEnum) IsSet() bool { + return v.isSet +} + +func (v *NullablePrivateLinkConnectionStateEnum) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePrivateLinkConnectionStateEnum(val *PrivateLinkConnectionStateEnum) *NullablePrivateLinkConnectionStateEnum { + return &NullablePrivateLinkConnectionStateEnum{value: val, isSet: true} +} + +func (v NullablePrivateLinkConnectionStateEnum) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePrivateLinkConnectionStateEnum) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/model_private_link_connection_type_enum.go b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_private_link_connection_type_enum.go new file mode 100644 index 00000000..2c91f0f7 --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_private_link_connection_type_enum.go @@ -0,0 +1,106 @@ +/* +TiDB Cloud Serverless Private Link Connection Open API + +TiDB Cloud Serverless Private Link Connection Open API + +API version: v1beta1 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package privatelink + +import ( + "encoding/json" +) + +// PrivateLinkConnectionTypeEnum - AWS_ENDPOINT_SERVICE: AWS endpoint service type. - ALICLOUD_ENDPOINT_SERVICE: Alicloud endpoint service type. +type PrivateLinkConnectionTypeEnum string + +// List of PrivateLinkConnectionType.Enum +const ( + PRIVATELINKCONNECTIONTYPEENUM_AWS_ENDPOINT_SERVICE PrivateLinkConnectionTypeEnum = "AWS_ENDPOINT_SERVICE" + PRIVATELINKCONNECTIONTYPEENUM_ALICLOUD_ENDPOINT_SERVICE PrivateLinkConnectionTypeEnum = "ALICLOUD_ENDPOINT_SERVICE" +) + +// All allowed values of PrivateLinkConnectionTypeEnum enum +var AllowedPrivateLinkConnectionTypeEnumEnumValues = []PrivateLinkConnectionTypeEnum{ + "AWS_ENDPOINT_SERVICE", + "ALICLOUD_ENDPOINT_SERVICE", +} + +func (v *PrivateLinkConnectionTypeEnum) UnmarshalJSON(src []byte) error { + var value string + err := json.Unmarshal(src, &value) + if err != nil { + return err + } + enumTypeValue := PrivateLinkConnectionTypeEnum(value) + for _, existing := range AllowedPrivateLinkConnectionTypeEnumEnumValues { + if existing == enumTypeValue { + *v = enumTypeValue + return nil + } + } + + *v = PrivateLinkConnectionTypeEnum(value) + return nil +} + +// NewPrivateLinkConnectionTypeEnumFromValue returns a pointer to a valid PrivateLinkConnectionTypeEnum for the value passed as argument +func NewPrivateLinkConnectionTypeEnumFromValue(v string) *PrivateLinkConnectionTypeEnum { + ev := PrivateLinkConnectionTypeEnum(v) + return &ev +} + +// IsValid return true if the value is valid for the enum, false otherwise +func (v PrivateLinkConnectionTypeEnum) IsValid() bool { + for _, existing := range AllowedPrivateLinkConnectionTypeEnumEnumValues { + if existing == v { + return true + } + } + return false +} + +// Ptr returns reference to PrivateLinkConnectionType.Enum value +func (v PrivateLinkConnectionTypeEnum) Ptr() *PrivateLinkConnectionTypeEnum { + return &v +} + +type NullablePrivateLinkConnectionTypeEnum struct { + value *PrivateLinkConnectionTypeEnum + isSet bool +} + +func (v NullablePrivateLinkConnectionTypeEnum) Get() *PrivateLinkConnectionTypeEnum { + return v.value +} + +func (v *NullablePrivateLinkConnectionTypeEnum) Set(val *PrivateLinkConnectionTypeEnum) { + v.value = val + v.isSet = true +} + +func (v NullablePrivateLinkConnectionTypeEnum) IsSet() bool { + return v.isSet +} + +func (v *NullablePrivateLinkConnectionTypeEnum) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePrivateLinkConnectionTypeEnum(val *PrivateLinkConnectionTypeEnum) *NullablePrivateLinkConnectionTypeEnum { + return &NullablePrivateLinkConnectionTypeEnum{value: val, isSet: true} +} + +func (v NullablePrivateLinkConnectionTypeEnum) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePrivateLinkConnectionTypeEnum) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/model_status.go b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_status.go new file mode 100644 index 00000000..88072ed1 --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/model_status.go @@ -0,0 +1,229 @@ +/* +TiDB Cloud Serverless Private Link Connection Open API + +TiDB Cloud Serverless Private Link Connection Open API + +API version: v1beta1 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package privatelink + +import ( + "encoding/json" +) + +// checks if the Status type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &Status{} + +// Status struct for Status +type Status struct { + Code *int32 `json:"code,omitempty"` + Message *string `json:"message,omitempty"` + Details []Any `json:"details,omitempty"` + AdditionalProperties map[string]interface{} +} + +type _Status Status + +// NewStatus instantiates a new Status object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewStatus() *Status { + this := Status{} + return &this +} + +// NewStatusWithDefaults instantiates a new Status object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewStatusWithDefaults() *Status { + this := Status{} + return &this +} + +// GetCode returns the Code field value if set, zero value otherwise. +func (o *Status) GetCode() int32 { + if o == nil || IsNil(o.Code) { + var ret int32 + return ret + } + return *o.Code +} + +// GetCodeOk returns a tuple with the Code field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Status) GetCodeOk() (*int32, bool) { + if o == nil || IsNil(o.Code) { + return nil, false + } + return o.Code, true +} + +// HasCode returns a boolean if a field has been set. +func (o *Status) HasCode() bool { + if o != nil && !IsNil(o.Code) { + return true + } + + return false +} + +// SetCode gets a reference to the given int32 and assigns it to the Code field. +func (o *Status) SetCode(v int32) { + o.Code = &v +} + +// GetMessage returns the Message field value if set, zero value otherwise. +func (o *Status) GetMessage() string { + if o == nil || IsNil(o.Message) { + var ret string + return ret + } + return *o.Message +} + +// GetMessageOk returns a tuple with the Message field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Status) GetMessageOk() (*string, bool) { + if o == nil || IsNil(o.Message) { + return nil, false + } + return o.Message, true +} + +// HasMessage returns a boolean if a field has been set. +func (o *Status) HasMessage() bool { + if o != nil && !IsNil(o.Message) { + return true + } + + return false +} + +// SetMessage gets a reference to the given string and assigns it to the Message field. +func (o *Status) SetMessage(v string) { + o.Message = &v +} + +// GetDetails returns the Details field value if set, zero value otherwise. +func (o *Status) GetDetails() []Any { + if o == nil || IsNil(o.Details) { + var ret []Any + return ret + } + return o.Details +} + +// GetDetailsOk returns a tuple with the Details field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Status) GetDetailsOk() ([]Any, bool) { + if o == nil || IsNil(o.Details) { + return nil, false + } + return o.Details, true +} + +// HasDetails returns a boolean if a field has been set. +func (o *Status) HasDetails() bool { + if o != nil && !IsNil(o.Details) { + return true + } + + return false +} + +// SetDetails gets a reference to the given []Any and assigns it to the Details field. +func (o *Status) SetDetails(v []Any) { + o.Details = v +} + +func (o Status) MarshalJSON() ([]byte, error) { + toSerialize,err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o Status) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + if !IsNil(o.Code) { + toSerialize["code"] = o.Code + } + if !IsNil(o.Message) { + toSerialize["message"] = o.Message + } + if !IsNil(o.Details) { + toSerialize["details"] = o.Details + } + + for key, value := range o.AdditionalProperties { + toSerialize[key] = value + } + + return toSerialize, nil +} + +func (o *Status) UnmarshalJSON(data []byte) (err error) { + varStatus := _Status{} + + err = json.Unmarshal(data, &varStatus) + + if err != nil { + return err + } + + *o = Status(varStatus) + + additionalProperties := make(map[string]interface{}) + + if err = json.Unmarshal(data, &additionalProperties); err == nil { + delete(additionalProperties, "code") + delete(additionalProperties, "message") + delete(additionalProperties, "details") + o.AdditionalProperties = additionalProperties + } + + return err +} + +type NullableStatus struct { + value *Status + isSet bool +} + +func (v NullableStatus) Get() *Status { + return v.value +} + +func (v *NullableStatus) Set(val *Status) { + v.value = val + v.isSet = true +} + +func (v NullableStatus) IsSet() bool { + return v.isSet +} + +func (v *NullableStatus) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableStatus(val *Status) *NullableStatus { + return &NullableStatus{value: val, isSet: true} +} + +func (v NullableStatus) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableStatus) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/response.go b/pkg/tidbcloud/v1beta1/serverless/privatelink/response.go new file mode 100644 index 00000000..412bedb2 --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/response.go @@ -0,0 +1,47 @@ +/* +TiDB Cloud Serverless Private Link Connection Open API + +TiDB Cloud Serverless Private Link Connection Open API + +API version: v1beta1 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package privatelink + +import ( + "net/http" +) + +// APIResponse stores the API response returned by the server. +type APIResponse struct { + *http.Response `json:"-"` + Message string `json:"message,omitempty"` + // Operation is the name of the OpenAPI operation. + Operation string `json:"operation,omitempty"` + // RequestURL is the request URL. This value is always available, even if the + // embedded *http.Response is nil. + RequestURL string `json:"url,omitempty"` + // Method is the HTTP method used for the request. This value is always + // available, even if the embedded *http.Response is nil. + Method string `json:"method,omitempty"` + // Payload holds the contents of the response body (which may be nil or empty). + // This is provided here as the raw response.Body() reader will have already + // been drained. + Payload []byte `json:"-"` +} + +// NewAPIResponse returns a new APIResponse object. +func NewAPIResponse(r *http.Response) *APIResponse { + + response := &APIResponse{Response: r} + return response +} + +// NewAPIResponseWithError returns a new APIResponse object with the provided error message. +func NewAPIResponseWithError(errorMessage string) *APIResponse { + + response := &APIResponse{Message: errorMessage} + return response +} diff --git a/pkg/tidbcloud/v1beta1/serverless/privatelink/utils.go b/pkg/tidbcloud/v1beta1/serverless/privatelink/utils.go new file mode 100644 index 00000000..5da91335 --- /dev/null +++ b/pkg/tidbcloud/v1beta1/serverless/privatelink/utils.go @@ -0,0 +1,361 @@ +/* +TiDB Cloud Serverless Private Link Connection Open API + +TiDB Cloud Serverless Private Link Connection Open API + +API version: v1beta1 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package privatelink + +import ( + "bytes" + "encoding/json" + "fmt" + "reflect" + "time" +) + +// PtrBool is a helper routine that returns a pointer to given boolean value. +func PtrBool(v bool) *bool { return &v } + +// PtrInt is a helper routine that returns a pointer to given integer value. +func PtrInt(v int) *int { return &v } + +// PtrInt32 is a helper routine that returns a pointer to given integer value. +func PtrInt32(v int32) *int32 { return &v } + +// PtrInt64 is a helper routine that returns a pointer to given integer value. +func PtrInt64(v int64) *int64 { return &v } + +// PtrFloat32 is a helper routine that returns a pointer to given float value. +func PtrFloat32(v float32) *float32 { return &v } + +// PtrFloat64 is a helper routine that returns a pointer to given float value. +func PtrFloat64(v float64) *float64 { return &v } + +// PtrString is a helper routine that returns a pointer to given string value. +func PtrString(v string) *string { return &v } + +// PtrTime is helper routine that returns a pointer to given Time value. +func PtrTime(v time.Time) *time.Time { return &v } + +type NullableBool struct { + value *bool + isSet bool +} + +func (v NullableBool) Get() *bool { + return v.value +} + +func (v *NullableBool) Set(val *bool) { + v.value = val + v.isSet = true +} + +func (v NullableBool) IsSet() bool { + return v.isSet +} + +func (v *NullableBool) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableBool(val *bool) *NullableBool { + return &NullableBool{value: val, isSet: true} +} + +func (v NullableBool) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableBool) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + +type NullableInt struct { + value *int + isSet bool +} + +func (v NullableInt) Get() *int { + return v.value +} + +func (v *NullableInt) Set(val *int) { + v.value = val + v.isSet = true +} + +func (v NullableInt) IsSet() bool { + return v.isSet +} + +func (v *NullableInt) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInt(val *int) *NullableInt { + return &NullableInt{value: val, isSet: true} +} + +func (v NullableInt) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInt) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + +type NullableInt32 struct { + value *int32 + isSet bool +} + +func (v NullableInt32) Get() *int32 { + return v.value +} + +func (v *NullableInt32) Set(val *int32) { + v.value = val + v.isSet = true +} + +func (v NullableInt32) IsSet() bool { + return v.isSet +} + +func (v *NullableInt32) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInt32(val *int32) *NullableInt32 { + return &NullableInt32{value: val, isSet: true} +} + +func (v NullableInt32) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInt32) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + +type NullableInt64 struct { + value *int64 + isSet bool +} + +func (v NullableInt64) Get() *int64 { + return v.value +} + +func (v *NullableInt64) Set(val *int64) { + v.value = val + v.isSet = true +} + +func (v NullableInt64) IsSet() bool { + return v.isSet +} + +func (v *NullableInt64) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInt64(val *int64) *NullableInt64 { + return &NullableInt64{value: val, isSet: true} +} + +func (v NullableInt64) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInt64) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + +type NullableFloat32 struct { + value *float32 + isSet bool +} + +func (v NullableFloat32) Get() *float32 { + return v.value +} + +func (v *NullableFloat32) Set(val *float32) { + v.value = val + v.isSet = true +} + +func (v NullableFloat32) IsSet() bool { + return v.isSet +} + +func (v *NullableFloat32) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFloat32(val *float32) *NullableFloat32 { + return &NullableFloat32{value: val, isSet: true} +} + +func (v NullableFloat32) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFloat32) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + +type NullableFloat64 struct { + value *float64 + isSet bool +} + +func (v NullableFloat64) Get() *float64 { + return v.value +} + +func (v *NullableFloat64) Set(val *float64) { + v.value = val + v.isSet = true +} + +func (v NullableFloat64) IsSet() bool { + return v.isSet +} + +func (v *NullableFloat64) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFloat64(val *float64) *NullableFloat64 { + return &NullableFloat64{value: val, isSet: true} +} + +func (v NullableFloat64) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFloat64) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + +type NullableString struct { + value *string + isSet bool +} + +func (v NullableString) Get() *string { + return v.value +} + +func (v *NullableString) Set(val *string) { + v.value = val + v.isSet = true +} + +func (v NullableString) IsSet() bool { + return v.isSet +} + +func (v *NullableString) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableString(val *string) *NullableString { + return &NullableString{value: val, isSet: true} +} + +func (v NullableString) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableString) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + +type NullableTime struct { + value *time.Time + isSet bool +} + +func (v NullableTime) Get() *time.Time { + return v.value +} + +func (v *NullableTime) Set(val *time.Time) { + v.value = val + v.isSet = true +} + +func (v NullableTime) IsSet() bool { + return v.isSet +} + +func (v *NullableTime) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTime(val *time.Time) *NullableTime { + return &NullableTime{value: val, isSet: true} +} + +func (v NullableTime) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTime) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + +// IsNil checks if an input is nil +func IsNil(i interface{}) bool { + if i == nil { + return true + } + switch reflect.TypeOf(i).Kind() { + case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice: + return reflect.ValueOf(i).IsNil() + case reflect.Array: + return reflect.ValueOf(i).IsZero() + } + return false +} + +type MappedNullable interface { + ToMap() (map[string]interface{}, error) +} + +// A wrapper for strict JSON decoding +func newStrictDecoder(data []byte) *json.Decoder { + dec := json.NewDecoder(bytes.NewBuffer(data)) + dec.DisallowUnknownFields() + return dec +} + +// Prevent trying to import "fmt" +func reportError(format string, a ...interface{}) error { + return fmt.Errorf(format, a...) +} \ No newline at end of file