From 3868b326016d1c99e8c57454d6efc518c6e9c95e Mon Sep 17 00:00:00 2001 From: elkezza <47871727+elkezza@users.noreply.github.com> Date: Mon, 16 Sep 2024 00:19:29 +0200 Subject: [PATCH] instancepool: add min available support and Migrate to egoscale v3 (#629) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Added min available to both instance_pool_create.go and instance_pool_update.go and Migrate to egoscale v3k, however, there are some parts need to be reviewed like InstanceType in instance_pool_update.go which I was not sure how to be correctly implemented in egoscale v3. ## Checklist (For exoscale contributors) * [ ] Changelog updated (under *Unreleased* block) * [ ] Testing ## Testing I test to create new instance pool with min available 3 then I updated see the bellow output of the tests: ```bash go run . compute instance-pool create my-pool --size 4 --min-available 3 ✔ Creating Instance Pool "my-pool"... 24s ┼──────────────────────┼──────────────────────────────────────┼ │ INSTANCE POOL │ │ ┼──────────────────────┼──────────────────────────────────────┼ │ ID │ 9c52ad25-9898-48c1-be9a-f90ce13575c2 │ │ Name │ my-pool │ │ Description │ │ │ Instance Type │ standard.medium │ │ Template │ Linux Ubuntu 22.04 LTS 64-bit │ │ Zone │ at-vie-1 │ │ Anti-Affinity Groups │ n/a │ │ Security Groups │ n/a │ │ Private Networks │ n/a │ │ Elastic IPs │ n/a │ │ IPv6 │ false │ │ SSH Key │ - │ │ Size │ 4 │ │ Disk Size │ 50 GiB │ │ Instance Prefix │ pool │ │ State │ scaling-up │ │ Labels │ n/a │ │ Instances │ pool-9c52a-dqhmy │ │ │ pool-9c52a-pkwqs │ │ │ pool-9c52a-iepbx │ │ │ pool-9c52a-staqe │ ┼──────────────────────┼──────────────────────────────────────┼ go run . compute instance-pool update my-pool --min-available 4 ✔ Updating Instance Pool "my-pool"... 0s ┼──────────────────────┼──────────────────────────────────────┼ │ INSTANCE POOL │ │ ┼──────────────────────┼──────────────────────────────────────┼ │ ID │ 9c52ad25-9898-48c1-be9a-f90ce13575c2 │ │ Name │ my-pool │ │ Description │ │ │ Instance Type │ standard.medium │ │ Template │ Linux Ubuntu 22.04 LTS 64-bit │ │ Zone │ at-vie-1 │ │ Anti-Affinity Groups │ n/a │ │ Security Groups │ n/a │ │ Private Networks │ n/a │ │ Elastic IPs │ n/a │ │ IPv6 │ false │ │ SSH Key │ - │ │ Size │ 4 │ │ Disk Size │ 50 GiB │ │ Instance Prefix │ pool │ │ State │ updating │ │ Labels │ n/a │ │ Instances │ pool-9c52a-dqhmy │ │ │ pool-9c52a-pkwqs │ │ │ pool-9c52a-iepbx │ │ │ pool-9c52a-staqe │ ┼──────────────────────┼──────────────────────────────────────┼ ``` --------- Signed-off-by: Pierre-Emmanuel Jacquier <15922119+pierre-emmanuelJ@users.noreply.github.com> Co-authored-by: Pierre-Emmanuel Jacquier <15922119+pierre-emmanuelJ@users.noreply.github.com> --- CHANGELOG.md | 3 + cmd/instance_pool_create.go | 157 ++++++++----- cmd/instance_pool_update.go | 153 ++++++++----- go.mod | 10 +- go.sum | 11 +- .../github.com/exoscale/egoscale/v3/README.md | 67 ++++++ vendor/github.com/exoscale/egoscale/v3/api.go | 3 +- .../github.com/exoscale/egoscale/v3/client.go | 16 +- .../exoscale/egoscale/v3/operations.go | 187 ++++++++++++---- .../exoscale/egoscale/v3/schemas.go | 7 + .../exoscale/egoscale/v3/version.go | 2 +- vendor/github.com/stretchr/objx/README.md | 2 +- vendor/github.com/stretchr/objx/Taskfile.yml | 2 +- .../testify/assert/assertion_compare.go | 28 ++- .../assert/assertion_compare_can_convert.go | 16 -- .../assert/assertion_compare_legacy.go | 16 -- .../testify/assert/assertion_format.go | 32 ++- .../testify/assert/assertion_forward.go | 59 +++-- .../stretchr/testify/assert/assertions.go | 207 +++++++++++------- .../testify/assert/http_assertions.go | 27 ++- .../github.com/stretchr/testify/mock/mock.go | 129 ++++++----- .../stretchr/testify/require/require.go | 65 ++++-- .../testify/require/require_forward.go | 59 +++-- vendor/modules.txt | 12 +- 24 files changed, 853 insertions(+), 417 deletions(-) delete mode 100644 vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go delete mode 100644 vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 359e3479..6ba528db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## Unreleased +### Features +- instance pool: added min-available flag to exo compute #629 + ## 1.79.1 ### Improvements diff --git a/cmd/instance_pool_create.go b/cmd/instance_pool_create.go index d0620521..cf9859e7 100644 --- a/cmd/instance_pool_create.go +++ b/cmd/instance_pool_create.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "os" "strings" "github.com/spf13/cobra" @@ -11,8 +12,7 @@ import ( "github.com/exoscale/cli/pkg/output" "github.com/exoscale/cli/pkg/userdata" "github.com/exoscale/cli/utils" - egoscale "github.com/exoscale/egoscale/v2" - exoapi "github.com/exoscale/egoscale/v2/api" + v3 "github.com/exoscale/egoscale/v3" ) type instancePoolCreateCmd struct { @@ -33,13 +33,14 @@ type instancePoolCreateCmd struct { InstancePrefix string `cli-usage:"string to prefix managed Compute instances names with"` InstanceType string `cli-usage:"managed Compute instances type (format: [FAMILY.]SIZE)"` Labels map[string]string `cli-flag:"label" cli-usage:"Instance Pool label (format: key=value)"` + MinAvailable int64 `cli-usage:"Minimum number of running Instances"` PrivateNetworks []string `cli-flag:"private-network" cli-usage:"managed Compute instances Private Network NAME|ID (can be specified multiple times)"` SSHKey string `cli-flag:"ssh-key" cli-usage:"SSH key to deploy on managed Compute instances"` SecurityGroups []string `cli-flag:"security-group" cli-short:"s" cli-usage:"managed Compute instances Security Group NAME|ID (can be specified multiple times)"` Size int64 `cli-usage:"Instance Pool size"` Template string `cli-short:"t" cli-usage:"managed Compute instances template NAME|ID"` TemplateVisibility string `cli-usage:"instance template visibility (public|private)"` - Zone string `cli-short:"z" cli-usage:"Instance Pool zone"` + Zone v3.ZoneName `cli-short:"z" cli-usage:"Instance Pool zone"` } func (c *instancePoolCreateCmd) cmdAliases() []string { return gCreateAlias } @@ -61,91 +62,132 @@ func (c *instancePoolCreateCmd) cmdPreRun(cmd *cobra.Command, args []string) err } func (c *instancePoolCreateCmd) cmdRun(_ *cobra.Command, _ []string) error { - instancePool := &egoscale.InstancePool{ - Description: utils.NonEmptyStringPtr(c.Description), - DiskSize: &c.DiskSize, - IPv6Enabled: &c.IPv6, - InstancePrefix: utils.NonEmptyStringPtr(c.InstancePrefix), - Labels: func() (v *map[string]string) { - if len(c.Labels) > 0 { - return &c.Labels - } - return - }(), - Name: &c.Name, - SSHKey: utils.NonEmptyStringPtr(c.SSHKey), - Size: &c.Size, + + ctx := gContext + client, err := switchClientZoneV3(ctx, globalstate.EgoscaleV3Client, c.Zone) + if err != nil { + return err } - ctx := exoapi.WithEndpoint(gContext, exoapi.NewReqEndpoint(account.CurrentAccount.Environment, c.Zone)) + sshKey := &v3.SSHKey{Name: c.SSHKey} + + instancePoolReq := v3.CreateInstancePoolRequest{ + Description: c.Description, + DiskSize: c.DiskSize, + Ipv6Enabled: &c.IPv6, + InstancePrefix: c.InstancePrefix, + Labels: c.Labels, + MinAvailable: c.MinAvailable, + Name: c.Name, + SSHKey: sshKey, + Size: c.Size, + } if l := len(c.AntiAffinityGroups); l > 0 { - antiAffinityGroupIDs := make([]string, l) + instancePoolReq.AntiAffinityGroups = make([]v3.AntiAffinityGroup, l) + af, err := client.ListAntiAffinityGroups(ctx) + if err != nil { + return fmt.Errorf("error listing Anti-Affinity Group: %w", err) + } for i := range c.AntiAffinityGroups { - antiAffinityGroup, err := globalstate.EgoscaleClient.FindAntiAffinityGroup(ctx, c.Zone, c.AntiAffinityGroups[i]) + antiAffinityGroup, err := af.FindAntiAffinityGroup(c.AntiAffinityGroups[i]) if err != nil { return fmt.Errorf("error retrieving Anti-Affinity Group: %w", err) } - antiAffinityGroupIDs[i] = *antiAffinityGroup.ID + instancePoolReq.AntiAffinityGroups[i] = v3.AntiAffinityGroup{ID: antiAffinityGroup.ID} } - instancePool.AntiAffinityGroupIDs = &antiAffinityGroupIDs } if c.DeployTarget != "" { - deployTarget, err := globalstate.EgoscaleClient.FindDeployTarget(ctx, c.Zone, c.DeployTarget) + targets, err := client.ListDeployTargets(ctx) + if err != nil { + return fmt.Errorf("error listing Deploy Target: %w", err) + } + deployTarget, err := targets.FindDeployTarget(c.DeployTarget) if err != nil { return fmt.Errorf("error retrieving Deploy Target: %w", err) } - instancePool.DeployTargetID = deployTarget.ID + instancePoolReq.DeployTarget = &v3.DeployTarget{ID: deployTarget.ID} } if l := len(c.ElasticIPs); l > 0 { - elasticIPIDs := make([]string, l) - for i := range c.ElasticIPs { - elasticIP, err := globalstate.EgoscaleClient.FindElasticIP(ctx, c.Zone, c.ElasticIPs[i]) + result := []v3.ElasticIP{} + eipList, err := client.ListElasticIPS(ctx) + if err != nil { + return fmt.Errorf("error listing Elastic IP: %w", err) + } + for _, input := range c.ElasticIPs { + eip, err := eipList.FindElasticIP(input) if err != nil { - return fmt.Errorf("error retrieving Elastic IP: %w", err) + fmt.Fprintf(os.Stderr, "warning: Elastic IP %s not found.\n", input) + continue } - elasticIPIDs[i] = *elasticIP.ID + + result = append(result, v3.ElasticIP{ID: eip.ID}) + } + + if len(result) != 0 { + instancePoolReq.ElasticIPS = result } - instancePool.ElasticIPIDs = &elasticIPIDs } - instanceType, err := globalstate.EgoscaleClient.FindInstanceType(ctx, c.Zone, c.InstanceType) + instanceTypes, err := client.ListInstanceTypes(ctx) if err != nil { - return fmt.Errorf("error retrieving instance type: %w", err) + return fmt.Errorf("error listing instance type: %w", err) + } + + // c.InstanceType is never empty + instanceType := utils.ParseInstanceType(c.InstanceType) + for i, it := range instanceTypes.InstanceTypes { + if it.Family == instanceType.Family && it.Size == instanceType.Size { + instancePoolReq.InstanceType = &instanceTypes.InstanceTypes[i] + break + } + } + if instancePoolReq.InstanceType == nil { + return fmt.Errorf("error retrieving instance type %s: not found", c.InstanceType) } - instancePool.InstanceTypeID = instanceType.ID + privateNetworks := make([]v3.PrivateNetwork, len(c.PrivateNetworks)) if l := len(c.PrivateNetworks); l > 0 { - privateNetworkIDs := make([]string, l) + pNetworks, err := client.ListPrivateNetworks(ctx) + if err != nil { + return fmt.Errorf("error listing Private Network: %w", err) + } + for i := range c.PrivateNetworks { - privateNetwork, err := globalstate.EgoscaleClient.FindPrivateNetwork(ctx, c.Zone, c.PrivateNetworks[i]) + privateNetwork, err := pNetworks.FindPrivateNetwork(c.PrivateNetworks[i]) if err != nil { return fmt.Errorf("error retrieving Private Network: %w", err) } - privateNetworkIDs[i] = *privateNetwork.ID + privateNetworks[i] = privateNetwork } - instancePool.PrivateNetworkIDs = &privateNetworkIDs } if l := len(c.SecurityGroups); l > 0 { - securityGroupIDs := make([]string, l) + sgs, err := client.ListSecurityGroups(ctx) + if err != nil { + return fmt.Errorf("error listing Security Group: %w", err) + } + instancePoolReq.SecurityGroups = make([]v3.SecurityGroup, l) for i := range c.SecurityGroups { - securityGroup, err := globalstate.EgoscaleClient.FindSecurityGroup(ctx, c.Zone, c.SecurityGroups[i]) + securityGroup, err := sgs.FindSecurityGroup(c.SecurityGroups[i]) if err != nil { return fmt.Errorf("error retrieving Security Group: %w", err) } - securityGroupIDs[i] = *securityGroup.ID + instancePoolReq.SecurityGroups[i] = v3.SecurityGroup{ID: securityGroup.ID} } - instancePool.SecurityGroupIDs = &securityGroupIDs } - if instancePool.SSHKey == nil && account.CurrentAccount.DefaultSSHKey != "" { - instancePool.SSHKey = &account.CurrentAccount.DefaultSSHKey + if instancePoolReq.SSHKey == nil && account.CurrentAccount.DefaultSSHKey != "" { + instancePoolReq.SSHKey = &v3.SSHKey{Name: account.CurrentAccount.DefaultSSHKey} } - template, err := globalstate.EgoscaleClient.FindTemplate(ctx, c.Zone, c.Template, c.TemplateVisibility) + templates, err := client.ListTemplates(ctx, v3.ListTemplatesWithVisibility(v3.ListTemplatesVisibility(c.TemplateVisibility))) + if err != nil { + return fmt.Errorf("error listing template with visibility %q: %w", c.TemplateVisibility, err) + } + template, err := templates.FindTemplate(c.Template) if err != nil { return fmt.Errorf( "no template %q found with visibility %s in zone %s", @@ -154,18 +196,33 @@ func (c *instancePoolCreateCmd) cmdRun(_ *cobra.Command, _ []string) error { c.Zone, ) } - instancePool.TemplateID = template.ID + instancePoolReq.Template = &v3.Template{ID: template.ID} if c.CloudInitFile != "" { userData, err := userdata.GetUserDataFromFile(c.CloudInitFile, c.CloudInitCompress) if err != nil { return fmt.Errorf("error parsing cloud-init user data: %w", err) } - instancePool.UserData = &userData + instancePoolReq.UserData = userData } + var instancePoolID v3.UUID + decorateAsyncOperation(fmt.Sprintf("Creating Instance Pool %q...", c.Name), func() { - instancePool, err = globalstate.EgoscaleClient.CreateInstancePool(ctx, c.Zone, instancePool) + var op *v3.Operation + op, err = client.CreateInstancePool(ctx, instancePoolReq) + if err != nil { + return + } + + op, err = client.Wait(ctx, op, v3.OperationStateSuccess) + if err != nil { + return + } + if op.Reference != nil { + instancePoolID = op.Reference.ID + } + }) if err != nil { return err @@ -174,8 +231,9 @@ func (c *instancePoolCreateCmd) cmdRun(_ *cobra.Command, _ []string) error { if !globalstate.Quiet { return (&instancePoolShowCmd{ cliCommandSettings: c.cliCommandSettings, - Zone: c.Zone, - InstancePool: *instancePool.ID, + InstancePool: instancePoolID.String(), + // TODO migrate instance_pool_show to v3 to pass v3.ZoneName + Zone: string(c.Zone), }).cmdRun(nil, nil) } @@ -189,6 +247,7 @@ func init() { DiskSize: 50, InstanceType: fmt.Sprintf("%s.%s", defaultInstanceTypeFamily, defaultInstanceType), Size: 1, + MinAvailable: 0, TemplateVisibility: defaultTemplateVisibility, })) } diff --git a/cmd/instance_pool_update.go b/cmd/instance_pool_update.go index ce8ab91c..f52db4a5 100644 --- a/cmd/instance_pool_update.go +++ b/cmd/instance_pool_update.go @@ -1,17 +1,17 @@ package cmd import ( - "errors" "fmt" + "os" "strings" "github.com/spf13/cobra" - "github.com/exoscale/cli/pkg/account" "github.com/exoscale/cli/pkg/globalstate" "github.com/exoscale/cli/pkg/output" "github.com/exoscale/cli/pkg/userdata" - exoapi "github.com/exoscale/egoscale/v2/api" + "github.com/exoscale/cli/utils" + v3 "github.com/exoscale/egoscale/v3" ) type instancePoolUpdateCmd struct { @@ -32,13 +32,14 @@ type instancePoolUpdateCmd struct { InstancePrefix string `cli-usage:"string to prefix managed Compute instances names with"` InstanceType string `cli-usage:"managed Compute instances type (format: [FAMILY.]SIZE)"` Labels map[string]string `cli-flag:"label" cli-usage:"Instance Pool label (format: key=value)"` + MinAvailable int64 `cli-usage:"Minimum number of running Instances"` Name string `cli-short:"n" cli-usage:"Instance Pool name"` PrivateNetworks []string `cli-flag:"private-network" cli-usage:"managed Compute instances Private Network NAME|ID (can be specified multiple times)"` SSHKey string `cli-flag:"ssh-key" cli-usage:"SSH key to deploy on managed Compute instances"` SecurityGroups []string `cli-flag:"security-group" cli-short:"s" cli-usage:"managed Compute instances Security Group NAME|ID (can be specified multiple times)"` Template string `cli-short:"t" cli-usage:"managed Compute instances template NAME|ID"` TemplateVisibility string `cli-usage:"instance template visibility (public|private)"` - Zone string `cli-short:"z" cli-usage:"Instance Pool zone"` + Zone v3.ZoneName `cli-short:"z" cli-usage:"Instance Pool zone"` } func (c *instancePoolUpdateCmd) cmdAliases() []string { return nil } @@ -61,123 +62,174 @@ func (c *instancePoolUpdateCmd) cmdPreRun(cmd *cobra.Command, args []string) err func (c *instancePoolUpdateCmd) cmdRun(cmd *cobra.Command, _ []string) error { //nolint:gocyclo var updated bool - ctx := exoapi.WithEndpoint(gContext, exoapi.NewReqEndpoint(account.CurrentAccount.Environment, c.Zone)) + ctx := gContext + client, err := switchClientZoneV3(ctx, globalstate.EgoscaleV3Client, c.Zone) + if err != nil { + return err + } - instancePool, err := globalstate.EgoscaleClient.FindInstancePool(ctx, c.Zone, c.InstancePool) + instancePools, err := client.ListInstancePools(ctx) if err != nil { - if errors.Is(err, exoapi.ErrNotFound) { - return fmt.Errorf("resource not found in zone %q", c.Zone) - } return err } + instancePool, err := instancePools.FindInstancePool(c.InstancePool) + if err != nil { + return err + } + updateReq := v3.UpdateInstancePoolRequest{} + if cmd.Flags().Changed(mustCLICommandFlagName(c, &c.AntiAffinityGroups)) { - antiAffinityGroupIDs := make([]string, len(c.AntiAffinityGroups)) - for i, v := range c.AntiAffinityGroups { - antiAffinityGroup, err := globalstate.EgoscaleClient.FindAntiAffinityGroup(ctx, c.Zone, v) + updateReq.AntiAffinityGroups = make([]v3.AntiAffinityGroup, len(c.AntiAffinityGroups)) + af, err := client.ListAntiAffinityGroups(ctx) + if err != nil { + return fmt.Errorf("error listing Anti-Affinity Group: %w", err) + } + for i := range c.AntiAffinityGroups { + antiAffinityGroup, err := af.FindAntiAffinityGroup(c.AntiAffinityGroups[i]) if err != nil { return fmt.Errorf("error retrieving Anti-Affinity Group: %w", err) } - antiAffinityGroupIDs[i] = *antiAffinityGroup.ID + updateReq.AntiAffinityGroups[i] = v3.AntiAffinityGroup{ID: antiAffinityGroup.ID} } - instancePool.AntiAffinityGroupIDs = &antiAffinityGroupIDs updated = true } if cmd.Flags().Changed(mustCLICommandFlagName(c, &c.DeployTarget)) { - deployTarget, err := globalstate.EgoscaleClient.FindDeployTarget(ctx, c.Zone, c.DeployTarget) + targets, err := client.ListDeployTargets(ctx) + if err != nil { + return fmt.Errorf("error listing Deploy Target: %w", err) + } + deployTarget, err := targets.FindDeployTarget(c.DeployTarget) if err != nil { return fmt.Errorf("error retrieving Deploy Target: %w", err) } - instancePool.DeployTargetID = deployTarget.ID + updateReq.DeployTarget = &v3.DeployTarget{ID: deployTarget.ID} updated = true } if cmd.Flags().Changed(mustCLICommandFlagName(c, &c.Description)) { - instancePool.Description = &c.Description + updateReq.Description = c.Description updated = true } if cmd.Flags().Changed(mustCLICommandFlagName(c, &c.DiskSize)) { - instancePool.DiskSize = &c.DiskSize + updateReq.DiskSize = c.DiskSize updated = true } if cmd.Flags().Changed(mustCLICommandFlagName(c, &c.ElasticIPs)) { - elasticIPIDs := make([]string, len(c.ElasticIPs)) - for i, v := range c.ElasticIPs { - elasticIP, err := globalstate.EgoscaleClient.FindElasticIP(ctx, c.Zone, v) + result := []v3.ElasticIP{} + eipList, err := client.ListElasticIPS(ctx) + if err != nil { + return fmt.Errorf("error listing Elastic IP: %w", err) + } + for _, input := range c.ElasticIPs { + eip, err := eipList.FindElasticIP(input) if err != nil { - return fmt.Errorf("error retrieving Elastic IP: %w", err) + fmt.Fprintf(os.Stderr, "warning: Elastic IP %s not found.\n", input) + continue } - elasticIPIDs[i] = *elasticIP.ID + + result = append(result, v3.ElasticIP{ID: eip.ID}) + } + + if len(result) != 0 { + updateReq.ElasticIPS = result + updated = true } - instancePool.ElasticIPIDs = &elasticIPIDs - updated = true } if cmd.Flags().Changed(mustCLICommandFlagName(c, &c.InstancePrefix)) { - instancePool.InstancePrefix = &c.InstancePrefix + updateReq.InstancePrefix = &c.InstancePrefix updated = true } if cmd.Flags().Changed(mustCLICommandFlagName(c, &c.IPv6)) { - instancePool.IPv6Enabled = &c.IPv6 + updateReq.Ipv6Enabled = &c.IPv6 updated = true } if cmd.Flags().Changed(mustCLICommandFlagName(c, &c.Labels)) { - instancePool.Labels = &c.Labels + updateReq.Labels = convertIfSpecialEmptyMap(c.Labels) + updated = true + } + + if cmd.Flags().Changed(mustCLICommandFlagName(c, &c.MinAvailable)) { + updateReq.MinAvailable = &c.MinAvailable updated = true } if cmd.Flags().Changed(mustCLICommandFlagName(c, &c.Name)) { - instancePool.Name = &c.Name + updateReq.Name = c.Name updated = true } if cmd.Flags().Changed(mustCLICommandFlagName(c, &c.PrivateNetworks)) { - privateNetworkIDs := make([]string, len(c.PrivateNetworks)) - for i, v := range c.PrivateNetworks { - privateNetwork, err := globalstate.EgoscaleClient.FindPrivateNetwork(ctx, c.Zone, v) + updateReq.PrivateNetworks = make([]v3.PrivateNetwork, len(c.PrivateNetworks)) + pn, err := client.ListPrivateNetworks(ctx) + if err != nil { + return fmt.Errorf("error listing Elastic IP: %w", err) + } + for i := range c.PrivateNetworks { + privateNetwork, err := pn.FindPrivateNetwork(c.PrivateNetworks[i]) if err != nil { return fmt.Errorf("error retrieving Private Network: %w", err) } - privateNetworkIDs[i] = *privateNetwork.ID + updateReq.PrivateNetworks[i] = v3.PrivateNetwork{ID: privateNetwork.ID} } - instancePool.PrivateNetworkIDs = &privateNetworkIDs updated = true } if cmd.Flags().Changed(mustCLICommandFlagName(c, &c.SecurityGroups)) { - securityGroupIDs := make([]string, len(c.SecurityGroups)) - for i, v := range c.SecurityGroups { - securityGroup, err := globalstate.EgoscaleClient.FindSecurityGroup(ctx, c.Zone, v) + sgs, err := client.ListSecurityGroups(ctx) + + if err != nil { + return fmt.Errorf("error listing Security Group: %w", err) + } + updateReq.SecurityGroups = make([]v3.SecurityGroup, len(c.SecurityGroups)) + + for i := range c.SecurityGroups { + securityGroup, err := sgs.FindSecurityGroup(c.SecurityGroups[i]) if err != nil { return fmt.Errorf("error retrieving Security Group: %w", err) } - securityGroupIDs[i] = *securityGroup.ID + updateReq.SecurityGroups[i] = v3.SecurityGroup{ID: securityGroup.ID} } - instancePool.SecurityGroupIDs = &securityGroupIDs updated = true } if cmd.Flags().Changed(mustCLICommandFlagName(c, &c.InstanceType)) { - instanceType, err := globalstate.EgoscaleClient.FindInstanceType(ctx, c.Zone, c.InstanceType) + instanceTypes, err := client.ListInstanceTypes(ctx) if err != nil { - return fmt.Errorf("error retrieving instance type: %w", err) + return fmt.Errorf("error listing instance type: %w", err) } - instancePool.InstanceTypeID = instanceType.ID + + instanceType := utils.ParseInstanceType(c.InstanceType) + for i, it := range instanceTypes.InstanceTypes { + if it.Family == instanceType.Family && it.Size == instanceType.Size { + updateReq.InstanceType = &v3.InstanceType{ID: instanceTypes.InstanceTypes[i].ID} + break + } + } + if updateReq.InstanceType == nil { + return fmt.Errorf("error retrieving instance type %s: not found", c.InstanceType) + } + updated = true } if cmd.Flags().Changed(mustCLICommandFlagName(c, &c.SSHKey)) { - instancePool.SSHKey = &c.SSHKey + updateReq.SSHKey = &v3.SSHKey{Name: c.SSHKey} updated = true } if cmd.Flags().Changed(mustCLICommandFlagName(c, &c.Template)) { - template, err := globalstate.EgoscaleClient.FindTemplate(ctx, c.Zone, c.Template, c.TemplateVisibility) + templates, err := client.ListTemplates(ctx, v3.ListTemplatesWithVisibility(v3.ListTemplatesVisibility(c.TemplateVisibility))) + if err != nil { + return fmt.Errorf("error listing template with visibility %q: %w", c.TemplateVisibility, err) + } + template, err := templates.FindTemplate(c.Template) if err != nil { return fmt.Errorf( "no template %q found with visibility %s in zone %s", @@ -186,7 +238,7 @@ func (c *instancePoolUpdateCmd) cmdRun(cmd *cobra.Command, _ []string) error { / c.Zone, ) } - instancePool.TemplateID = template.ID + updateReq.Template = &template updated = true } @@ -195,15 +247,14 @@ func (c *instancePoolUpdateCmd) cmdRun(cmd *cobra.Command, _ []string) error { / if err != nil { return fmt.Errorf("error parsing cloud-init user data: %w", err) } - instancePool.UserData = &userData + updateReq.UserData = &userData updated = true } if updated { decorateAsyncOperation(fmt.Sprintf("Updating Instance Pool %q...", c.InstancePool), func() { - if err = globalstate.EgoscaleClient.UpdateInstancePool(ctx, c.Zone, instancePool); err != nil { - return - } + _, updateErr := client.UpdateInstancePool(ctx, instancePool.ID, updateReq) + err = updateErr }) if err != nil { return err @@ -213,8 +264,8 @@ func (c *instancePoolUpdateCmd) cmdRun(cmd *cobra.Command, _ []string) error { / if !globalstate.Quiet { return (&instancePoolShowCmd{ cliCommandSettings: c.cliCommandSettings, - Zone: c.Zone, - InstancePool: *instancePool.ID, + InstancePool: instancePool.ID.String(), + Zone: string(c.Zone), }).cmdRun(nil, nil) } diff --git a/go.mod b/go.mod index 6349fc74..e1553ea0 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/aws/smithy-go v1.1.0 github.com/dustin/go-humanize v1.0.1 github.com/exoscale/egoscale v0.102.4 - github.com/exoscale/egoscale/v3 v3.1.2 + github.com/exoscale/egoscale/v3 v3.1.4 github.com/exoscale/openapi-cli-generator v1.1.0 github.com/fatih/camelcase v1.0.0 github.com/google/uuid v1.4.0 @@ -27,7 +27,7 @@ require ( github.com/spf13/cobra v1.3.0 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.18.2 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 github.com/vbauerster/mpb/v4 v4.12.2 github.com/withfig/autocomplete-tools/integrations/cobra v1.2.1 github.com/xeipuuv/gojsonschema v1.2.0 @@ -132,7 +132,7 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect - github.com/stretchr/objx v0.5.1 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/tdewolff/minify/v2 v2.12.8 // indirect github.com/tdewolff/parse/v2 v2.6.7 // indirect @@ -161,4 +161,6 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -go 1.22 +go 1.23.0 + +toolchain go1.23.1 diff --git a/go.sum b/go.sum index 4d28a3b6..8acb30c3 100644 --- a/go.sum +++ b/go.sum @@ -197,8 +197,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= github.com/exoscale/egoscale v0.102.4 h1:GBKsZMIOzwBfSu+4ZmWka3Ejf2JLiaBDHp4CQUgvp2E= github.com/exoscale/egoscale v0.102.4/go.mod h1:ROSmPtle0wvf91iLZb09++N/9BH2Jo9XxIpAEumvocA= -github.com/exoscale/egoscale/v3 v3.1.2 h1:yhSN5mKR32U9Dte7Gbz3OwzgDCQl38E8vsNc8gD60Kc= -github.com/exoscale/egoscale/v3 v3.1.2/go.mod h1:lPsza7G+giSxdzvzaHSEcjEAYz/YTiu2bEEha9KVAc4= +github.com/exoscale/egoscale/v3 v3.1.4 h1:xpKEGX58GIC3CHTsJdRB5+ij74DmgWPts/n8OrItJ6s= +github.com/exoscale/egoscale/v3 v3.1.4/go.mod h1:GHKucK/J26v8PGWztGdhxWNMjrjG9PbelxKCJ4YI11Q= github.com/exoscale/openapi-cli-generator v1.1.0 h1:fYjmPqHR5vxlOBrbvde7eo7bISNQIFxsGn4A5/acwKA= github.com/exoscale/openapi-cli-generator v1.1.0/go.mod h1:TZBnbT7f3hJ5ImyUphJwRM+X5xF/zCQZ6o8a42gQeTs= github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= @@ -612,8 +612,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.1 h1:4VhoImhV/Bm0ToFkXFi8hXNXwpDRZ/ynw3amt82mzq0= -github.com/stretchr/objx v0.5.1/go.mod h1:/iHQpkQwBD6DLUmQ4pE+s1TXdob1mORJ4/UFdrifcy0= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -624,8 +624,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= diff --git a/vendor/github.com/exoscale/egoscale/v3/README.md b/vendor/github.com/exoscale/egoscale/v3/README.md index cae793dc..4c39f8f8 100644 --- a/vendor/github.com/exoscale/egoscale/v3/README.md +++ b/vendor/github.com/exoscale/egoscale/v3/README.md @@ -70,6 +70,23 @@ func main() { } ``` +### Findable + +Most of the list request `ListX()` return a type containing the list of the resource requested and a method `FindX()` to be able to retrieve a resource by its `name` or `id` most of the time. + +```Golang +pools, err := client.ListInstancePools(ctx) +if err != nil { + log.Fatal(err) +} +pool, err := pools.FindInstancePool("my-pool-example") +if err != nil { + log.Fatal(err) +} + +fmt.Println(pool.Name) +``` + ## Development ### Generate Egoscale v3 @@ -87,3 +104,53 @@ GENERATOR_DEBUG=client make generate > test/client.go GENERATOR_DEBUG=schemas make generate > test/schemas.go GENERATOR_DEBUG=operations make generate > test/operations.go ``` + +### OpenAPI Extensions + +The generator support two types of extension: +- `x-go-type` to specify a type definition in Golang. + + OpenAPI Spec + ```yaml + api-endpoint: + type: string + x-go-type: Endpoint + description: Zone API endpoint + ``` + Generated code + ```Golang + type Endpoint string + + type Zone struct { + APIEndpoint Endpoint // Here is the generated type definition. + ... + } + ``` +- `x-go-findable` to specify which fields in the findable resource to fetch + OpenAPI Spec + ```yaml + elastic-ip: + type: object + properties: + id: + type: string + x-go-findable: "1" + description: Elastic IP ID + ip: + type: string + x-go-findable: "2" + description: Elastic IP address + ``` + Generated code + ```Golang + // FindElasticIP attempts to find an ElasticIP by idOrIP. + func (l ListElasticIPSResponse) FindElasticIP(idOrIP string) (ElasticIP, error) { + for i, elem := range l.ElasticIPS { + if string(elem.ID) == idOrIP || string(elem.IP) == idOrIP { + return l.ElasticIPS[i], nil + } + } + + return ElasticIP{}, fmt.Errorf("%q not found in ListElasticIPSResponse: %w", idOrIP, ErrNotFound) + } + ``` diff --git a/vendor/github.com/exoscale/egoscale/v3/api.go b/vendor/github.com/exoscale/egoscale/v3/api.go index 5a569194..cab17b4f 100644 --- a/vendor/github.com/exoscale/egoscale/v3/api.go +++ b/vendor/github.com/exoscale/egoscale/v3/api.go @@ -7,6 +7,7 @@ import ( "crypto/sha256" "encoding/base64" "encoding/json" + "errors" "fmt" "io" "net/http" @@ -133,7 +134,7 @@ func (c Client) Validate(s any) error { } else { errorString += fmt.Sprintf("'%s=%v'", e.ActualTag(), e.Param()) } - return fmt.Errorf(errorString) + return errors.New(errorString) } return err diff --git a/vendor/github.com/exoscale/egoscale/v3/client.go b/vendor/github.com/exoscale/egoscale/v3/client.go index 804a3780..a333d69a 100644 --- a/vendor/github.com/exoscale/egoscale/v3/client.go +++ b/vendor/github.com/exoscale/egoscale/v3/client.go @@ -30,26 +30,26 @@ const ( func (c Client) GetZoneName(ctx context.Context, endpoint Endpoint) (ZoneName, error) { resp, err := c.ListZones(ctx) if err != nil { - return "", fmt.Errorf("get zone name: %w", err) + return "", fmt.Errorf("get zone name: list zones: %w", err) } - for _, zone := range resp.Zones { - if zone.APIEndpoint == endpoint { - return zone.Name, nil - } + + zone, err := resp.FindZone(string(endpoint)) + if err != nil { + return "", fmt.Errorf("get zone name: find zone: %w", err) } - return "", fmt.Errorf("get zone name: no matching zone for %s", endpoint) + return zone.Name, nil } func (c Client) GetZoneAPIEndpoint(ctx context.Context, zoneName ZoneName) (Endpoint, error) { resp, err := c.ListZones(ctx) if err != nil { - return "", fmt.Errorf("get zone api endpoint: %w", err) + return "", fmt.Errorf("get zone api endpoint: list zones: %w", err) } zone, err := resp.FindZone(string(zoneName)) if err != nil { - return "", fmt.Errorf("get zone api endpoint: %w", err) + return "", fmt.Errorf("get zone api endpoint: find zone: %w", err) } return zone.APIEndpoint, nil diff --git a/vendor/github.com/exoscale/egoscale/v3/operations.go b/vendor/github.com/exoscale/egoscale/v3/operations.go index d7f02d6f..c5cbfbd3 100644 --- a/vendor/github.com/exoscale/egoscale/v3/operations.go +++ b/vendor/github.com/exoscale/egoscale/v3/operations.go @@ -19,7 +19,7 @@ type ListAntiAffinityGroupsResponse struct { // FindAntiAffinityGroup attempts to find an AntiAffinityGroup by nameOrID. func (l ListAntiAffinityGroupsResponse) FindAntiAffinityGroup(nameOrID string) (AntiAffinityGroup, error) { for i, elem := range l.AntiAffinityGroups { - if string(elem.Name) == nameOrID || elem.ID.String() == nameOrID { + if string(elem.Name) == nameOrID || string(elem.ID) == nameOrID { return l.AntiAffinityGroups[i], nil } } @@ -217,15 +217,15 @@ type ListAPIKeysResponse struct { APIKeys []IAMAPIKey `json:"api-keys,omitempty"` } -// FindIAMAPIKey attempts to find an IAMAPIKey by name. -func (l ListAPIKeysResponse) FindIAMAPIKey(name string) (IAMAPIKey, error) { +// FindIAMAPIKey attempts to find an IAMAPIKey by nameOrKey. +func (l ListAPIKeysResponse) FindIAMAPIKey(nameOrKey string) (IAMAPIKey, error) { for i, elem := range l.APIKeys { - if string(elem.Name) == name { + if string(elem.Name) == nameOrKey || string(elem.Key) == nameOrKey { return l.APIKeys[i], nil } } - return IAMAPIKey{}, fmt.Errorf("%q not found in ListAPIKeysResponse: %w", name, ErrNotFound) + return IAMAPIKey{}, fmt.Errorf("%q not found in ListAPIKeysResponse: %w", nameOrKey, ErrNotFound) } // List API keys @@ -421,7 +421,7 @@ type ListBlockStorageVolumesResponse struct { // FindBlockStorageVolume attempts to find an BlockStorageVolume by nameOrID. func (l ListBlockStorageVolumesResponse) FindBlockStorageVolume(nameOrID string) (BlockStorageVolume, error) { for i, elem := range l.BlockStorageVolumes { - if string(elem.Name) == nameOrID || elem.ID.String() == nameOrID { + if string(elem.Name) == nameOrID || string(elem.ID) == nameOrID { return l.BlockStorageVolumes[i], nil } } @@ -556,7 +556,7 @@ type ListBlockStorageSnapshotsResponse struct { // FindBlockStorageSnapshot attempts to find an BlockStorageSnapshot by nameOrID. func (l ListBlockStorageSnapshotsResponse) FindBlockStorageSnapshot(nameOrID string) (BlockStorageSnapshot, error) { for i, elem := range l.BlockStorageSnapshots { - if string(elem.Name) == nameOrID || elem.ID.String() == nameOrID { + if string(elem.Name) == nameOrID || string(elem.ID) == nameOrID { return l.BlockStorageSnapshots[i], nil } } @@ -2337,7 +2337,7 @@ type ListDBAASExternalEndpointsResponse struct { // FindDBAASExternalEndpoint attempts to find an DBAASExternalEndpoint by nameOrID. func (l ListDBAASExternalEndpointsResponse) FindDBAASExternalEndpoint(nameOrID string) (DBAASExternalEndpoint, error) { for i, elem := range l.DBAASEndpoints { - if string(elem.Name) == nameOrID || elem.ID.String() == nameOrID { + if string(elem.Name) == nameOrID || string(elem.ID) == nameOrID { return l.DBAASEndpoints[i], nil } } @@ -2388,6 +2388,107 @@ func (c Client) ListDBAASExternalEndpoints(ctx context.Context) (*ListDBAASExter return bodyresp, nil } +type GetDBAASExternalIntegrationSettingsDatadogResponse struct { + Settings *DBAASIntegrationSettingsDatadog `json:"settings,omitempty"` +} + +// [BETA] Get Datadog integration settings +func (c Client) GetDBAASExternalIntegrationSettingsDatadog(ctx context.Context, integrationID UUID) (*GetDBAASExternalIntegrationSettingsDatadogResponse, error) { + path := fmt.Sprintf("/dbaas-external-integration-settings-datadog/%v", integrationID) + + request, err := http.NewRequestWithContext(ctx, "GET", c.serverEndpoint+path, nil) + if err != nil { + return nil, fmt.Errorf("GetDBAASExternalIntegrationSettingsDatadog: new request: %w", err) + } + request.Header.Add("User-Agent", UserAgent) + + if err := c.executeRequestInterceptors(ctx, request); err != nil { + return nil, fmt.Errorf("GetDBAASExternalIntegrationSettingsDatadog: execute request editors: %w", err) + } + + if err := c.signRequest(request); err != nil { + return nil, fmt.Errorf("GetDBAASExternalIntegrationSettingsDatadog: sign request: %w", err) + } + + if c.trace { + dumpRequest(request, "get-dbaas-external-integration-settings-datadog") + } + + response, err := c.httpClient.Do(request) + if err != nil { + return nil, fmt.Errorf("GetDBAASExternalIntegrationSettingsDatadog: http client do: %w", err) + } + + if c.trace { + dumpResponse(response) + } + + if err := handleHTTPErrorResp(response); err != nil { + return nil, fmt.Errorf("GetDBAASExternalIntegrationSettingsDatadog: http response: %w", err) + } + + bodyresp := &GetDBAASExternalIntegrationSettingsDatadogResponse{} + if err := prepareJSONResponse(response, bodyresp); err != nil { + return nil, fmt.Errorf("GetDBAASExternalIntegrationSettingsDatadog: prepare Json response: %w", err) + } + + return bodyresp, nil +} + +type UpdateDBAASExternalIntegrationSettingsDatadogRequest struct { + Settings *DBAASIntegrationSettingsDatadog `json:"settings,omitempty"` +} + +// [BETA] Manage Datadog integration settings +func (c Client) UpdateDBAASExternalIntegrationSettingsDatadog(ctx context.Context, integrationID UUID, req UpdateDBAASExternalIntegrationSettingsDatadogRequest) (*Operation, error) { + path := fmt.Sprintf("/dbaas-external-integration-settings-datadog/%v", integrationID) + + body, err := prepareJSONBody(req) + if err != nil { + return nil, fmt.Errorf("UpdateDBAASExternalIntegrationSettingsDatadog: prepare Json body: %w", err) + } + + request, err := http.NewRequestWithContext(ctx, "POST", c.serverEndpoint+path, body) + if err != nil { + return nil, fmt.Errorf("UpdateDBAASExternalIntegrationSettingsDatadog: new request: %w", err) + } + request.Header.Add("User-Agent", UserAgent) + + request.Header.Add("Content-Type", "application/json") + + if err := c.executeRequestInterceptors(ctx, request); err != nil { + return nil, fmt.Errorf("UpdateDBAASExternalIntegrationSettingsDatadog: execute request editors: %w", err) + } + + if err := c.signRequest(request); err != nil { + return nil, fmt.Errorf("UpdateDBAASExternalIntegrationSettingsDatadog: sign request: %w", err) + } + + if c.trace { + dumpRequest(request, "update-dbaas-external-integration-settings-datadog") + } + + response, err := c.httpClient.Do(request) + if err != nil { + return nil, fmt.Errorf("UpdateDBAASExternalIntegrationSettingsDatadog: http client do: %w", err) + } + + if c.trace { + dumpResponse(response) + } + + if err := handleHTTPErrorResp(response); err != nil { + return nil, fmt.Errorf("UpdateDBAASExternalIntegrationSettingsDatadog: http response: %w", err) + } + + bodyresp := &Operation{} + if err := prepareJSONResponse(response, bodyresp); err != nil { + return nil, fmt.Errorf("UpdateDBAASExternalIntegrationSettingsDatadog: prepare Json response: %w", err) + } + + return bodyresp, nil +} + // [BETA] Get a DBaaS external integration func (c Client) GetDBAASExternalIntegration(ctx context.Context, id UUID) (*DBAASExternalIntegration, error) { path := fmt.Sprintf("/dbaas-external-integration/%v", id) @@ -2435,15 +2536,15 @@ type ListDBAASExternalIntegrationsResponse struct { ExternalIntegrations []DBAASExternalIntegration `json:"external-integrations,omitempty"` } -// FindDBAASExternalIntegration attempts to find an DBAASExternalIntegration by ID. -func (l ListDBAASExternalIntegrationsResponse) FindDBAASExternalIntegration(ID string) (DBAASExternalIntegration, error) { +// FindDBAASExternalIntegration attempts to find an DBAASExternalIntegration by id. +func (l ListDBAASExternalIntegrationsResponse) FindDBAASExternalIntegration(id string) (DBAASExternalIntegration, error) { for i, elem := range l.ExternalIntegrations { - if elem.ID.String() == ID { + if string(elem.ID) == id { return l.ExternalIntegrations[i], nil } } - return DBAASExternalIntegration{}, fmt.Errorf("%q not found in ListDBAASExternalIntegrationsResponse: %w", ID, ErrNotFound) + return DBAASExternalIntegration{}, fmt.Errorf("%q not found in ListDBAASExternalIntegrationsResponse: %w", id, ErrNotFound) } // [BETA] List all DBaaS connections between services and external endpoints @@ -7934,7 +8035,7 @@ type ListDeployTargetsResponse struct { // FindDeployTarget attempts to find an DeployTarget by nameOrID. func (l ListDeployTargetsResponse) FindDeployTarget(nameOrID string) (DeployTarget, error) { for i, elem := range l.DeployTargets { - if string(elem.Name) == nameOrID || elem.ID.String() == nameOrID { + if string(elem.Name) == nameOrID || string(elem.ID) == nameOrID { return l.DeployTargets[i], nil } } @@ -8032,15 +8133,15 @@ type ListDNSDomainsResponse struct { DNSDomains []DNSDomain `json:"dns-domains,omitempty"` } -// FindDNSDomain attempts to find an DNSDomain by ID. -func (l ListDNSDomainsResponse) FindDNSDomain(ID string) (DNSDomain, error) { +// FindDNSDomain attempts to find an DNSDomain by idOrUnicodeName. +func (l ListDNSDomainsResponse) FindDNSDomain(idOrUnicodeName string) (DNSDomain, error) { for i, elem := range l.DNSDomains { - if elem.ID.String() == ID { + if string(elem.ID) == idOrUnicodeName || string(elem.UnicodeName) == idOrUnicodeName { return l.DNSDomains[i], nil } } - return DNSDomain{}, fmt.Errorf("%q not found in ListDNSDomainsResponse: %w", ID, ErrNotFound) + return DNSDomain{}, fmt.Errorf("%q not found in ListDNSDomainsResponse: %w", idOrUnicodeName, ErrNotFound) } // List DNS domains @@ -8149,7 +8250,7 @@ type ListDNSDomainRecordsResponse struct { // FindDNSDomainRecord attempts to find an DNSDomainRecord by nameOrID. func (l ListDNSDomainRecordsResponse) FindDNSDomainRecord(nameOrID string) (DNSDomainRecord, error) { for i, elem := range l.DNSDomainRecords { - if string(elem.Name) == nameOrID || elem.ID.String() == nameOrID { + if string(elem.Name) == nameOrID || string(elem.ID) == nameOrID { return l.DNSDomainRecords[i], nil } } @@ -8567,15 +8668,15 @@ type ListElasticIPSResponse struct { ElasticIPS []ElasticIP `json:"elastic-ips,omitempty"` } -// FindElasticIP attempts to find an ElasticIP by ID. -func (l ListElasticIPSResponse) FindElasticIP(ID string) (ElasticIP, error) { +// FindElasticIP attempts to find an ElasticIP by idOrIP. +func (l ListElasticIPSResponse) FindElasticIP(idOrIP string) (ElasticIP, error) { for i, elem := range l.ElasticIPS { - if elem.ID.String() == ID { + if string(elem.ID) == idOrIP || string(elem.IP) == idOrIP { return l.ElasticIPS[i], nil } } - return ElasticIP{}, fmt.Errorf("%q not found in ListElasticIPSResponse: %w", ID, ErrNotFound) + return ElasticIP{}, fmt.Errorf("%q not found in ListElasticIPSResponse: %w", idOrIP, ErrNotFound) } // List Elastic IPs @@ -9158,7 +9259,7 @@ type ListIAMRolesResponse struct { // FindIAMRole attempts to find an IAMRole by nameOrID. func (l ListIAMRolesResponse) FindIAMRole(nameOrID string) (IAMRole, error) { for i, elem := range l.IAMRoles { - if string(elem.Name) == nameOrID || elem.ID.String() == nameOrID { + if string(elem.Name) == nameOrID || string(elem.ID) == nameOrID { return l.IAMRoles[i], nil } } @@ -9515,7 +9616,7 @@ type ListInstancesResponse struct { // FindListInstancesResponseInstances attempts to find an ListInstancesResponseInstances by nameOrID. func (l ListInstancesResponse) FindListInstancesResponseInstances(nameOrID string) (ListInstancesResponseInstances, error) { for i, elem := range l.Instances { - if string(elem.Name) == nameOrID || elem.ID.String() == nameOrID { + if string(elem.Name) == nameOrID || string(elem.ID) == nameOrID { return l.Instances[i], nil } } @@ -9686,7 +9787,7 @@ type ListInstancePoolsResponse struct { // FindInstancePool attempts to find an InstancePool by nameOrID. func (l ListInstancePoolsResponse) FindInstancePool(nameOrID string) (InstancePool, error) { for i, elem := range l.InstancePools { - if string(elem.Name) == nameOrID || elem.ID.String() == nameOrID { + if string(elem.Name) == nameOrID || string(elem.ID) == nameOrID { return l.InstancePools[i], nil } } @@ -10187,15 +10288,15 @@ type ListInstanceTypesResponse struct { InstanceTypes []InstanceType `json:"instance-types,omitempty"` } -// FindInstanceType attempts to find an InstanceType by ID. -func (l ListInstanceTypesResponse) FindInstanceType(ID string) (InstanceType, error) { +// FindInstanceType attempts to find an InstanceType by id. +func (l ListInstanceTypesResponse) FindInstanceType(id string) (InstanceType, error) { for i, elem := range l.InstanceTypes { - if elem.ID.String() == ID { + if string(elem.ID) == id { return l.InstanceTypes[i], nil } } - return InstanceType{}, fmt.Errorf("%q not found in ListInstanceTypesResponse: %w", ID, ErrNotFound) + return InstanceType{}, fmt.Errorf("%q not found in ListInstanceTypesResponse: %w", id, ErrNotFound) } // List Compute instance Types @@ -11075,7 +11176,7 @@ type ListLoadBalancersResponse struct { // FindLoadBalancer attempts to find an LoadBalancer by nameOrID. func (l ListLoadBalancersResponse) FindLoadBalancer(nameOrID string) (LoadBalancer, error) { for i, elem := range l.LoadBalancers { - if string(elem.Name) == nameOrID || elem.ID.String() == nameOrID { + if string(elem.Name) == nameOrID || string(elem.ID) == nameOrID { return l.LoadBalancers[i], nil } } @@ -11772,7 +11873,7 @@ type ListPrivateNetworksResponse struct { // FindPrivateNetwork attempts to find an PrivateNetwork by nameOrID. func (l ListPrivateNetworksResponse) FindPrivateNetwork(nameOrID string) (PrivateNetwork, error) { for i, elem := range l.PrivateNetworks { - if string(elem.Name) == nameOrID || elem.ID.String() == nameOrID { + if string(elem.Name) == nameOrID || string(elem.ID) == nameOrID { return l.PrivateNetworks[i], nil } } @@ -12642,7 +12743,7 @@ type ListSecurityGroupsResponse struct { // FindSecurityGroup attempts to find an SecurityGroup by nameOrID. func (l ListSecurityGroupsResponse) FindSecurityGroup(nameOrID string) (SecurityGroup, error) { for i, elem := range l.SecurityGroups { - if string(elem.Name) == nameOrID || elem.ID.String() == nameOrID { + if string(elem.Name) == nameOrID || string(elem.ID) == nameOrID { return l.SecurityGroups[i], nil } } @@ -13227,7 +13328,7 @@ type ListSKSClustersResponse struct { // FindSKSCluster attempts to find an SKSCluster by nameOrID. func (l ListSKSClustersResponse) FindSKSCluster(nameOrID string) (SKSCluster, error) { for i, elem := range l.SKSClusters { - if string(elem.Name) == nameOrID || elem.ID.String() == nameOrID { + if string(elem.Name) == nameOrID || string(elem.ID) == nameOrID { return l.SKSClusters[i], nil } } @@ -14436,7 +14537,7 @@ type ListSnapshotsResponse struct { // FindSnapshot attempts to find an Snapshot by nameOrID. func (l ListSnapshotsResponse) FindSnapshot(nameOrID string) (Snapshot, error) { for i, elem := range l.Snapshots { - if string(elem.Name) == nameOrID || elem.ID.String() == nameOrID { + if string(elem.Name) == nameOrID || string(elem.ID) == nameOrID { return l.Snapshots[i], nil } } @@ -14804,15 +14905,15 @@ type ListSSHKeysResponse struct { SSHKeys []SSHKey `json:"ssh-keys,omitempty"` } -// FindSSHKey attempts to find an SSHKey by name. -func (l ListSSHKeysResponse) FindSSHKey(name string) (SSHKey, error) { +// FindSSHKey attempts to find an SSHKey by nameOrFingerprint. +func (l ListSSHKeysResponse) FindSSHKey(nameOrFingerprint string) (SSHKey, error) { for i, elem := range l.SSHKeys { - if string(elem.Name) == name { + if string(elem.Name) == nameOrFingerprint || string(elem.Fingerprint) == nameOrFingerprint { return l.SSHKeys[i], nil } } - return SSHKey{}, fmt.Errorf("%q not found in ListSSHKeysResponse: %w", name, ErrNotFound) + return SSHKey{}, fmt.Errorf("%q not found in ListSSHKeysResponse: %w", nameOrFingerprint, ErrNotFound) } // List SSH keys @@ -15008,7 +15109,7 @@ type ListTemplatesResponse struct { // FindTemplate attempts to find an Template by nameOrID. func (l ListTemplatesResponse) FindTemplate(nameOrID string) (Template, error) { for i, elem := range l.Templates { - if string(elem.Name) == nameOrID || elem.ID.String() == nameOrID { + if string(elem.Name) == nameOrID || string(elem.ID) == nameOrID { return l.Templates[i], nil } } @@ -15374,15 +15475,15 @@ type ListZonesResponse struct { Zones []Zone `json:"zones,omitempty"` } -// FindZone attempts to find an Zone by name. -func (l ListZonesResponse) FindZone(name string) (Zone, error) { +// FindZone attempts to find an Zone by nameOrAPIEndpoint. +func (l ListZonesResponse) FindZone(nameOrAPIEndpoint string) (Zone, error) { for i, elem := range l.Zones { - if string(elem.Name) == name { + if string(elem.Name) == nameOrAPIEndpoint || string(elem.APIEndpoint) == nameOrAPIEndpoint { return l.Zones[i], nil } } - return Zone{}, fmt.Errorf("%q not found in ListZonesResponse: %w", name, ErrNotFound) + return Zone{}, fmt.Errorf("%q not found in ListZonesResponse: %w", nameOrAPIEndpoint, ErrNotFound) } // List Zones diff --git a/vendor/github.com/exoscale/egoscale/v3/schemas.go b/vendor/github.com/exoscale/egoscale/v3/schemas.go index 3796e735..95ddaea9 100644 --- a/vendor/github.com/exoscale/egoscale/v3/schemas.go +++ b/vendor/github.com/exoscale/egoscale/v3/schemas.go @@ -361,6 +361,13 @@ type DBAASIntegration struct { Type string `json:"type,omitempty"` } +type DBAASIntegrationSettingsDatadog struct { + // Database monitoring: view query metrics, explain plans, and execution details. Correlate queries with host metrics. + DatadogDbmEnabled *bool `json:"datadog-dbm-enabled,omitempty"` + // Integrate PgBouncer with Datadog to track connection pool metrics and monitor application traffic. + DatadogPgbouncerEnabled *bool `json:"datadog-pgbouncer-enabled,omitempty"` +} + // A JSON schema of additional settings of the integration. type DBAASIntegrationTypeSettings struct { AdditionalProperties *bool `json:"additionalProperties,omitempty"` diff --git a/vendor/github.com/exoscale/egoscale/v3/version.go b/vendor/github.com/exoscale/egoscale/v3/version.go index 909a039a..02227f72 100644 --- a/vendor/github.com/exoscale/egoscale/v3/version.go +++ b/vendor/github.com/exoscale/egoscale/v3/version.go @@ -1,4 +1,4 @@ package v3 // Version represents the current egoscale v3 version. -const Version = "v3.1.0" +const Version = "v3.1.4" diff --git a/vendor/github.com/stretchr/objx/README.md b/vendor/github.com/stretchr/objx/README.md index 736e1eb5..78dc1f8b 100644 --- a/vendor/github.com/stretchr/objx/README.md +++ b/vendor/github.com/stretchr/objx/README.md @@ -74,7 +74,7 @@ To update Objx to the latest version, run: go get -u github.com/stretchr/objx ### Supported go versions -We currently support the most recent major Go versions from 1.13 onward. +We currently support the three recent major Go versions. ## Contributing Please feel free to submit issues, fork the repository and send pull requests! diff --git a/vendor/github.com/stretchr/objx/Taskfile.yml b/vendor/github.com/stretchr/objx/Taskfile.yml index 39f49d5a..8a79e8d6 100644 --- a/vendor/github.com/stretchr/objx/Taskfile.yml +++ b/vendor/github.com/stretchr/objx/Taskfile.yml @@ -1,4 +1,4 @@ -version: '2' +version: '3' tasks: default: diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare.go b/vendor/github.com/stretchr/testify/assert/assertion_compare.go index b774da88..4d4b4aad 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_compare.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_compare.go @@ -28,6 +28,8 @@ var ( uint32Type = reflect.TypeOf(uint32(1)) uint64Type = reflect.TypeOf(uint64(1)) + uintptrType = reflect.TypeOf(uintptr(1)) + float32Type = reflect.TypeOf(float32(1)) float64Type = reflect.TypeOf(float64(1)) @@ -308,11 +310,11 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { case reflect.Struct: { // All structs enter here. We're not interested in most types. - if !canConvert(obj1Value, timeType) { + if !obj1Value.CanConvert(timeType) { break } - // time.Time can compared! + // time.Time can be compared! timeObj1, ok := obj1.(time.Time) if !ok { timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time) @@ -328,7 +330,7 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { case reflect.Slice: { // We only care about the []byte type. - if !canConvert(obj1Value, bytesType) { + if !obj1Value.CanConvert(bytesType) { break } @@ -345,6 +347,26 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { return CompareType(bytes.Compare(bytesObj1, bytesObj2)), true } + case reflect.Uintptr: + { + uintptrObj1, ok := obj1.(uintptr) + if !ok { + uintptrObj1 = obj1Value.Convert(uintptrType).Interface().(uintptr) + } + uintptrObj2, ok := obj2.(uintptr) + if !ok { + uintptrObj2 = obj2Value.Convert(uintptrType).Interface().(uintptr) + } + if uintptrObj1 > uintptrObj2 { + return compareGreater, true + } + if uintptrObj1 == uintptrObj2 { + return compareEqual, true + } + if uintptrObj1 < uintptrObj2 { + return compareLess, true + } + } } return compareEqual, false diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go b/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go deleted file mode 100644 index da867903..00000000 --- a/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build go1.17 -// +build go1.17 - -// TODO: once support for Go 1.16 is dropped, this file can be -// merged/removed with assertion_compare_go1.17_test.go and -// assertion_compare_legacy.go - -package assert - -import "reflect" - -// Wrapper around reflect.Value.CanConvert, for compatibility -// reasons. -func canConvert(value reflect.Value, to reflect.Type) bool { - return value.CanConvert(to) -} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go b/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go deleted file mode 100644 index 1701af2a..00000000 --- a/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build !go1.17 -// +build !go1.17 - -// TODO: once support for Go 1.16 is dropped, this file can be -// merged/removed with assertion_compare_go1.17_test.go and -// assertion_compare_can_convert.go - -package assert - -import "reflect" - -// Older versions of Go does not have the reflect.Value.CanConvert -// method. -func canConvert(value reflect.Value, to reflect.Type) bool { - return false -} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go index 84dbd6c7..3ddab109 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_format.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go @@ -1,7 +1,4 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ +// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. package assert @@ -107,7 +104,7 @@ func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, return EqualExportedValues(t, expected, actual, append([]interface{}{msg}, args...)...) } -// EqualValuesf asserts that two objects are equal or convertable to the same types +// EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // // assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted") @@ -616,6 +613,16 @@ func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interf return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...) } +// NotImplementsf asserts that an object does not implement the specified interface. +// +// assert.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotImplements(t, interfaceObject, object, append([]interface{}{msg}, args...)...) +} + // NotNilf asserts that the specified object is not nil. // // assert.NotNilf(t, err, "error message %s", "formatted") @@ -660,10 +667,12 @@ func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...) } -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubsetf asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted") +// assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -747,10 +756,11 @@ func Samef(t TestingT, expected interface{}, actual interface{}, msg string, arg return Same(t, expected, actual, append([]interface{}{msg}, args...)...) } -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subsetf asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +// assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted") +// assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go index b1d94aec..a84e09bd 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_forward.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go @@ -1,7 +1,4 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ +// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. package assert @@ -189,7 +186,7 @@ func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface return EqualExportedValuesf(a.t, expected, actual, msg, args...) } -// EqualValues asserts that two objects are equal or convertable to the same types +// EqualValues asserts that two objects are equal or convertible to the same types // and equal. // // a.EqualValues(uint32(123), int32(123)) @@ -200,7 +197,7 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn return EqualValues(a.t, expected, actual, msgAndArgs...) } -// EqualValuesf asserts that two objects are equal or convertable to the same types +// EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // // a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted") @@ -1221,6 +1218,26 @@ func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...in return NotErrorIsf(a.t, err, target, msg, args...) } +// NotImplements asserts that an object does not implement the specified interface. +// +// a.NotImplements((*MyInterface)(nil), new(MyObject)) +func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotImplements(a.t, interfaceObject, object, msgAndArgs...) +} + +// NotImplementsf asserts that an object does not implement the specified interface. +// +// a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotImplementsf(a.t, interfaceObject, object, msg, args...) +} + // NotNil asserts that the specified object is not nil. // // a.NotNil(err) @@ -1309,10 +1326,12 @@ func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg stri return NotSamef(a.t, expected, actual, msg, args...) } -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubset asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +// a.NotSubset([1, 3, 4], [1, 2]) +// a.NotSubset({"x": 1, "y": 2}, {"z": 3}) func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1320,10 +1339,12 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs return NotSubset(a.t, list, subset, msgAndArgs...) } -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubsetf asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +// a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted") +// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1483,10 +1504,11 @@ func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, return Samef(a.t, expected, actual, msg, args...) } -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subset asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +// a.Subset([1, 2, 3], [1, 2]) +// a.Subset({"x": 1, "y": 2}, {"x": 1}) func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1494,10 +1516,11 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ... return Subset(a.t, list, subset, msgAndArgs...) } -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subsetf asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +// a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted") +// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go index a55d1bba..0b7570f2 100644 --- a/vendor/github.com/stretchr/testify/assert/assertions.go +++ b/vendor/github.com/stretchr/testify/assert/assertions.go @@ -19,7 +19,7 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/pmezard/go-difflib/difflib" - yaml "gopkg.in/yaml.v3" + "gopkg.in/yaml.v3" ) //go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl" @@ -110,7 +110,12 @@ func copyExportedFields(expected interface{}) interface{} { return result.Interface() case reflect.Array, reflect.Slice: - result := reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len()) + var result reflect.Value + if expectedKind == reflect.Array { + result = reflect.New(reflect.ArrayOf(expectedValue.Len(), expectedType.Elem())).Elem() + } else { + result = reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len()) + } for i := 0; i < expectedValue.Len(); i++ { index := expectedValue.Index(i) if isNil(index) { @@ -140,6 +145,8 @@ func copyExportedFields(expected interface{}) interface{} { // structures. // // This function does no assertion of any kind. +// +// Deprecated: Use [EqualExportedValues] instead. func ObjectsExportedFieldsAreEqual(expected, actual interface{}) bool { expectedCleaned := copyExportedFields(expected) actualCleaned := copyExportedFields(actual) @@ -153,17 +160,40 @@ func ObjectsAreEqualValues(expected, actual interface{}) bool { return true } - actualType := reflect.TypeOf(actual) - if actualType == nil { + expectedValue := reflect.ValueOf(expected) + actualValue := reflect.ValueOf(actual) + if !expectedValue.IsValid() || !actualValue.IsValid() { return false } - expectedValue := reflect.ValueOf(expected) - if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) { + + expectedType := expectedValue.Type() + actualType := actualValue.Type() + if !expectedType.ConvertibleTo(actualType) { + return false + } + + if !isNumericType(expectedType) || !isNumericType(actualType) { // Attempt comparison after type conversion - return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual) + return reflect.DeepEqual( + expectedValue.Convert(actualType).Interface(), actual, + ) } - return false + // If BOTH values are numeric, there are chances of false positives due + // to overflow or underflow. So, we need to make sure to always convert + // the smaller type to a larger type before comparing. + if expectedType.Size() >= actualType.Size() { + return actualValue.Convert(expectedType).Interface() == expected + } + + return expectedValue.Convert(actualType).Interface() == actual +} + +// isNumericType returns true if the type is one of: +// int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, +// float32, float64, complex64, complex128 +func isNumericType(t reflect.Type) bool { + return t.Kind() >= reflect.Int && t.Kind() <= reflect.Complex128 } /* CallerInfo is necessary because the assert functions use the testing object @@ -266,7 +296,7 @@ func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { // Aligns the provided message so that all lines after the first line start at the same location as the first line. // Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab). -// The longestLabelLen parameter specifies the length of the longest label in the output (required becaues this is the +// The longestLabelLen parameter specifies the length of the longest label in the output (required because this is the // basis on which the alignment occurs). func indentMessageLines(message string, longestLabelLen int) string { outBuf := new(bytes.Buffer) @@ -382,6 +412,25 @@ func Implements(t TestingT, interfaceObject interface{}, object interface{}, msg return true } +// NotImplements asserts that an object does not implement the specified interface. +// +// assert.NotImplements(t, (*MyInterface)(nil), new(MyObject)) +func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + interfaceType := reflect.TypeOf(interfaceObject).Elem() + + if object == nil { + return Fail(t, fmt.Sprintf("Cannot check if nil does not implement %v", interfaceType), msgAndArgs...) + } + if reflect.TypeOf(object).Implements(interfaceType) { + return Fail(t, fmt.Sprintf("%T implements %v", object, interfaceType), msgAndArgs...) + } + + return true +} + // IsType asserts that the specified objects are of the same type. func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { @@ -496,7 +545,7 @@ func samePointers(first, second interface{}) bool { // representations appropriate to be presented to the user. // // If the values are not of like type, the returned strings will be prefixed -// with the type name, and the value will be enclosed in parenthesis similar +// with the type name, and the value will be enclosed in parentheses similar // to a type conversion in the Go grammar. func formatUnequalValues(expected, actual interface{}) (e string, a string) { if reflect.TypeOf(expected) != reflect.TypeOf(actual) { @@ -523,7 +572,7 @@ func truncatingFormat(data interface{}) string { return value } -// EqualValues asserts that two objects are equal or convertable to the same types +// EqualValues asserts that two objects are equal or convertible to the same types // and equal. // // assert.EqualValues(t, uint32(123), int32(123)) @@ -566,12 +615,19 @@ func EqualExportedValues(t TestingT, expected, actual interface{}, msgAndArgs .. return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...) } + if aType.Kind() == reflect.Ptr { + aType = aType.Elem() + } + if bType.Kind() == reflect.Ptr { + bType = bType.Elem() + } + if aType.Kind() != reflect.Struct { - return Fail(t, fmt.Sprintf("Types expected to both be struct \n\t%v != %v", aType.Kind(), reflect.Struct), msgAndArgs...) + return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", aType.Kind(), reflect.Struct), msgAndArgs...) } if bType.Kind() != reflect.Struct { - return Fail(t, fmt.Sprintf("Types expected to both be struct \n\t%v != %v", bType.Kind(), reflect.Struct), msgAndArgs...) + return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", bType.Kind(), reflect.Struct), msgAndArgs...) } expected = copyExportedFields(expected) @@ -620,17 +676,6 @@ func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { return Fail(t, "Expected value not to be nil.", msgAndArgs...) } -// containsKind checks if a specified kind in the slice of kinds. -func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool { - for i := 0; i < len(kinds); i++ { - if kind == kinds[i] { - return true - } - } - - return false -} - // isNil checks if a specified object is nil or not, without Failing. func isNil(object interface{}) bool { if object == nil { @@ -638,16 +683,13 @@ func isNil(object interface{}) bool { } value := reflect.ValueOf(object) - kind := value.Kind() - isNilableKind := containsKind( - []reflect.Kind{ - reflect.Chan, reflect.Func, - reflect.Interface, reflect.Map, - reflect.Ptr, reflect.Slice, reflect.UnsafePointer}, - kind) - - if isNilableKind && value.IsNil() { - return true + switch value.Kind() { + case + reflect.Chan, reflect.Func, + reflect.Interface, reflect.Map, + reflect.Ptr, reflect.Slice, reflect.UnsafePointer: + + return value.IsNil() } return false @@ -731,16 +773,14 @@ func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { } -// getLen try to get length of object. -// return (false, 0) if impossible. -func getLen(x interface{}) (ok bool, length int) { +// getLen tries to get the length of an object. +// It returns (0, false) if impossible. +func getLen(x interface{}) (length int, ok bool) { v := reflect.ValueOf(x) defer func() { - if e := recover(); e != nil { - ok = false - } + ok = recover() == nil }() - return true, v.Len() + return v.Len(), true } // Len asserts that the specified object has specific length. @@ -751,13 +791,13 @@ func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) if h, ok := t.(tHelper); ok { h.Helper() } - ok, l := getLen(object) + l, ok := getLen(object) if !ok { - return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...) + return Fail(t, fmt.Sprintf("\"%v\" could not be applied builtin len()", object), msgAndArgs...) } if l != length { - return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) + return Fail(t, fmt.Sprintf("\"%v\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) } return true } @@ -919,10 +959,11 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) } -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subset asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +// assert.Subset(t, [1, 2, 3], [1, 2]) +// assert.Subset(t, {"x": 1, "y": 2}, {"x": 1}) func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { if h, ok := t.(tHelper); ok { h.Helper() @@ -975,10 +1016,12 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok return true } -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubset asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +// assert.NotSubset(t, [1, 3, 4], [1, 2]) +// assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3}) func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1439,7 +1482,7 @@ func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAnd h.Helper() } if math.IsNaN(epsilon) { - return Fail(t, "epsilon must not be NaN") + return Fail(t, "epsilon must not be NaN", msgAndArgs...) } actualEpsilon, err := calcRelativeError(expected, actual) if err != nil { @@ -1458,19 +1501,26 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m if h, ok := t.(tHelper); ok { h.Helper() } - if expected == nil || actual == nil || - reflect.TypeOf(actual).Kind() != reflect.Slice || - reflect.TypeOf(expected).Kind() != reflect.Slice { + + if expected == nil || actual == nil { return Fail(t, "Parameters must be slice", msgAndArgs...) } - actualSlice := reflect.ValueOf(actual) expectedSlice := reflect.ValueOf(expected) + actualSlice := reflect.ValueOf(actual) - for i := 0; i < actualSlice.Len(); i++ { - result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon) - if !result { - return result + if expectedSlice.Type().Kind() != reflect.Slice { + return Fail(t, "Expected value must be slice", msgAndArgs...) + } + + expectedLen := expectedSlice.Len() + if !IsType(t, expected, actual) || !Len(t, actual, expectedLen) { + return false + } + + for i := 0; i < expectedLen; i++ { + if !InEpsilon(t, expectedSlice.Index(i).Interface(), actualSlice.Index(i).Interface(), epsilon, "at index %d", i) { + return false } } @@ -1870,23 +1920,18 @@ func (c *CollectT) Errorf(format string, args ...interface{}) { } // FailNow panics. -func (c *CollectT) FailNow() { +func (*CollectT) FailNow() { panic("Assertion failed") } -// Reset clears the collected errors. -func (c *CollectT) Reset() { - c.errors = nil +// Deprecated: That was a method for internal usage that should not have been published. Now just panics. +func (*CollectT) Reset() { + panic("Reset() is deprecated") } -// Copy copies the collected errors to the supplied t. -func (c *CollectT) Copy(t TestingT) { - if tt, ok := t.(tHelper); ok { - tt.Helper() - } - for _, err := range c.errors { - t.Errorf("%v", err) - } +// Deprecated: That was a method for internal usage that should not have been published. Now just panics. +func (*CollectT) Copy(TestingT) { + panic("Copy() is deprecated") } // EventuallyWithT asserts that given condition will be met in waitFor time, @@ -1912,8 +1957,8 @@ func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time h.Helper() } - collect := new(CollectT) - ch := make(chan bool, 1) + var lastFinishedTickErrs []error + ch := make(chan []error, 1) timer := time.NewTimer(waitFor) defer timer.Stop() @@ -1924,19 +1969,25 @@ func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time for tick := ticker.C; ; { select { case <-timer.C: - collect.Copy(t) + for _, err := range lastFinishedTickErrs { + t.Errorf("%v", err) + } return Fail(t, "Condition never satisfied", msgAndArgs...) case <-tick: tick = nil - collect.Reset() go func() { + collect := new(CollectT) + defer func() { + ch <- collect.errors + }() condition(collect) - ch <- len(collect.errors) == 0 }() - case v := <-ch: - if v { + case errs := <-ch: + if len(errs) == 0 { return true } + // Keep the errors from the last ended condition, so that they can be copied to t if timeout is reached. + lastFinishedTickErrs = errs tick = ticker.C } } diff --git a/vendor/github.com/stretchr/testify/assert/http_assertions.go b/vendor/github.com/stretchr/testify/assert/http_assertions.go index d8038c28..861ed4b7 100644 --- a/vendor/github.com/stretchr/testify/assert/http_assertions.go +++ b/vendor/github.com/stretchr/testify/assert/http_assertions.go @@ -12,7 +12,7 @@ import ( // an error if building a new request fails. func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) { w := httptest.NewRecorder() - req, err := http.NewRequest(method, url, nil) + req, err := http.NewRequest(method, url, http.NoBody) if err != nil { return -1, err } @@ -32,12 +32,12 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, value } code, err := httpCode(handler, method, url, values) if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent if !isSuccessCode { - Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code)) + Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) } return isSuccessCode @@ -54,12 +54,12 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, valu } code, err := httpCode(handler, method, url, values) if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect if !isRedirectCode { - Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code)) + Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) } return isRedirectCode @@ -76,12 +76,12 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values } code, err := httpCode(handler, method, url, values) if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } isErrorCode := code >= http.StatusBadRequest if !isErrorCode { - Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code)) + Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) } return isErrorCode @@ -98,12 +98,12 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, va } code, err := httpCode(handler, method, url, values) if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } successful := code == statuscode if !successful { - Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code)) + Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code), msgAndArgs...) } return successful @@ -113,7 +113,10 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, va // empty string if building a new request fails. func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string { w := httptest.NewRecorder() - req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) + if len(values) > 0 { + url += "?" + values.Encode() + } + req, err := http.NewRequest(method, url, http.NoBody) if err != nil { return "" } @@ -135,7 +138,7 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, contains := strings.Contains(body, fmt.Sprint(str)) if !contains { - Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...) } return contains @@ -155,7 +158,7 @@ func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url strin contains := strings.Contains(body, fmt.Sprint(str)) if contains { - Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...) } return !contains diff --git a/vendor/github.com/stretchr/testify/mock/mock.go b/vendor/github.com/stretchr/testify/mock/mock.go index f4b42e44..213bde2e 100644 --- a/vendor/github.com/stretchr/testify/mock/mock.go +++ b/vendor/github.com/stretchr/testify/mock/mock.go @@ -18,6 +18,9 @@ import ( "github.com/stretchr/testify/assert" ) +// regex for GCCGO functions +var gccgoRE = regexp.MustCompile(`\.pN\d+_`) + // TestingT is an interface wrapper around *testing.T type TestingT interface { Logf(format string, args ...interface{}) @@ -111,7 +114,7 @@ func (c *Call) Return(returnArguments ...interface{}) *Call { return c } -// Panic specifies if the functon call should fail and the panic message +// Panic specifies if the function call should fail and the panic message // // Mock.On("DoSomething").Panic("test panic") func (c *Call) Panic(msg string) *Call { @@ -123,21 +126,21 @@ func (c *Call) Panic(msg string) *Call { return c } -// Once indicates that that the mock should only return the value once. +// Once indicates that the mock should only return the value once. // // Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Once() func (c *Call) Once() *Call { return c.Times(1) } -// Twice indicates that that the mock should only return the value twice. +// Twice indicates that the mock should only return the value twice. // // Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Twice() func (c *Call) Twice() *Call { return c.Times(2) } -// Times indicates that that the mock should only return the indicated number +// Times indicates that the mock should only return the indicated number // of times. // // Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Times(5) @@ -455,9 +458,8 @@ func (m *Mock) Called(arguments ...interface{}) Arguments { // For Ex: github_com_docker_libkv_store_mock.WatchTree.pN39_github_com_docker_libkv_store_mock.Mock // uses interface information unlike golang github.com/docker/libkv/store/mock.(*Mock).WatchTree // With GCCGO we need to remove interface information starting from pN
. - re := regexp.MustCompile("\\.pN\\d+_") - if re.MatchString(functionPath) { - functionPath = re.Split(functionPath, -1)[0] + if gccgoRE.MatchString(functionPath) { + functionPath = gccgoRE.Split(functionPath, -1)[0] } parts := strings.Split(functionPath, ".") functionName := parts[len(parts)-1] @@ -474,7 +476,7 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen found, call := m.findExpectedCall(methodName, arguments...) if found < 0 { - // expected call found but it has already been called with repeatable times + // expected call found, but it has already been called with repeatable times if call != nil { m.mutex.Unlock() m.fail("\nassert: mock: The method has been called over %d times.\n\tEither do one more Mock.On(\"%s\").Return(...), or remove extra call.\n\tThis call was unexpected:\n\t\t%s\n\tat: %s", call.totalCalls, methodName, callString(methodName, arguments, true), assert.CallerInfo()) @@ -563,7 +565,7 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen Assertions */ -type assertExpectationser interface { +type assertExpectationiser interface { AssertExpectations(TestingT) bool } @@ -580,7 +582,7 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool { t.Logf("Deprecated mock.AssertExpectationsForObjects(myMock.Mock) use mock.AssertExpectationsForObjects(myMock)") obj = m } - m := obj.(assertExpectationser) + m := obj.(assertExpectationiser) if !m.AssertExpectations(t) { t.Logf("Expectations didn't match for Mock: %+v", reflect.TypeOf(m)) return false @@ -592,6 +594,9 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool { // AssertExpectations asserts that everything specified with On and Return was // in fact called as expected. Calls may have occurred in any order. func (m *Mock) AssertExpectations(t TestingT) bool { + if s, ok := t.(interface{ Skipped() bool }); ok && s.Skipped() { + return true + } if h, ok := t.(tHelper); ok { h.Helper() } @@ -606,8 +611,8 @@ func (m *Mock) AssertExpectations(t TestingT) bool { satisfied, reason := m.checkExpectation(expectedCall) if !satisfied { failedExpectations++ + t.Logf(reason) } - t.Logf(reason) } if failedExpectations != 0 { @@ -758,25 +763,33 @@ const ( Anything = "mock.Anything" ) -// AnythingOfTypeArgument is a string that contains the type of an argument +// AnythingOfTypeArgument contains the type of an argument +// for use when type checking. Used in Diff and Assert. +// +// Deprecated: this is an implementation detail that must not be used. Use [AnythingOfType] instead. +type AnythingOfTypeArgument = anythingOfTypeArgument + +// anythingOfTypeArgument is a string that contains the type of an argument // for use when type checking. Used in Diff and Assert. -type AnythingOfTypeArgument string +type anythingOfTypeArgument string -// AnythingOfType returns an AnythingOfTypeArgument object containing the -// name of the type to check for. Used in Diff and Assert. +// AnythingOfType returns a special value containing the +// name of the type to check for. The type name will be matched against the type name returned by [reflect.Type.String]. +// +// Used in Diff and Assert. // // For example: // // Assert(t, AnythingOfType("string"), AnythingOfType("int")) func AnythingOfType(t string) AnythingOfTypeArgument { - return AnythingOfTypeArgument(t) + return anythingOfTypeArgument(t) } // IsTypeArgument is a struct that contains the type of an argument // for use when type checking. This is an alternative to AnythingOfType. // Used in Diff and Assert. type IsTypeArgument struct { - t interface{} + t reflect.Type } // IsType returns an IsTypeArgument object containing the type to check for. @@ -786,7 +799,7 @@ type IsTypeArgument struct { // For example: // Assert(t, IsType(""), IsType(0)) func IsType(t interface{}) *IsTypeArgument { - return &IsTypeArgument{t: t} + return &IsTypeArgument{t: reflect.TypeOf(t)} } // FunctionalOptionsArgument is a struct that contains the type and value of an functional option argument @@ -950,53 +963,55 @@ func (args Arguments) Diff(objects []interface{}) (string, int) { differences++ output = fmt.Sprintf("%s\t%d: FAIL: %s not matched by %s\n", output, i, actualFmt, matcher) } - } else if reflect.TypeOf(expected) == reflect.TypeOf((*AnythingOfTypeArgument)(nil)).Elem() { - // type checking - if reflect.TypeOf(actual).Name() != string(expected.(AnythingOfTypeArgument)) && reflect.TypeOf(actual).String() != string(expected.(AnythingOfTypeArgument)) { - // not match - differences++ - output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actualFmt) - } - } else if reflect.TypeOf(expected) == reflect.TypeOf((*IsTypeArgument)(nil)) { - t := expected.(*IsTypeArgument).t - if reflect.TypeOf(t) != reflect.TypeOf(actual) { - differences++ - output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, reflect.TypeOf(t).Name(), reflect.TypeOf(actual).Name(), actualFmt) - } - } else if reflect.TypeOf(expected) == reflect.TypeOf((*FunctionalOptionsArgument)(nil)) { - t := expected.(*FunctionalOptionsArgument).value + } else { + switch expected := expected.(type) { + case anythingOfTypeArgument: + // type checking + if reflect.TypeOf(actual).Name() != string(expected) && reflect.TypeOf(actual).String() != string(expected) { + // not match + differences++ + output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actualFmt) + } + case *IsTypeArgument: + actualT := reflect.TypeOf(actual) + if actualT != expected.t { + differences++ + output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected.t.Name(), actualT.Name(), actualFmt) + } + case *FunctionalOptionsArgument: + t := expected.value - var name string - tValue := reflect.ValueOf(t) - if tValue.Len() > 0 { - name = "[]" + reflect.TypeOf(tValue.Index(0).Interface()).String() - } + var name string + tValue := reflect.ValueOf(t) + if tValue.Len() > 0 { + name = "[]" + reflect.TypeOf(tValue.Index(0).Interface()).String() + } - tName := reflect.TypeOf(t).Name() - if name != reflect.TypeOf(actual).String() && tValue.Len() != 0 { - differences++ - output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, tName, reflect.TypeOf(actual).Name(), actualFmt) - } else { - if ef, af := assertOpts(t, actual); ef == "" && af == "" { + tName := reflect.TypeOf(t).Name() + if name != reflect.TypeOf(actual).String() && tValue.Len() != 0 { + differences++ + output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, tName, reflect.TypeOf(actual).Name(), actualFmt) + } else { + if ef, af := assertOpts(t, actual); ef == "" && af == "" { + // match + output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, tName, tName) + } else { + // not match + differences++ + output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, af, ef) + } + } + + default: + if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) { // match - output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, tName, tName) + output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, actualFmt, expectedFmt) } else { // not match differences++ - output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, af, ef) + output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, actualFmt, expectedFmt) } } - } else { - // normal checking - - if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) { - // match - output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, actualFmt, expectedFmt) - } else { - // not match - differences++ - output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, actualFmt, expectedFmt) - } } } diff --git a/vendor/github.com/stretchr/testify/require/require.go b/vendor/github.com/stretchr/testify/require/require.go index 63f85214..506a82f8 100644 --- a/vendor/github.com/stretchr/testify/require/require.go +++ b/vendor/github.com/stretchr/testify/require/require.go @@ -1,7 +1,4 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ +// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. package require @@ -235,7 +232,7 @@ func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, t.FailNow() } -// EqualValues asserts that two objects are equal or convertable to the same types +// EqualValues asserts that two objects are equal or convertible to the same types // and equal. // // assert.EqualValues(t, uint32(123), int32(123)) @@ -249,7 +246,7 @@ func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArg t.FailNow() } -// EqualValuesf asserts that two objects are equal or convertable to the same types +// EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // // assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted") @@ -1546,6 +1543,32 @@ func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interf t.FailNow() } +// NotImplements asserts that an object does not implement the specified interface. +// +// assert.NotImplements(t, (*MyInterface)(nil), new(MyObject)) +func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotImplements(t, interfaceObject, object, msgAndArgs...) { + return + } + t.FailNow() +} + +// NotImplementsf asserts that an object does not implement the specified interface. +// +// assert.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotImplementsf(t, interfaceObject, object, msg, args...) { + return + } + t.FailNow() +} + // NotNil asserts that the specified object is not nil. // // assert.NotNil(t, err) @@ -1658,10 +1681,12 @@ func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, t.FailNow() } -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubset asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +// assert.NotSubset(t, [1, 3, 4], [1, 2]) +// assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3}) func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1672,10 +1697,12 @@ func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...i t.FailNow() } -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubsetf asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted") +// assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1880,10 +1907,11 @@ func Samef(t TestingT, expected interface{}, actual interface{}, msg string, arg t.FailNow() } -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subset asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +// assert.Subset(t, [1, 2, 3], [1, 2]) +// assert.Subset(t, {"x": 1, "y": 2}, {"x": 1}) func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1894,10 +1922,11 @@ func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...inte t.FailNow() } -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subsetf asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +// assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted") +// assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go b/vendor/github.com/stretchr/testify/require/require_forward.go index 3b5b0933..eee8310a 100644 --- a/vendor/github.com/stretchr/testify/require/require_forward.go +++ b/vendor/github.com/stretchr/testify/require/require_forward.go @@ -1,7 +1,4 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ +// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. package require @@ -190,7 +187,7 @@ func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface EqualExportedValuesf(a.t, expected, actual, msg, args...) } -// EqualValues asserts that two objects are equal or convertable to the same types +// EqualValues asserts that two objects are equal or convertible to the same types // and equal. // // a.EqualValues(uint32(123), int32(123)) @@ -201,7 +198,7 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn EqualValues(a.t, expected, actual, msgAndArgs...) } -// EqualValuesf asserts that two objects are equal or convertable to the same types +// EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // // a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted") @@ -1222,6 +1219,26 @@ func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...in NotErrorIsf(a.t, err, target, msg, args...) } +// NotImplements asserts that an object does not implement the specified interface. +// +// a.NotImplements((*MyInterface)(nil), new(MyObject)) +func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotImplements(a.t, interfaceObject, object, msgAndArgs...) +} + +// NotImplementsf asserts that an object does not implement the specified interface. +// +// a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotImplementsf(a.t, interfaceObject, object, msg, args...) +} + // NotNil asserts that the specified object is not nil. // // a.NotNil(err) @@ -1310,10 +1327,12 @@ func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg stri NotSamef(a.t, expected, actual, msg, args...) } -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubset asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +// a.NotSubset([1, 3, 4], [1, 2]) +// a.NotSubset({"x": 1, "y": 2}, {"z": 3}) func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1321,10 +1340,12 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs NotSubset(a.t, list, subset, msgAndArgs...) } -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubsetf asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +// a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted") +// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1484,10 +1505,11 @@ func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, Samef(a.t, expected, actual, msg, args...) } -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subset asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +// a.Subset([1, 2, 3], [1, 2]) +// a.Subset({"x": 1, "y": 2}, {"x": 1}) func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1495,10 +1517,11 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ... Subset(a.t, list, subset, msgAndArgs...) } -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subsetf asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +// a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted") +// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() diff --git a/vendor/modules.txt b/vendor/modules.txt index 98688e69..08788f4d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -220,8 +220,8 @@ github.com/exoscale/egoscale/v2 github.com/exoscale/egoscale/v2/api github.com/exoscale/egoscale/v2/oapi github.com/exoscale/egoscale/version -# github.com/exoscale/egoscale/v3 v3.1.2 -## explicit; go 1.22 +# github.com/exoscale/egoscale/v3 v3.1.4 +## explicit; go 1.22.0 github.com/exoscale/egoscale/v3 github.com/exoscale/egoscale/v3/credentials # github.com/exoscale/openapi-cli-generator v1.1.0 @@ -557,11 +557,11 @@ github.com/spf13/viper/internal/encoding/json github.com/spf13/viper/internal/encoding/toml github.com/spf13/viper/internal/encoding/yaml github.com/spf13/viper/internal/features -# github.com/stretchr/objx v0.5.1 -## explicit; go 1.13 -github.com/stretchr/objx -# github.com/stretchr/testify v1.8.4 +# github.com/stretchr/objx v0.5.2 ## explicit; go 1.20 +github.com/stretchr/objx +# github.com/stretchr/testify v1.9.0 +## explicit; go 1.17 github.com/stretchr/testify/assert github.com/stretchr/testify/mock github.com/stretchr/testify/require