MGC Go SDK

The MGC Go SDK provides a convenient way to interact with the Magalu Cloud API from Go applications.
This is an very active project and work in progress, with many products support comming soon.
For more information about Magalu Cloud, visit:
Installation
go get github.com/MagaluCloud/mgc-sdk-go
Supported Products
- Compute (Virtual Machines)
- Instances
- Machine Types
- Images
- Snapshots
- Block Storage
- Volumes
- Snapshots
- Volume Types
- SSH Keys
- Availability Zones
- Audit
- Database as a Service (DBaaS)
- Instances
- Instance Types
- Snapshots
- Replicas
- Engines
- Clusters
- Parameters
- Container Registry
- Repositories
- Registries
- Images
- Credentials
- Kubernetes
- Clusters
- Flavors
- Info
- Nodepool
- Version
- Network
- VPCs
- Interfaces
- Subnets
- Security Groups
- Public IPs
- Subnetpools
Authentication
The SDK uses an API token for authentication.
client := client.New("your-api-token")
Find more information about how to generate an API token in the Magalu Cloud documentation.
Regions
The Magalu Cloud API is region-based, and each service is available in specific regions. You can set the region on the client to interact with a specific region.
Brazil South East 1 (BR-SE1) - Default
core := client.NewMgcClient(apiToken, client.WithBaseURL(client.BrSe1))
Brazil North East 1 (BR-NE1)
core := client.NewMgcClient(apiToken, client.WithBaseURL(client.BrNe1))
Global Services
Some Magalu Cloud services operate globally and use a dedicated global endpoint (api.magalu.cloud). These global services are:
- SSH Keys Management
- Availability Zones
When using global services, any region configuration set on the core client will be overridden. The service will automatically use the global endpoint.
// Even if core client has a region set
core := client.NewMgcClient(apiToken, client.WithBaseURL(client.BrSe1))
// Global services will ignore the region and use global endpoint
sshClient := sshkeys.New(core) // Uses api.magalu.cloud
// To use a custom endpoint for a global service, use the service's specific option
sshClient := sshkeys.New(core, sshkeys.WithGlobalBasePath("custom-endpoint"))
Note: Setting a region on the core client only affects regional services. Global services will always use their global endpoint unless explicitly configured otherwise using their specific options.
Project Structure
mgc-sdk-go/
├── client/ # Base client implementation and configuration
├── compute/ # Compute service API (instances, images, machine types)
├── helpers/ # Utility functions
├── internal/ # Internal packages
└── cmd/ # Examples
Usage Examples
Initializing the Client
import (
"github.com/MagaluCloud/mgc-sdk-go/client"
"github.com/MagaluCloud/mgc-sdk-go/compute"
)
apiToken := os.Getenv("MGC_API_TOKEN")
c := client.NewMgcClient(apiToken)
computeClient := compute.New(c)
Client Configuration Options
You can customize the client behavior using options:
import (
"time"
"log/slog"
)
// Configure client with multiple options
c := client.NewMgcClient(
apiToken,
client.WithTimeout(5 * time.Minute),
client.WithUserAgent("my-app/1.0"),
client.WithLogger(slog.Default().With("service", "mgc")),
client.WithRetryConfig(
3, // maxAttempts
1 * time.Second, // initialInterval
30 * time.Second, // maxInterval
1.5, // backoffFactor
),
client.WithBaseURL(client.BrSe1),
)
Available options:
WithTimeout
: Sets the client timeout for requests
WithUserAgent
: Sets a custom User-Agent header
WithLogger
: Configures a custom logger
WithRetryConfig
: Customizes the retry behavior
WithHTTPClient
: Uses a custom HTTP client
WithBaseURL
: Changes the API endpoint (useful for testing or setting a specific region to interact)
WithCustomHeader
: Adds custom headers to all requests
Listing Instances
instances, err := computeClient.Instances().List(context.Background(), compute.ListOptions{
Limit: helpers.IntPtr(10),
Offset: helpers.IntPtr(0),
Expand: []string{compute.InstanceMachineTypeExpand, compute.InstanceImageExpand},
})
Creating an Instance
createReq := compute.CreateRequest{
Name: "my-test-vm",
MachineType: compute.IDOrName{
Name: helpers.StrPtr("BV1-1-40"),
},
Image: compute.IDOrName{
Name: helpers.StrPtr("cloud-ubuntu-24.04 LTS"),
},
Network: &compute.CreateParametersNetwork{
AssociatePublicIp: helpers.BoolPtr(false),
},
SshKeyName: helpers.StrPtr("my-ssh-key"),
}
id, err := computeClient.Instances().Create(context.Background(), createReq)
Managing Machine Types
machineTypes, err := computeClient.MachineTypes().List(context.Background(), compute.MachineTypeListOptions{})
Managing Images
images, err := computeClient.Images().List(context.Background(), compute.ImageListOptions{})
Using Request IDs
You can track requests across systems by setting a request ID in the context. The request ID must be a valid UUIDv4 string:
import (
"context"
"github.com/google/uuid"
"github.com/MagaluCloud/mgc-sdk-go/client"
)
// Generate a valid UUIDv4 for the request
requestID := uuid.New().String()
// Create a context with request ID
ctx := context.WithValue(context.Background(), client.RequestIDKey, requestID)
// The client will automatically include the X-Request-ID header
instances, err := computeClient.Instances().List(ctx, compute.ListOptions{})
The request ID will be:
- Must be a valid UUIDv4 string (e.g. "123e4567-e89b-12d3-a456-426614174000")
- Included in the request as
X-Request-ID
header
- Logged in the client's logger
- Returned in the response headers for tracking
Error Handling
HTTP Errors
err := computeClient.Instances().Delete(ctx, id)
if httpErr, ok := err.(*client.HTTPError); ok {
switch httpErr.StatusCode {
case 404:
log.Fatal("Instance not found")
case 403:
log.Fatal("Permission denied")
case 429:
log.Fatal("Rate limit exceeded")
}
log.Printf("Response body: %s", string(httpErr.Body))
}
Validation Errors
_, err := computeClient.Instances().Create(ctx, compute.CreateRequest{})
if validErr, ok := err.(*client.ValidationError); ok {
log.Printf("Invalid field %s: %s", validErr.Field, validErr.Message)
}
Error Types and Interfaces
The SDK provides these error types:
// HTTPError contains details about API request failures
type HTTPError struct {
StatusCode int // HTTP status code
Status string // Status message
Body []byte // Raw response body
Response *http.Response
}
// ValidationError occurs when request parameters are invalid
type ValidationError struct {
Field string // Which field failed validation
Message string // Why the validation failed
}
Common error handling patterns:
// Check for specific error types
err := computeClient.Instances().Delete(ctx, id)
switch e := err.(type) {
case *client.HTTPError:
// Handle HTTP errors (404, 403, etc)
fmt.Printf("HTTP %d: %s\n", e.StatusCode, e.Body)
case *client.ValidationError:
// Handle validation failures
fmt.Printf("Invalid %s: %s\n", e.Field, e.Message)
default:
// Handle other errors (context timeout, network issues)
fmt.Printf("Error: %v\n", err)
}
// Check if error has additional details
if detailed, ok := err.(interface{ ErrorDetails() map[string]interface{} }); ok {
details := detailed.ErrorDetails()
fmt.Printf("Error details: %+v\n", details)
}
Retries
The client automatically retries on network errors and 5xx responses:
client := client.NewMgcClient(
apiToken,
client.WithRetryConfig(
3, // maxAttempts
1 * time.Second, // initialInterval
30 * time.Second, // maxInterval
1.5, // backoffFactor
),
)
Advanced HTTP Client Usage
For more advanced use cases, you can directly use the mgc_http
package. This is useful when you need to interact with API endpoints that are not yet fully supported by the SDK.
ExecuteSimpleRequestWithRespBody
Use this function when you expect a response body that needs to be unmarshaled into a struct.
import (
"context"
"github.com/MagaluCloud/mgc-sdk-go/internal/http"
"github.com/MagaluCloud/mgc-sdk-go/client"
)
type MyResponse struct {
ID string `json:"id"`
Name string `json:"name"`
}
// Create a new request function
newRequest := func(ctx context.Context, method, path string, body any) (*http.Request, error) {
return mgc_http.NewRequest(myClient.Config, ctx, method, path, body)
}
// Make the request
var myResponse MyResponse
_, err := mgc_http.ExecuteSimpleRequestWithRespBody(
context.Background(),
newRequest,
myClient.Config,
"GET",
"/my-endpoint",
nil, // No request body
nil, // No query parameters
&myResponse,
)
ExecuteSimpleRequest
Use this function for requests where you don't expect a response body, such as DELETE
requests or other operations that return a 204 No Content
status.
err := mgc_http.ExecuteSimpleRequest(
context.Background(),
newRequest,
myClient.Config,
"DELETE",
"/my-endpoint/123",
nil, // No request body
nil, // No query parameters
)
Handling Query Parameters
To add query parameters to your request, you can use the helpers.NewQueryParams
function.
import "github.com/MagaluCloud/mgc-sdk-go/helpers"
// ...
req, _ := http.NewRequest("GET", "", nil)
queryParams := helpers.NewQueryParams(req)
queryParams.Add("name", helpers.StrPtr("my-resource"))
queryParams.Add("limit", helpers.IntPtr(10))
// The query parameters will be encoded and added to the request URL
_, err := mgc_http.ExecuteSimpleRequestWithRespBody(
// ...
queryParams,
// ...
)
Handling Optional Fields in JSON
To prevent optional fields from being included in the JSON payload when they are not set, use the omitempty
tag in your struct definitions. This is standard Go practice and is fully supported by the SDK.
type MyRequest struct {
RequiredField string `json:"required_field"`
OptionalField *string `json:"optional_field,omitempty"`
}
// Create a request with only the required field
reqBody := MyRequest{
RequiredField: "some-value",
}
// The resulting JSON will be: {"required_field":"some-value"}
// The optional_field will be omitted.
Full Example
Check the cmd/examples directory for complete working examples of all SDK features.
Contributing
We welcome contributions from the community! Please read our Contributing Guide to learn about our development process, how to propose bugfixes and improvements, and how to build and test your changes.
License
This project is licensed under the Apache 2.0 License - see the LICENSE file for details.