### Manage Fastly Service Configuration with Go Source: https://github.com/fastly/go-fastly/blob/main/EXAMPLES.md This example demonstrates the complete workflow for managing a Fastly service configuration using the go-fastly client. It covers creating a client, fetching service details, cloning a version, adding domains and backends, validating the version, and finally activating it. Ensure the FASTLY_API_KEY environment variable is set. ```go package main import ( "fmt" "log" "os" "github.com/fastly/go-fastly/v15/fastly" ) func main() { // Create a client object. The client has no state, so it can be persisted // and re-used. It is also safe to use concurrently due to its lack of state. // There is also a DefaultClient() method that reads an environment variable. // Please see the documentation for more information and details. client, err := fastly.NewClient(os.Getenv("FASTLY_API_KEY")) if err != nil { log.Fatal(err) } // You can find the service ID in the Fastly web console. var serviceID = "SERVICE_ID" // We'll get the latest 'active' version by inspecting the service metadata and // then finding which available version is the 'active' version. service, err := client.GetService(&fastly.GetServiceInput{ ServiceID: serviceID, }) if err != nil { log.Fatal(err) } // Let's acquire a service version to clone from. We'll start by searching for // the latest 'active' version available, and if there are no active versions, // then we'll clone from whatever is the latest version. latest := service.Versions[len(service.Versions)-1] for _, version := range service.Versions { if *version.Active { latest = version break } } // Clone the latest version so we can make changes without affecting the // active configuration. version, err := client.CloneVersion(&fastly.CloneVersionInput{ ServiceID: serviceID, ServiceVersion: *latest.Number, }) if err != nil { log.Fatal(err) } // Now you can make any changes to the new version. In this example, we will add // a new domain. domain, err := client.CreateDomain(&fastly.CreateDomainInput{ ServiceID: serviceID, ServiceVersion: *version.Number, Name: fastly.ToPointer("example.com"), }) if err != nil { log.Fatal(err) } // Output: "example.com" fmt.Println("domain.Name:", domain.Name) // And we will also add a new backend. backend, err := client.CreateBackend(&fastly.CreateBackendInput{ ServiceID: serviceID, ServiceVersion: *version.Number, Name: fastly.ToPointer("example-backend"), Address: fastly.ToPointer("127.0.0.1"), Port: fastly.ToPointer(80), }) if err != nil { log.Fatal(err) } // Output: "example-backend" fmt.Println("backend.Name:", backend.Name) // Now we can validate that our version is valid. valid, _, err := client.ValidateVersion(&fastly.ValidateVersionInput{ ServiceID: serviceID, ServiceVersion: *version.Number, }) if err != nil { log.Fatal(err) } if !valid { log.Fatal("not valid version") } // Finally, activate this new version. activeVersion, err := client.ActivateVersion(&fastly.ActivateVersionInput{ ServiceID: serviceID, ServiceVersion: *version.Number, }) if err != nil { log.Fatal(err) } // Output: true fmt.Println("activeVersion.Locked:", activeVersion.Locked) } ``` -------------------------------- ### Manage Backends with Go Fastly Client Source: https://context7.com/fastly/go-fastly/llms.txt Provides examples for backend management, including creating, listing, updating, and deleting origin servers. Supports full TLS configuration, load balancing, health checks, and more. All settings are optional pointers allowing partial updates. ```go ctx := context.Background() serviceID := "SU1Z0isxPaozGVKXdv0eY" version := 3 // Create a backend backend, err := client.CreateBackend(ctx, &fastly.CreateBackendInput{ ServiceID: serviceID, ServiceVersion: version, Name: fastly.ToPointer("my-origin"), Address: fastly.ToPointer("origin.example.com"), Port: fastly.ToPointer(443), UseSSL: fastly.ToPointer(fastly.Compatibool(true)), SSLCheckCert: fastly.ToPointer(fastly.Compatibool(true)), SSLCertHostname: fastly.ToPointer("origin.example.com"), ConnectTimeout: fastly.ToPointer(1000), FirstByteTimeout: fastly.ToPointer(15000), MaxConn: fastly.ToPointer(200), Weight: fastly.ToPointer(100), }) if err != nil { log.Fatal(err) } fmt.Println("Backend:", *backend.Name, "address:", *backend.Address) // List all backends on this version backends, err := client.ListBackends(ctx, &fastly.ListBackendsInput{ ServiceID: serviceID, ServiceVersion: version, }) if err != nil { log.Fatal(err) } for _, b := range backends { fmt.Printf(" %s -> %s:%d\n", *b.Name, *b.Address, *b.Port) } // Update a backend updated, err := client.UpdateBackend(ctx, &fastly.UpdateBackendInput{ ServiceID: serviceID, ServiceVersion: version, Name: "my-origin", MaxConn: fastly.ToPointer(500), Shield: fastly.ToPointer("iad-va-us"), }) if err != nil { log.Fatal(err) } fmt.Println("Updated max_conn:", *updated.MaxConn) // Output: Updated max_conn: 500 // Delete a backend err = client.DeleteBackend(ctx, &fastly.DeleteBackendInput{ ServiceID: serviceID, ServiceVersion: version, Name: "my-origin", }) if err != nil { log.Fatal(err) } ``` -------------------------------- ### Get Service Configuration Version Diff Source: https://context7.com/fastly/go-fastly/llms.txt Generates a diff between two service configuration versions. Specify the output format as 'text', 'html', or 'html_simple'. ```go ctx := context.Background() diff, err := client.GetDiff(ctx, &fastly.GetDiffInput{ ServiceID: "SU1Z0isxPaozGVKXdv0eY", From: 4, To: 5, Format: "text", }) if err != nil { log.Fatal(err) } fmt.Printf("Diff from v%d to v%d:\n%s\n", diff.From, diff.To, diff.Diff) ``` -------------------------------- ### Build Project Source: https://github.com/fastly/go-fastly/blob/main/DEVELOPMENT.md Run this command to build the project and verify changes. ```bash $ make all ``` -------------------------------- ### Get Fastly Edge Network IP Addresses Source: https://context7.com/fastly/go-fastly/llms.txt Retrieves Fastly's public edge network IP addresses for both IPv4 and IPv6. Useful for firewall rules. ```go ctx := context.Background() // Get both IPv4 and IPv6 ranges v4, v6, err := client.AllIPs(ctx) if err != nil { log.Fatal(err) } fmt.Printf("IPv4 ranges: %d, IPv6 ranges: %d\n", len(v4), len(v6)) // Output example: IPv4 ranges: 43, IPv6 ranges: 3 for _, ip := range v4 { fmt.Println(" IPv4:", ip) } // Just IPv6 ipv6Only, err := client.IPsV6(ctx) if err != nil { log.Fatal(err) } for _, ip := range ipv6Only { fmt.Println(" IPv6:", ip) } ``` -------------------------------- ### Manage Config Stores with Go Client Source: https://context7.com/fastly/go-fastly/llms.txt Demonstrates creating, adding items to, retrieving metadata from, and listing Fastly Config Stores. Config Stores are globally available and not tied to service versions. ```go ctx := context.Background() // Create cs, err := client.CreateConfigStore(ctx, &fastly.CreateConfigStoreInput{Name: "app-config"}) if err != nil { log.Fatal(err) } fmt.Println("Config Store ID:", cs.StoreID) // Add an item _, err = client.CreateConfigStoreItem(ctx, &fastly.CreateConfigStoreItemInput{ StoreID: cs.StoreID, Key: "api_base_url", Value: "https://internal-api.example.com", }) if err != nil { log.Fatal(err) } // Retrieve store metadata (item count) meta, err := client.GetConfigStoreMetadata(ctx, &fastly.GetConfigStoreMetadataInput{ StoreID: cs.StoreID, }) if err != nil { log.Fatal(err) } fmt.Println("Item count:", meta.ItemCount) // Output: Item count: 1 // List all config stores (sorted by name) stores, err := client.ListConfigStores(ctx, &fastly.ListConfigStoresInput{}) if err != nil { log.Fatal(err) } for _, s := range stores { fmt.Println(" -", s.Name, s.StoreID) } // Find which services use this store services, err := client.ListConfigStoreServices(ctx, &fastly.ListConfigStoreServicesInput{ StoreID: cs.StoreID, }) if err != nil { log.Fatal(err) } for _, svc := range services { fmt.Println("Used by service:", *svc.ID) } ``` -------------------------------- ### Initialize Fastly Client (Go) Source: https://github.com/fastly/go-fastly/blob/main/DEVELOPMENT.md Initialize a Fastly API client using a standard Go environment. Ensure your FASTLY_API_KEY is set and a backend named 'fastly' points to 'https://api.fastly.com'. ```go client, err := fastly.NewClient("FASTLY_API_KEY") client.HTTPClient.Transport = fsthttp.NewTransport("fastly") ``` -------------------------------- ### Manage ACLs and Entries with Go Source: https://context7.com/fastly/go-fastly/llms.txt Demonstrates creating an ACL, adding entries, batch modifying entries, and paginating through ACL entries. Ensure you have the Fastly client initialized. ```go ctx := context.Background() serviceID := "SU1Z0isxPaozGVKXdv0eY" version := 3 // Create an ACL on the version acl, err := client.CreateACL(ctx, &fastly.CreateACLInput{ ServiceID: serviceID, ServiceVersion: version, Name: fastly.ToPointer("block-list"), }) if err != nil { log.Fatal(err) } fmt.Println("ACL ID:", *acl.ACLID) // Add an entry entry, err := client.CreateACLEntry(ctx, &fastly.CreateACLEntryInput{ ServiceID: serviceID, ACLID: *acl.ACLID, IP: fastly.ToPointer("192.0.2.0"), Subnet: fastly.ToPointer(24), Negated: fastly.ToPointer(fastly.Compatibool(false)), Comment: fastly.ToPointer("Block test subnet"), }) if err != nil { log.Fatal(err) } fmt.Printf("Entry ID: %s IP: %s/%d\n", *entry.EntryID, *entry.IP, *entry.Subnet) // Batch modify entries (create/update/delete up to 1000 at once) err = client.BatchModifyACLEntries(ctx, &fastly.BatchModifyACLEntriesInput{ ServiceID: serviceID, ACLID: *acl.ACLID, Entries: []*fastly.BatchACLEntry{ { Operation: fastly.ToPointer(fastly.CreateBatchOperation), IP: fastly.ToPointer("198.51.100.0"), Subnet: fastly.ToPointer(24), }, { Operation: fastly.ToPointer(fastly.DeleteBatchOperation), EntryID: entry.EntryID, }, }, }) if err != nil { log.Fatal(err) } // Paginate through large ACLs paginator := client.GetACLEntries(ctx, &fastly.GetACLEntriesInput{ ServiceID: serviceID, ACLID: *acl.ACLID, PerPage: fastly.ToPointer(100), }) for paginator.HasNext() { entries, err := paginator.GetNext() if err != nil { log.Fatal(err) } fmt.Printf("Page has %d entries\n", len(entries)) } ``` -------------------------------- ### Download Go Modules Source: https://github.com/fastly/go-fastly/blob/main/DEVELOPMENT.md Use this command to download project dependencies. ```bash $ go mod download ``` -------------------------------- ### Manage Fastly Domains with Go Source: https://context7.com/fastly/go-fastly/llms.txt Demonstrates creating, validating, and listing domains for a Fastly service version. Ensure the service ID and version are correctly set. ```go ctx := context.Background() serviceID := "SU1Z0isxPaozGVKXdv0eY" version := 3 // Add a domain domain, err := client.CreateDomain(ctx, &fastly.CreateDomainInput{ ServiceID: serviceID, ServiceVersion: version, Name: fastly.ToPointer("www.example.com"), Comment: fastly.ToPointer("Primary public domain"), }) if err != nil { log.Fatal(err) } fmt.Println("Created domain:", *domain.Name) // Validate DNS for a single domain result, err := client.ValidateDomain(ctx, &fastly.ValidateDomainInput{ ServiceID: serviceID, ServiceVersion: version, Name: "www.example.com", }) if err != nil { log.Fatal(err) } fmt.Printf("Domain valid=%v cname=%s\n", *result.Valid, *result.CName) // Validate all domains at once results, err := client.ValidateAllDomains(ctx, &fastly.ValidateAllDomainsInput{ ServiceID: serviceID, ServiceVersion: version, }) if err != nil { log.Fatal(err) } for _, r := range results { fmt.Printf(" %s valid=%v\n", *r.Metadata.Name, *r.Valid) } // List domains (optionally with staging IPs) domains, err := client.ListDomains(ctx, &fastly.ListDomainsInput{ ServiceID: serviceID, ServiceVersion: version, IncludeStagingIPs: true, }) if err != nil { log.Fatal(err) } for _, d := range domains { fmt.Println(" -", *d.Name) } ``` -------------------------------- ### Manage KV Stores with Go Client Source: https://context7.com/fastly/go-fastly/llms.txt Demonstrates creating, inserting, retrieving, listing, and deleting keys in a Fastly KV Store. Supports TTL, metadata, and conditional writes. ```go ctx := context.Background() // Create a KV store in a specific region store, err := client.CreateKVStore(ctx, &fastly.CreateKVStoreInput{ Name: "my-feature-flags", Location: "US", }) if err != nil { log.Fatal(err) } fmt.Println("Store ID:", store.StoreID) // Insert a key err = client.InsertKVStoreKey(ctx, &fastly.InsertKVStoreKeyInput{ StoreID: store.StoreID, Key: "feature:dark-mode", Value: "enabled", TimeToLiveSec: 3600, // expires in 1 hour Metadata: fastly.ToPointer("set by deploy pipeline"), }) if err != nil { log.Fatal(err) } // Retrieve a key's full item (value + metadata + generation) item, err := client.GetKVStoreItem(ctx, &fastly.GetKVStoreItemInput{ StoreID: store.StoreID, Key: "feature:dark-mode", }) if err != nil { log.Fatal(err) } val, err := item.ValueAsString() // closes item.Value automatically if err != nil { log.Fatal(err) } fmt.Printf("Value: %s Generation: %d Metadata: %s\n", val, item.Generation, item.Metadata) // Paginate through keys with a prefix filter pager := client.NewListKVStoreKeysPaginator(ctx, &fastly.ListKVStoreKeysInput{ StoreID: store.StoreID, Prefix: "feature:", Consistency: fastly.ConsistencyStrong, Limit: 100, }) for pager.Next() { for _, key := range pager.Keys() { fmt.Println(" key:", key) } } if err := pager.Err(); err != nil { log.Fatal(err) } // Conditional delete using generation marker err = client.DeleteKVStoreKey(ctx, &fastly.DeleteKVStoreKeyInput{ StoreID: store.StoreID, Key: "feature:dark-mode", IfGenerationMatch: item.Generation, }) if err != nil { log.Fatal(err) } ``` -------------------------------- ### Manage Edge Dictionaries and Items with Go Source: https://context7.com/fastly/go-fastly/llms.txt Shows how to create an Edge Dictionary, add a single item, and perform batch upserts of items. Requires an initialized Fastly client. ```go ctx := context.Background() serviceID := "SU1Z0isxPaozGVKXdv0eY" version := 3 // Create a dictionary dict, err := client.CreateDictionary(ctx, &fastly.CreateDictionaryInput{ ServiceID: serviceID, ServiceVersion: version, Name: fastly.ToPointer("redirects"), WriteOnly: fastly.ToPointer(fastly.Compatibool(false)), }) if err != nil { log.Fatal(err) } fmt.Println("Dictionary ID:", *dict.DictionaryID) // Add a single item item, err := client.CreateDictionaryItem(ctx, &fastly.CreateDictionaryItemInput{ ServiceID: serviceID, DictionaryID: *dict.DictionaryID, ItemKey: fastly.ToPointer("/old-path"), ItemValue: fastly.ToPointer("/new-path"), }) if err != nil { log.Fatal(err) } fmt.Printf("Item: %s -> %s\n", *item.ItemKey, *item.ItemValue) // Batch upsert up to 1000 items err = client.BatchModifyDictionaryItems(ctx, &fastly.BatchModifyDictionaryItemsInput{ ServiceID: serviceID, DictionaryID: *dict.DictionaryID, Items: []*fastly.BatchDictionaryItem{ { Operation: fastly.ToPointer(fastly.UpsertBatchOperation), ItemKey: fastly.ToPointer("/promo"), ItemValue: fastly.ToPointer("/sale"), }, { Operation: fastly.ToPointer(fastly.UpsertBatchOperation), ItemKey: fastly.ToPointer("/blog"), ItemValue: fastly.ToPointer("/articles"), }, }, }) if err != nil { log.Fatal(err) } fmt.Println("Batch upsert complete") ``` -------------------------------- ### Initialize go-fastly Client Source: https://context7.com/fastly/go-fastly/llms.txt Creates an authenticated HTTP client for the Fastly API. Reads API key from environment variables or accepts it directly. Debug mode can be enabled to log all HTTP traffic. ```go package main import ( "context" "fmt" "log" "os" "github.com/fastly/go-fastly/v15/fastly" ) func main() { // Using an explicit API key client, err := fastly.NewClient(os.Getenv("FASTLY_API_KEY")) if err != nil { log.Fatal(err) } // Or use DefaultClient (panics on error, intended for program startup) // client := fastly.DefaultClient() // Custom endpoint (e.g., for testing) // client, err = fastly.NewClientForEndpoint("my-key", "https://api.fastly.com") fmt.Println("Client address:", client.Address) // Output: Client address: https://api.fastly.com // Check rate limiting after any write operation fmt.Println("Writes remaining:", client.RateLimitRemaining()) fmt.Println("Rate limit resets at:", client.RateLimitReset()) ctx := context.Background() _ = ctx // used in subsequent calls } ``` -------------------------------- ### Manage Fastly Service Version Lifecycle Source: https://context7.com/fastly/go-fastly/llms.txt Demonstrates the core workflow for managing service versions: fetching the active version, cloning it for modification, validating the changes, and activating the new version. ```go package main import ( "context" "fmt" "log" "os" "github.com/fastly/go-fastly/v15/fastly" ) func main() { client, err := fastly.NewClient(os.Getenv("FASTLY_API_KEY")) if err != nil { log.Fatal(err) } ctx := context.Background() serviceID := "SU1Z0isxPaozGVKXdv0eY" // Fetch service metadata to find the active version service, err := client.GetService(&fastly.GetServiceInput{ServiceID: serviceID}) if err != nil { log.Fatal(err) } latest := service.Versions[len(service.Versions)-1] for _, v := range service.Versions { if *v.Active { latest = v break } } fmt.Printf("Active version: %d\n", *latest.Number) // Clone to get a new editable version version, err := client.CloneVersion(&fastly.CloneVersionInput{ ServiceID: serviceID, ServiceVersion: *latest.Number, }) if err != nil { log.Fatal(err) } fmt.Printf("Cloned to version: %d\n", *version.Number) // ... make changes to version.Number ... // Validate valid, msg, err := client.ValidateVersion(ctx, &fastly.ValidateVersionInput{ ServiceID: serviceID, ServiceVersion: *version.Number, }) if err != nil { log.Fatal(err) } if !valid { log.Fatalf("version invalid: %s", msg) } // Activate active, err := client.ActivateVersion(ctx, &fastly.ActivateVersionInput{ ServiceID: serviceID, ServiceVersion: *version.Number, }) if err != nil { log.Fatal(err) } fmt.Printf("Activated version %d, locked=%v\n", *active.Number, *active.Locked) // Output: Activated version 3, locked=true } ``` -------------------------------- ### Client Initialization Source: https://context7.com/fastly/go-fastly/llms.txt Creates an authenticated HTTP client for interacting with the Fastly API. Supports reading credentials from environment variables or explicit configuration. ```APIDOC ## Client Initialization ### `NewClient` / `DefaultClient` / `NewClientForEndpoint` Creates an authenticated HTTP client. `NewClient` reads `FASTLY_API_URL` from the environment for the endpoint (falling back to `https://api.fastly.com`) and accepts the API key directly. `DefaultClient` reads the key from `FASTLY_API_KEY`. `NewClientForEndpoint` allows supplying both key and endpoint explicitly. Setting `FASTLY_DEBUG_MODE=true` dumps all HTTP traffic. ```go package main import ( "context" "fmt" "log" "os" "github.com/fastly/go-fastly/v15/fastly" ) func main() { // Using an explicit API key client, err := fastly.NewClient(os.Getenv("FASTLY_API_KEY")) if err != nil { log.Fatal(err) } // Or use DefaultClient (panics on error, intended for program startup) // client := fastly.DefaultClient() // Custom endpoint (e.g., for testing) // client, err = fastly.NewClientForEndpoint("my-key", "https://api.fastly.com") fmt.Println("Client address:", client.Address) // Output: Client address: https://api.fastly.com // Check rate limiting after any write operation fmt.Println("Writes remaining:", client.RateLimitRemaining()) fmt.Println("Rate limit resets at:", client.RateLimitReset()) ctx := context.Background() _ = ctx // used in subsequent calls } ``` ``` -------------------------------- ### Manage Service Versions with Go Fastly Client Source: https://context7.com/fastly/go-fastly/llms.txt Demonstrates full lifecycle management of service configuration versions. Use `ListVersions` to see all versions, `LatestVersion` for the most recent, `LockVersion` to prevent edits, and `DeactivateVersion` to remove a version from production traffic. ```go ctx := context.Background() serviceID := "SU1Z0isxPaozGVKXdv0eY" // List all versions versions, err := client.ListVersions(ctx, &fastly.ListVersionsInput{ ServiceID: serviceID, }) if err != nil { log.Fatal(err) } for _, v := range versions { fmt.Printf("Version %d active=%v locked=%v\n", *v.Number, *v.Active, *v.Locked) } // Get the most recent version latest, err := client.LatestVersion(ctx, &fastly.LatestVersionInput{ServiceID: serviceID}) if err != nil { log.Fatal(err) } fmt.Println("Latest version number:", *latest.Number) // Lock a version to prevent edits locked, err := client.LockVersion(ctx, &fastly.LockVersionInput{ ServiceID: serviceID, ServiceVersion: *latest.Number, }) if err != nil { log.Fatal(err) } fmt.Println("Locked:", *locked.Locked) // Output: Locked: true // Deactivate a specific version deactivated, err := client.DeactivateVersion(ctx, &fastly.DeactivateVersionInput{ ServiceID: serviceID, ServiceVersion: *latest.Number, }) if err != nil { log.Fatal(err) } fmt.Println("Active after deactivate:", *deactivated.Active) // Output: Active after deactivate: false ``` -------------------------------- ### Manage Compute Package Deployment Source: https://context7.com/fastly/go-fastly/llms.txt Retrieve the currently deployed WebAssembly package for a Compute service. Upload a new package from a local file path or from in-memory bytes. ```go ctx := context.Background() serviceID := "SU1Z0isxPaozGVKXdv0eY" version := 3 // Retrieve the currently deployed package pkg, err := client.GetPackage(ctx, &fastly.GetPackageInput{ ServiceID: serviceID, ServiceVersion: version, }) if err != nil { log.Fatal(err) } if pkg.Metadata != nil { fmt.Printf("Package: %s language: %s size: %d bytes\n", *pkg.Metadata.Name, *pkg.Metadata.Language, *pkg.Metadata.Size) } // Upload a new package from a local file updated, err := client.UpdatePackage(ctx, &fastly.UpdatePackageInput{ ServiceID: serviceID, ServiceVersion: version, PackagePath: fastly.ToPointer("./pkg/main.tar.gz"), }) if err != nil { log.Fatal(err) } fmt.Println("Deployed package ID:", *updated.PackageID) // Upload from in-memory bytes (e.g. downloaded from a registry) packageBytes, _ := os.ReadFile("./pkg/main.tar.gz") updated, err = client.UpdatePackage(ctx, &fastly.UpdatePackageInput{ ServiceID: serviceID, ServiceVersion: version, PackageContent: packageBytes, }) if err != nil { log.Fatal(err) } fmt.Println("Deployed package from memory:", *updated.PackageID) ``` -------------------------------- ### Import Go Fastly Client Source: https://github.com/fastly/go-fastly/blob/main/README.md Import the Go Fastly client module to begin interacting with the Fastly API. Ensure you are using the correct version. ```go import "github.com/fastly/go-fastly/v15/fastly" ``` -------------------------------- ### Create and Update S3 Log Configuration Source: https://context7.com/fastly/go-fastly/llms.txt Configure Fastly to stream logs to an S3 bucket using IAM role authentication. Update the configuration to use access key credentials. ```go ctx := context.Background() serviceID := "SU1Z0isxPaozGVKXdv0eY" version := 3 s3Logger, err := client.CreateS3(ctx, &fastly.CreateS3Input{ ServiceID: serviceID, ServiceVersion: version, Name: fastly.ToPointer("prod-access-logs"), BucketName: fastly.ToPointer("my-fastly-logs"), IAMRole: fastly.ToPointer("arn:aws:iam::123456789012:role/FastlyLogsRole"), Path: fastly.ToPointer("/cdn/"), Period: fastly.ToPointer(3600), Format: fastly.ToPointer(`%h %l %u %t \"%r\" %>s %b`), FormatVersion: fastly.ToPointer(2), Redundancy: fastly.ToPointer(fastly.S3RedundancyStandard), ServerSideEncryption: fastly.ToPointer(fastly.S3ServerSideEncryptionAES), CompressionCodec: fastly.ToPointer("zstd"), MessageType: fastly.ToPointer("classic"), Placement: fastly.ToPointer("none"), }) if err != nil { log.Fatal(err) } fmt.Printf("S3 logger %q -> s3://%s%s\n", *s3Logger.Name, *s3Logger.BucketName, *s3Logger.Path) // Update to switch from IAM role to access key credentials updated, err := client.UpdateS3(ctx, &fastly.UpdateS3Input{ ServiceID: serviceID, ServiceVersion: version, Name: "prod-access-logs", AccessKey: fastly.ToPointer("AKIAIOSFODNN7EXAMPLE"), SecretKey: fastly.ToPointer("wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"), }) if err != nil { log.Fatal(err) } fmt.Println("Updated S3 logger:", *updated.Name) ``` -------------------------------- ### Configure Fastly Health Checks with Go Source: https://context7.com/fastly/go-fastly/llms.txt Shows how to create and update health checks for Fastly origins. Customize parameters like host, path, interval, and timeouts for effective probing. ```go ctx := context.Background() serviceID := "SU1Z0isxPaozGVKXdv0eY" version := 3 hc, err := client.CreateHealthCheck(ctx, &fastly.CreateHealthCheckInput{ ServiceID: serviceID, ServiceVersion: version, Name: fastly.ToPointer("origin-health"), Host: fastly.ToPointer("origin.example.com"), Path: fastly.ToPointer("/health"), Method: fastly.ToPointer("GET"), ExpectedResponse: fastly.ToPointer(200), CheckInterval: fastly.ToPointer(5000), // every 5 seconds Timeout: fastly.ToPointer(3000), // 3-second timeout Window: fastly.ToPointer(5), // last 5 results considered Threshold: fastly.ToPointer(3), // 3 of 5 must pass Initial: fastly.ToPointer(2), HTTPVersion: fastly.ToPointer("1.1"), Headers: &[]string{"Authorization: Bearer secret-token"}, }) if err != nil { log.Fatal(err) } fmt.Printf("Health check %q on path %s every %dms\n", *hc.Name, *hc.Path, *hc.CheckInterval) // Update the interval updated, err := client.UpdateHealthCheck(ctx, &fastly.UpdateHealthCheckInput{ ServiceID: serviceID, ServiceVersion: version, Name: "origin-health", CheckInterval: fastly.ToPointer(10000), }) if err != nil { log.Fatal(err) } fmt.Println("New interval:", *updated.CheckInterval) // Output: New interval: 10000 ``` -------------------------------- ### Run All Analysis Checks and Tests Source: https://github.com/fastly/go-fastly/blob/main/RELEASE.md Execute all analysis checks and tests to ensure code quality and stability before proceeding with a release. This command should be run locally. ```bash make all ``` -------------------------------- ### Resource-Level Serialization with Context Source: https://github.com/fastly/go-fastly/blob/main/SERIALIZATION.md Use `fastly.NewContextForResourceID` to create a context with a resource ID. Set this context in the `Input` structure for operations to enable resource-level serialization, allowing concurrent requests to distinct resources to execute in parallel. ```go import ( "context" "github.com/fastly/go-fastly/v15/fastly" ) client := fastly.DefaultClient() serviceID := '1234abcd' requestContext := fastly.NewContextForResourceID(context.TODO(), serviceID) client.CreateBackend(&fastly.CreateBackendInput { ServiceID: serviceID, ServiceVersion: 5, Name: fastly.ToPointer('test'), Address: fastly.ToPointer('example.com'), Context: requestContext }) ``` -------------------------------- ### Compute Package Management Source: https://context7.com/fastly/go-fastly/llms.txt Manage WebAssembly packages for Fastly Compute services, including uploading and retrieving package details. ```APIDOC ## Compute Package Deployment ### `GetPackage`, `UpdatePackage` Manages WebAssembly packages for Fastly Compute services. A package is a compiled `.tar.gz` Wasm bundle. It can be uploaded from a local file path or from in-memory bytes. ### GetPackage Example ```go ctx := context.Background() serviceID := "SU1Z0isxPaozGVKXdv0eY" version := 3 // Retrieve the currently deployed package pkg, err := client.GetPackage(ctx, &fastly.GetPackageInput{ ServiceID: serviceID, ServiceVersion: version, }) if err != nil { log.Fatal(err) } if pkg.Metadata != nil { fmt.Printf("Package: %s language: %s size: %d bytes\n", *pkg.Metadata.Name, *pkg.Metadata.Language, *pkg.Metadata.Size) } ``` ### UpdatePackage Example (from file path) ```go ctx := context.Background() serviceID := "SU1Z0isxPaozGVKXdv0eY" version := 3 // Upload a new package from a local file updated, err := client.UpdatePackage(ctx, &fastly.UpdatePackageInput{ ServiceID: serviceID, ServiceVersion: version, PackagePath: fastly.ToPointer("./pkg/main.tar.gz"), }) if err != nil { log.Fatal(err) } fmt.Println("Deployed package ID:", *updated.PackageID) ``` ### UpdatePackage Example (from in-memory bytes) ```go ctx := context.Background() serviceID := "SU1Z0isxPaozGVKXdv0eY" version := 3 // Upload from in-memory bytes (e.g. downloaded from a registry) packageBytes, _ := os.ReadFile("./pkg/main.tar.gz") updated, err = client.UpdatePackage(ctx, &fastly.UpdatePackageInput{ ServiceID: serviceID, ServiceVersion: version, PackageContent: packageBytes, }) if err != nil { log.Fatal(err) } fmt.Println("Deployed package from memory:", *updated.PackageID) ``` ``` -------------------------------- ### Create, List, and Delete Automation Tokens Source: https://context7.com/fastly/go-fastly/llms.txt Create a scoped automation token with specific roles and service access. List all existing tokens using the built-in paginator. Delete a token by its ID. ```go ctx := context.Background() // Create a scoped automation token (requires sudo capability) token, err := client.CreateAutomationToken(ctx, &fastly.CreateAutomationTokenInput{ Name: "deploy-bot", Role: fastly.EngineerRole, Scope: fastly.ToPointer(fastly.TokenScope("global")), Services: []string{"SU1Z0isxPaozGVKXdv0eY"}, TLSAccess: false, }) if err != nil { log.Fatal(err) } fmt.Printf("Token ID: %s AccessToken: %s\n", *token.TokenID, *token.AccessToken) // List all tokens using the built-in paginator tokens, err := client.ListAutomationTokens(ctx) if err != nil { log.Fatal(err) } for _, t := range tokens { fmt.Printf(" %s role=%s scope=%s\n", *t.Name, *t.Role, *t.Scope) } // Delete a token err = client.DeleteAutomationToken(ctx, &fastly.DeleteAutomationTokenInput{ TokenID: *token.TokenID, }) if err != nil { log.Fatal(err) } fmt.Println("Token deleted") ``` -------------------------------- ### Fastly Pointer Helper Functions Source: https://context7.com/fastly/go-fastly/llms.txt Utilize helper functions for managing pointer types in resource fields, distinguishing unset values from zero values, and handling JSON null serialization. ```go // ToPointer: wrap any scalar in a pointer name := fastly.ToPointer("my-backend") // *string port := fastly.ToPointer(443) // *int enabled := fastly.ToPointer(true) // *bool // ToValue: safe dereference (returns zero if nil) var maybePort *int fmt.Println(fastly.ToValue(maybePort)) // Output: 0 fmt.Println(fastly.ToValue(port)) // Output: 443 // NullString: returns nil for empty strings, pointer otherwise fmt.Println(fastly.NullString("")) // Output: fmt.Println(*fastly.NullString("hello")) // Output: hello // Nullable[T]: serialize to JSON null or a value type Payload struct { Description *fastly.Nullable[string] `json:"description"` } p1 := Payload{Description: fastly.NullValue[string]()} p2 := Payload{Description: fastly.NewNullable("hello")} b1, _ := json.Marshal(p1) b2, _ := json.Marshal(p2) fmt.Println(string(b1)) // Output: {"description":null} fmt.Println(string(b2)) // Output: {"description":"hello"} ``` -------------------------------- ### S3 Logging Configuration Source: https://context7.com/fastly/go-fastly/llms.txt Configure Fastly to stream access logs to an S3 bucket. Supports various authentication methods, encryption, and formatting options. ```APIDOC ## CreateS3, GetS3, UpdateS3, DeleteS3, ListS3s Configures Fastly to stream access logs to an S3 bucket. Supports IAM role authentication, server-side encryption (AES256 or KMS), storage class/redundancy selection, and custom Fastly log format strings. ### CreateS3 Example ```go ctx := context.Background() serviceID := "SU1Z0isxPaozGVKXdv0eY" version := 3 s3Logger, err := client.CreateS3(ctx, &fastly.CreateS3Input{ ServiceID: serviceID, ServiceVersion: version, Name: fastly.ToPointer("prod-access-logs"), BucketName: fastly.ToPointer("my-fastly-logs"), IAMRole: fastly.ToPointer("arn:aws:iam::123456789012:role/FastlyLogsRole"), Path: fastly.ToPointer("/cdn/"), Period: fastly.ToPointer(3600), Format: fastly.ToPointer(`%h %l %u %t \"%r\" %>s %b`), FormatVersion: fastly.ToPointer(2), Redundancy: fastly.ToPointer(fastly.S3RedundancyStandard), ServerSideEncryption: fastly.ToPointer(fastly.S3ServerSideEncryptionAES), CompressionCodec: fastly.ToPointer("zstd"), MessageType: fastly.ToPointer("classic"), Placement: fastly.ToPointer("none"), }) if err != nil { log.Fatal(err) } fmt.Printf("S3 logger %q -> s3://%s%s\n", *s3Logger.Name, *s3Logger.BucketName, *s3Logger.Path) ``` ### UpdateS3 Example (Switch to Access Key) ```go ctx := context.Background() serviceID := "SU1Z0isxPaozGVKXdv0eY" version := 3 updated, err := client.UpdateS3(ctx, &fastly.UpdateS3Input{ ServiceID: serviceID, ServiceVersion: version, Name: "prod-access-logs", AccessKey: fastly.ToPointer("AKIAIOSFODNN7EXAMPLE"), SecretKey: fastly.ToPointer("wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"), }) if err != nil { log.Fatal(err) } fmt.Println("Updated S3 logger:", *updated.Name) ``` ``` -------------------------------- ### Create and Push Signed Git Tag Source: https://github.com/fastly/go-fastly/blob/main/RELEASE.md Create a new signed Git tag for the release and push it to the remote repository. Replace {{remote}} with your Git remote name (e.g., origin or upstream). Ensure you have configured your signing key with Git. ```bash tag=vX.Y.Z && git tag -s $tag -m $tag && git push {{remote}} $tag ``` -------------------------------- ### Track Rate Limit Quota Source: https://context7.com/fastly/go-fastly/llms.txt The client automatically tracks rate limit headers. Use `RateLimitRemaining()` and `RateLimitReset()` to implement backpressure or observe remaining write quota after write operations. ```go ctx := context.Background() serviceID := "SU1Z0isxPaozGVKXdv0eY" v, err := client.LatestVersion(ctx, &fastly.LatestVersionInput{ServiceID: serviceID}) if err != nil { log.Fatal(err) } dict, err := client.GetDictionary(ctx, &fastly.GetDictionaryInput{ ServiceID: serviceID, ServiceVersion: *v.Number, Name: "my-dict", }) if err != nil { log.Fatal(err) } // After each write, check quota for i := 0; i < 5; i++ { _, err := client.UpdateDictionaryItem(ctx, &fastly.UpdateDictionaryItemInput{ ServiceID: serviceID, DictionaryID: *dict.DictionaryID, ItemKey: "counter", ItemValue: fmt.Sprintf("%d", i), }) if err != nil { log.Fatal(err) } fmt.Printf("Remaining writes: %d Reset at: %v\n", client.RateLimitRemaining(), client.RateLimitReset(), ) } ``` -------------------------------- ### Config Store Management Source: https://context7.com/fastly/go-fastly/llms.txt Manage non-versioned, globally available key-value stores linked to services. These are distinct from dictionaries and not tied to service versions. ```APIDOC ## Config Store Management ### CreateConfigStore **Description**: Creates a new configuration store. ### GetConfigStore **Description**: Retrieves a configuration store. ### UpdateConfigStore **Description**: Updates an existing configuration store. ### DeleteConfigStore **Description**: Deletes a configuration store. ### ListConfigStores **Description**: Lists all configuration stores. ### GetConfigStoreMetadata **Description**: Retrieves metadata for a configuration store, such as the item count. ### ListConfigStoreServices **Description**: Lists the services that are using a specific configuration store. ``` -------------------------------- ### Fix Next-Gen WAF Fixtures Source: https://github.com/fastly/go-fastly/blob/main/TESTING.md Run this command to update Next-Gen WAF fixtures with your specific workspace ID. Replace with your actual workspace ID. ```sh make fix-ngwaf-fixtures FASTLY_TEST_NGWAF_WORKSPACE_ID= ``` -------------------------------- ### KV Store Management Source: https://context7.com/fastly/go-fastly/llms.txt Manage globally consistent key-value stores independent of service versions. Supports various operations like creation, insertion, retrieval, and conditional deletion of keys. ```APIDOC ## KV Store Operations ### CreateKVStore **Description**: Creates a new KV store in a specified region. ### GetKVStore **Description**: Retrieves an existing KV store. ### ListKVStores **Description**: Lists all available KV stores. ### DeleteKVStore **Description**: Deletes a KV store. ### InsertKVStoreKey **Description**: Inserts a key-value pair into a KV store. Supports Time-To-Live (TTL) and metadata. ### GetKVStoreKey **Description**: Retrieves a key from a KV store. ### GetKVStoreItem **Description**: Retrieves a full KV store item, including value, metadata, and generation. ### DeleteKVStoreKey **Description**: Deletes a key from a KV store. Supports conditional deletion using generation matching. ### BatchModifyKVStoreKey **Description**: Performs batch modifications on KV store keys. ``` -------------------------------- ### Backend Management Source: https://context7.com/fastly/go-fastly/llms.txt Manage backend origins for a service. This includes creating, retrieving, updating, deleting, and listing backends. Backends support full TLS configuration, load balancing, health checks, and more. ```APIDOC ## CreateBackend, GetBackend, UpdateBackend, DeleteBackend, ListBackends Backends represent origin servers. Supports full TLS configuration, load balancing weight, health check association, TCP keepalives, and IPv6 preference. All settings are optional pointers allowing partial updates. ### CreateBackend Creates a new backend for a given service version. ### GetBackend Retrieves a specific backend for a given service version. ### UpdateBackend Updates an existing backend for a given service version. Supports partial updates. ### DeleteBackend Deletes a specific backend for a given service version. ### ListBackends Lists all backends for a given service version. #### Example Usage (Go) ```go ctx := context.Background() serviceID := "SU1Z0isxPaozGVKXdv0eY" version := 3 // Create a backend backend, err := client.CreateBackend(ctx, &fastly.CreateBackendInput{ ServiceID: serviceID, ServiceVersion: version, Name: fastly.ToPointer("my-origin"), Address: fastly.ToPointer("origin.example.com"), Port: fastly.ToPointer(443), UseSSL: fastly.ToPointer(fastly.Compatibool(true)), SSLCheckCert: fastly.ToPointer(fastly.Compatibool(true)), SSLCertHostname: fastly.ToPointer("origin.example.com"), ConnectTimeout: fastly.ToPointer(1000), FirstByteTimeout: fastly.ToPointer(15000), MaxConn: fastly.ToPointer(200), Weight: fastly.ToPointer(100), }) if err != nil { log.Fatal(err) } fmt.Println("Backend:", *backend.Name, "address:", *backend.Address) // List all backends on this version backends, err := client.ListBackends(ctx, &fastly.ListBackendsInput{ ServiceID: serviceID, ServiceVersion: version, }) if err != nil { log.Fatal(err) } for _, b := range backends { fmt.Printf(" %s -> %s:%d\n", *b.Name, *b.Address, *b.Port) } // Update a backend updated, err := client.UpdateBackend(ctx, &fastly.UpdateBackendInput{ ServiceID: serviceID, ServiceVersion: version, Name: "my-origin", MaxConn: fastly.ToPointer(500), Shield: fastly.ToPointer("iad-va-us"), }) if err != nil { log.Fatal(err) } fmt.Println("Updated max_conn:", *updated.MaxConn) // Output: Updated max_conn: 500 // Delete a backend err = client.DeleteBackend(ctx, &fastly.DeleteBackendInput{ ServiceID: serviceID, ServiceVersion: version, Name: "my-origin", }) if err != nil { log.Fatal(err) } ``` ```