or run

tessl search
Log in

Version

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
golangpkg:golang/cloud.google.com/go/kms@v1.24.0

docs

autokey-client.mdcore-types.mdekm-client.mdenums.mdindex.mdinventory-clients.mditerators.mdkey-management-client.mdoperations.mdrequest-response-types.md
tile.json

tessl/golang-cloud-google-com--go--kms

tessl install tessl/golang-cloud-google-com--go--kms@1.24.0

Go Client Library for Google Cloud Key Management Service (KMS) API for managing cryptographic keys and performing cryptographic operations

iterators.mddocs/

Iterator Types and Pagination

Overview

KMS list operations return iterator types for efficient pagination through large result sets. All iterators follow the same pattern and provide three methods for accessing results: Next(), PageInfo(), and All().

Packages:

  • cloud.google.com/go/kms/apiv1 - Main KMS iterators
  • cloud.google.com/go/kms/inventory/apiv1 - Inventory iterators

Iterator Pattern

Basic Usage with Next()

import "google.golang.org/api/iterator"

it := client.ListCryptoKeys(ctx, req)
for {
    item, err := it.Next()
    if err == iterator.Done {
        break
    }
    if err != nil {
        // Handle error
    }
    // Use item
}

Range Loop with All() (Go 1.23+)

it := client.ListCryptoKeys(ctx, req)
for item, err := range it.All() {
    if err != nil {
        // Handle error
    }
    // Use item
}

Page-Based Iteration

it := client.ListCryptoKeys(ctx, req)
pageInfo := it.PageInfo()
pageInfo.MaxSize = 50 // Items per page

for pageInfo.HasNext() {
    page := make([]*kmspb.CryptoKey, 0, pageInfo.PageSize())
    nextPageToken, err := iterator.NewPager(it, pageInfo.PageSize(), "").NextPage(&page)
    if err != nil {
        // Handle error
    }
    // Process page
    for _, item := range page {
        // Use item
    }
}

KMS Iterators

CryptoKeyIterator

type CryptoKeyIterator struct {
    Response interface{} // Raw response for current page (cast to RPC response type)
    InternalFetch func(pageSize int, pageToken string) (results []*kmspb.CryptoKey, nextPageToken string, err error)
}

Manages a stream of *kmspb.CryptoKey for paginated list results.

Methods:

func (it *CryptoKeyIterator) Next() (*kmspb.CryptoKey, error)
func (it *CryptoKeyIterator) PageInfo() *iterator.PageInfo
func (it *CryptoKeyIterator) All() iter.Seq2[*kmspb.CryptoKey, error]

Returned By:

  • KeyManagementClient.ListCryptoKeys()
  • KeyDashboardClient.ListCryptoKeys()

Example:

req := &kmspb.ListCryptoKeysRequest{
    Parent:   "projects/my-project/locations/us-central1/keyRings/my-keyring",
    PageSize: 100,
}

it := client.ListCryptoKeys(ctx, req)
count := 0
for {
    key, err := it.Next()
    if err == iterator.Done {
        break
    }
    if err != nil {
        log.Fatal(err)
    }
    count++
    fmt.Printf("CryptoKey %d: %s\n", count, key.Name)
}
fmt.Printf("Total: %d keys\n", count)

CryptoKeyVersionIterator

type CryptoKeyVersionIterator struct {
    Response interface{}
    InternalFetch func(pageSize int, pageToken string) (results []*kmspb.CryptoKeyVersion, nextPageToken string, err error)
}

Manages a stream of *kmspb.CryptoKeyVersion for paginated list results.

Methods:

func (it *CryptoKeyVersionIterator) Next() (*kmspb.CryptoKeyVersion, error)
func (it *CryptoKeyVersionIterator) PageInfo() *iterator.PageInfo
func (it *CryptoKeyVersionIterator) All() iter.Seq2[*kmspb.CryptoKeyVersion, error]

Returned By:

  • KeyManagementClient.ListCryptoKeyVersions()

Example:

req := &kmspb.ListCryptoKeyVersionsRequest{
    Parent: "projects/my-project/locations/us-central1/keyRings/my-keyring/cryptoKeys/my-key",
}

it := client.ListCryptoKeyVersions(ctx, req)
for {
    version, err := it.Next()
    if err == iterator.Done {
        break
    }
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Version: %s (State: %v)\n", version.Name, version.State)
}

KeyRingIterator

type KeyRingIterator struct {
    Response interface{}
    InternalFetch func(pageSize int, pageToken string) (results []*kmspb.KeyRing, nextPageToken string, err error)
}

Manages a stream of *kmspb.KeyRing for paginated list results.

Methods:

func (it *KeyRingIterator) Next() (*kmspb.KeyRing, error)
func (it *KeyRingIterator) PageInfo() *iterator.PageInfo
func (it *KeyRingIterator) All() iter.Seq2[*kmspb.KeyRing, error]

Returned By:

  • KeyManagementClient.ListKeyRings()

ImportJobIterator

type ImportJobIterator struct {
    Response interface{}
    InternalFetch func(pageSize int, pageToken string) (results []*kmspb.ImportJob, nextPageToken string, err error)
}

Manages a stream of *kmspb.ImportJob for paginated list results.

Methods:

func (it *ImportJobIterator) Next() (*kmspb.ImportJob, error)
func (it *ImportJobIterator) PageInfo() *iterator.PageInfo
func (it *ImportJobIterator) All() iter.Seq2[*kmspb.ImportJob, error]

Returned By:

  • KeyManagementClient.ListImportJobs()

KeyHandleIterator

type KeyHandleIterator struct {
    Response interface{}
    InternalFetch func(pageSize int, pageToken string) (results []*kmspb.KeyHandle, nextPageToken string, err error)
}

Manages a stream of *kmspb.KeyHandle for paginated list results.

Methods:

func (it *KeyHandleIterator) Next() (*kmspb.KeyHandle, error)
func (it *KeyHandleIterator) PageInfo() *iterator.PageInfo
func (it *KeyHandleIterator) All() iter.Seq2[*kmspb.KeyHandle, error]

Returned By:

  • AutokeyClient.ListKeyHandles()

EkmConnectionIterator

type EkmConnectionIterator struct {
    Response interface{}
    InternalFetch func(pageSize int, pageToken string) (results []*kmspb.EkmConnection, nextPageToken string, err error)
}

Manages a stream of *kmspb.EkmConnection for paginated list results.

Methods:

func (it *EkmConnectionIterator) Next() (*kmspb.EkmConnection, error)
func (it *EkmConnectionIterator) PageInfo() *iterator.PageInfo
func (it *EkmConnectionIterator) All() iter.Seq2[*kmspb.EkmConnection, error]

Returned By:

  • EkmClient.ListEkmConnections()

LocationIterator

type LocationIterator struct {
    Response interface{}
    InternalFetch func(pageSize int, pageToken string) (results []*locationpb.Location, nextPageToken string, err error)
}

Manages a stream of *locationpb.Location for paginated list results.

Methods:

func (it *LocationIterator) Next() (*locationpb.Location, error)
func (it *LocationIterator) PageInfo() *iterator.PageInfo
func (it *LocationIterator) All() iter.Seq2[*locationpb.Location, error]

Returned By:

  • KeyManagementClient.ListLocations()
  • AutokeyClient.ListLocations()
  • AutokeyAdminClient.ListLocations()
  • EkmClient.ListLocations()
  • KeyDashboardClient.ListLocations()
  • KeyTrackingClient.ListLocations()

Inventory Iterators

ProtectedResourceIterator

type ProtectedResourceIterator struct {
    Response interface{}
    InternalFetch func(pageSize int, pageToken string) (results []*inventorypb.ProtectedResource, nextPageToken string, err error)
}

Manages a stream of *inventorypb.ProtectedResource for search results.

Methods:

func (it *ProtectedResourceIterator) Next() (*inventorypb.ProtectedResource, error)
func (it *ProtectedResourceIterator) PageInfo() *iterator.PageInfo
func (it *ProtectedResourceIterator) All() iter.Seq2[*inventorypb.ProtectedResource, error]

Returned By:

  • KeyTrackingClient.SearchProtectedResources()

Example:

import "cloud.google.com/go/kms/inventory/apiv1/inventorypb"

req := &inventorypb.SearchProtectedResourcesRequest{
    Scope:     "organizations/123456789",
    CryptoKey: "projects/my-project/locations/us-central1/keyRings/my-keyring/cryptoKeys/my-key",
    PageSize:  100,
}

it := trackingClient.SearchProtectedResources(ctx, req)
for {
    resource, err := it.Next()
    if err == iterator.Done {
        break
    }
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Protected: %s (%s in %s)\n", resource.Name, resource.ResourceType, resource.Location)
}

PageInfo Methods

All iterators provide a PageInfo() method that returns *iterator.PageInfo:

type PageInfo struct {
    // MaxSize is the maximum number of items returned per page.
    // If zero or negative, the iterator will determine a reasonable page size.
    MaxSize int

    // Token is the page token to use for the next request.
    Token string
}

func (p *PageInfo) HasNext() bool
func (p *PageInfo) Remaining() int
func (p *PageInfo) PageSize() int

Example:

it := client.ListCryptoKeys(ctx, req)
pageInfo := it.PageInfo()
pageInfo.MaxSize = 50 // Request 50 items per page

for pageInfo.HasNext() {
    key, err := it.Next()
    if err != nil {
        log.Fatal(err)
    }
    // Process key
}

Advanced Patterns

Collecting All Results

func collectAllKeys(it *CryptoKeyIterator) ([]*kmspb.CryptoKey, error) {
    var keys []*kmspb.CryptoKey
    for {
        key, err := it.Next()
        if err == iterator.Done {
            break
        }
        if err != nil {
            return nil, err
        }
        keys = append(keys, key)
    }
    return keys, nil
}

Filtering While Iterating

func findEnabledVersions(it *CryptoKeyVersionIterator) ([]*kmspb.CryptoKeyVersion, error) {
    var enabled []*kmspb.CryptoKeyVersion
    for {
        version, err := it.Next()
        if err == iterator.Done {
            break
        }
        if err != nil {
            return nil, err
        }
        if version.State == kmspb.CryptoKeyVersion_ENABLED {
            enabled = append(enabled, version)
        }
    }
    return enabled, nil
}

Paginated Processing

func processInBatches(it *CryptoKeyIterator, batchSize int) error {
    pageInfo := it.PageInfo()
    pageInfo.MaxSize = batchSize

    batch := make([]*kmspb.CryptoKey, 0, batchSize)
    for {
        key, err := it.Next()
        if err == iterator.Done {
            if len(batch) > 0 {
                // Process final batch
                if err := processBatch(batch); err != nil {
                    return err
                }
            }
            break
        }
        if err != nil {
            return err
        }

        batch = append(batch, key)
        if len(batch) >= batchSize {
            // Process batch
            if err := processBatch(batch); err != nil {
                return err
            }
            batch = batch[:0] // Reset batch
        }
    }
    return nil
}

Early Termination

func findFirstMatchingKey(it *CryptoKeyIterator, predicate func(*kmspb.CryptoKey) bool) (*kmspb.CryptoKey, error) {
    for {
        key, err := it.Next()
        if err == iterator.Done {
            return nil, nil // Not found
        }
        if err != nil {
            return nil, err
        }
        if predicate(key) {
            return key, nil
        }
    }
}

// Usage
key, err := findFirstMatchingKey(it, func(k *kmspb.CryptoKey) bool {
    return k.Purpose == kmspb.CryptoKey_ENCRYPT_DECRYPT
})

Counting Results

func countItems(it *CryptoKeyIterator) (int, error) {
    count := 0
    for {
        _, err := it.Next()
        if err == iterator.Done {
            break
        }
        if err != nil {
            return 0, err
        }
        count++
    }
    return count, nil
}

Error Handling

it := client.ListCryptoKeys(ctx, req)
for {
    key, err := it.Next()
    if err == iterator.Done {
        // Normal completion
        break
    }
    if err != nil {
        // Check for specific error types
        if status.Code(err) == codes.PermissionDenied {
            log.Printf("Permission denied: %v", err)
            return err
        }
        // Handle other errors
        return fmt.Errorf("iteration error: %w", err)
    }
    // Process key
}

Best Practices

  1. Always check for iterator.Done to detect normal completion
  2. Set PageSize appropriately - too small causes many API calls, too large may timeout
  3. Handle errors immediately - don't accumulate results before checking errors
  4. Use context cancellation - iterators respect context timeouts
  5. Don't reuse iterators - create a new iterator for each list operation
  6. Access Response field for raw pagination data if needed

Performance Considerations

  1. Page Size - Default is typically 300, adjust based on needs (max varies by API)
  2. Network Calls - Each Next() call after a page boundary makes a new API call
  3. Memory Usage - Large page sizes use more memory
  4. Latency - Smaller pages mean more round trips

See Also

  • KeyManagementClient
  • Inventory Clients
  • google.golang.org/api/iterator