diff --git a/option/internaloption/parsed_client_options.go b/option/internaloption/parsed_client_options.go new file mode 100644 index 00000000000..f91fcb68d60 --- /dev/null +++ b/option/internaloption/parsed_client_options.go @@ -0,0 +1,38 @@ +// Copyright 2025 Google LLC. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Package internaloption contains options used internally by Google client code. +package internaloption + +import ( + "google.golang.org/api/internal" + "google.golang.org/api/option" +) + +type ParsedOptions struct { + internal.DialSettings +} + +// ParseClientOptions validates the given option.ClientOption slice and returns +// ParsedOptions with the resolved settings. It returns an error if the +// provided options are invalid. +// +// This function allows other Google Cloud client libraries to read configuration +// values set by users via ClientOptions, which are otherwise unreadable outside of +// google.golang.org/api. +func ParseClientOptions(opts []option.ClientOption) (*ParsedOptions, error) { + var ds internal.DialSettings + // Apply all options to the internal DialSettings struct. + for _, opt := range opts { + opt.Apply(&ds) + } + + // Validate the combined settings. + if err := ds.Validate(); err != nil { + return nil, err + } + + return &ParsedOptions{ + DialSettings: ds, + }, nil +} diff --git a/option/internaloption/parsed_client_options_test.go b/option/internaloption/parsed_client_options_test.go new file mode 100644 index 00000000000..87875c4f8fe --- /dev/null +++ b/option/internaloption/parsed_client_options_test.go @@ -0,0 +1,41 @@ +// Copyright 2025 Google LLC. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package internaloption + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "google.golang.org/api/option" +) + +func TestParseClientOptions(t *testing.T) { + testEndpoint := "test.example.com" + testAPIKey := "testAPIKey" + testScopes := []string{"scope1", "scope2"} + + opts := []option.ClientOption{ + option.WithEndpoint(testEndpoint), + option.WithAPIKey(testAPIKey), + option.WithScopes(testScopes...), + } + po, err := ParseClientOptions(opts) + if err != nil { + t.Fatalf("ParseClientOptions(%v) err = %v, want nil", opts, err) + } + + if po.Endpoint != testEndpoint { + t.Errorf("po.Endpoint = %q, want %q", po.Endpoint, testEndpoint) + } + if po.APIKey != testAPIKey { + t.Errorf("po.APIKey = %q, want %q", po.APIKey, testAPIKey) + } + if !cmp.Equal(po.Scopes, testScopes) { + t.Errorf("po.Scopes diff (-got +want):\n%s", cmp.Diff(po.Scopes, testScopes)) + } + if po.UserAgent != "" { + t.Errorf("po.UserAgent != nil, got %q", po.UserAgent) + } +}