This is an automated email from the ASF dual-hosted git repository.

zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-go.git


The following commit(s) were added to refs/heads/main by this push:
     new 2f4cb2831 fix(rest): take renewal expiry from the vended credential 
(#2182)
2f4cb2831 is described below

commit 2f4cb2831b63ed7b217fed756a4fd4d0c2536424
Author: Revanth <[email protected]>
AuthorDate: Wed Oct 14 11:13:59 2026 -0500

    fix(rest): take renewal expiry from the vended credential (#2182)
    
    * fix(rest): take renewal expiry from the vended credential
    
    * test(rest): pin vended expiry at Create, Register and Load
---
 catalog/rest/refresh_table_credentials_test.go | 108 ++++++++++++++++++++-----
 catalog/rest/rest.go                           |  21 +++--
 catalog/rest/vended_creds.go                   |  45 ++++++-----
 catalog/rest/vended_creds_test.go              |  86 ++++++++++++++++----
 4 files changed, 195 insertions(+), 65 deletions(-)

diff --git a/catalog/rest/refresh_table_credentials_test.go 
b/catalog/rest/refresh_table_credentials_test.go
index 3170efd66..5f46bc899 100644
--- a/catalog/rest/refresh_table_credentials_test.go
+++ b/catalog/rest/refresh_table_credentials_test.go
@@ -24,10 +24,12 @@ import (
        "net/http"
        "net/http/httptest"
        "net/url"
+       "strconv"
        "strings"
        "sync"
        "sync/atomic"
        "testing"
+       "time"
 
        "github.com/apache/iceberg-go"
        "github.com/apache/iceberg-go/catalog"
@@ -580,9 +582,9 @@ func tableResponseFSProps(t *testing.T, scheme, metadataLoc 
string, tableConfig,
 // table-wide merge sites, where config is the whole table config rather than a
 // per-location copy. The table's FileIO serves only the metadata location's
 // account, so a vended adls.token drops what would apply to that account ahead
-// of it or set its lifetime: that account's SAS token and connection string,
-// any shared key, and every inherited credential expiry. Another account's 
SAS token and
-// connection string never apply to it and are kept.
+// of it: that account's SAS token and connection string, and any shared key.
+// Another account's SAS token and connection string never apply to it and are
+// kept.
 func TestTableResponseVendedADLSTokenClearsShadowingCredentials(t *testing.T) {
        const (
                scheme    = "restcreds-table-adls"
@@ -595,15 +597,12 @@ func 
TestTableResponseVendedADLSTokenClearsShadowingCredentials(t *testing.T) {
                map[string]string{
                        // The factory would sign this account's requests with 
another
                        // account's shared key.
-                       iceio.ADLSSharedKeyAccountName:              "other",
-                       iceio.ADLSSharedKeyAccountKey:               
"other-key",
-                       iceio.ADLSSasTokenPrefix + host:             
"stale-sas",
-                       "adls.sas-token-expires-at-ms." + host:      "1000",
-                       iceio.ADLSConnectionStringPrefix + "acct":   
"stale-conn",
-                       iceio.ADLSSasTokenPrefix + otherHost:        
"other-sas",
-                       "adls.sas-token-expires-at-ms." + otherHost: "1000",
-                       iceio.ADLSConnectionStringPrefix + "other":  
"other-conn",
-                       "expiration-time":                           "1000",
+                       iceio.ADLSSharedKeyAccountName:             "other",
+                       iceio.ADLSSharedKeyAccountKey:              "other-key",
+                       iceio.ADLSSasTokenPrefix + host:            "stale-sas",
+                       iceio.ADLSConnectionStringPrefix + "acct":  
"stale-conn",
+                       iceio.ADLSSasTokenPrefix + otherHost:       "other-sas",
+                       iceio.ADLSConnectionStringPrefix + "other": 
"other-conn",
                },
                map[string]string{iceio.ADLSToken: "vended-token"})
 
@@ -617,18 +616,89 @@ func 
TestTableResponseVendedADLSTokenClearsShadowingCredentials(t *testing.T) {
                } {
                        assert.NotContains(t, props, k, "%s: credential %q 
would be selected ahead of the token", name, k)
                }
-               for _, k := range []string{
-                       "adls.sas-token-expires-at-ms." + host,
-                       "adls.sas-token-expires-at-ms." + otherHost,
-                       "expiration-time",
-               } {
-                       assert.NotContains(t, props, k, "%s: inherited expiry 
%q would set the token's lifetime", name, k)
-               }
                assert.Equal(t, "other-sas", 
props[iceio.ADLSSasTokenPrefix+otherHost], name)
                assert.Equal(t, "other-conn", 
props[iceio.ADLSConnectionStringPrefix+"other"], name)
        }
 }
 
+// TestTableResponseExpiryComesFromVendedCredential checks that a table's 
FileIO
+// renews on the expiry of the credential vended with it, not on an expiry
+// inherited from the table config or on the default TTL. The inherited one has
+// already passed, so taking it would refetch credentials on every load; the
+// default TTL would keep an expired vended credential until the TTL elapses.
+func TestTableResponseExpiryComesFromVendedCredential(t *testing.T) {
+       const scheme = "restcreds-table-expiry"
+
+       rec := &ioPropsRecorder{}
+       rec.register(t, scheme)
+
+       metadataLoc := scheme + 
"://warehouse/database/table/metadata/00000-a.metadata.json"
+
+       for _, ec := range []struct {
+               name         string
+               vendedExpiry string
+               wantKey      string
+               wantFetches  int32
+       }{
+               {
+                       name:         "valid vend ignores stale config 
expiries",
+                       vendedExpiry: 
strconv.FormatInt(time.Now().Add(time.Hour).UnixMilli(), 10),
+                       wantKey:      "vended-key",
+               },
+               {
+                       // Already past, so the next FileIO use must go back to 
the catalog.
+                       name:         "expired vend renews",
+                       vendedExpiry: "1",
+                       wantKey:      "renewed-key",
+                       wantFetches:  1,
+               },
+       } {
+               t.Run(ec.name, func(t *testing.T) {
+                       respond := func(w http.ResponseWriter, _ *http.Request) 
{
+                               body := 
storageCredentialsBody(scheme+"://warehouse/database/table", map[string]string{
+                                       iceio.S3AccessKeyID:              
"vended-key",
+                                       "s3.session-token-expires-at-ms": 
ec.vendedExpiry,
+                               })
+                               body["metadata-location"] = metadataLoc
+                               body["metadata"] = 
json.RawMessage(strings.ReplaceAll(
+                                       exampleTableMetadataNoSnapshotV1, 
"s3://", scheme+"://"))
+                               body["config"] = map[string]string{
+                                       "gcs.oauth2.token-expires-at": "1000",
+                                       "expiration-time":             "1000",
+                               }
+                               assert.NoError(t, 
json.NewEncoder(w).Encode(body))
+                       }
+
+                       var credsCalls atomic.Int32
+                       cat := newCredsTestCatalog(t, credsCatalogOpts{
+                               creds: func(w http.ResponseWriter, _ 
*http.Request) {
+                                       credsCalls.Add(1)
+                                       assert.NoError(t, 
json.NewEncoder(w).Encode(storageCredentialsBody(
+                                               
scheme+"://warehouse/database/table",
+                                               
map[string]string{iceio.S3AccessKeyID: "renewed-key"})))
+                               },
+                               loadTable: respond,
+                               routes: map[string]http.HandlerFunc{
+                                       "/v1/namespaces/db/tables":   respond,
+                                       "/v1/namespaces/db/register": respond,
+                               },
+                       })
+
+                       for _, tc := range tableResponseCalls {
+                               before := credsCalls.Load()
+                               tbl, err := tc.call(context.Background(), cat)
+                               require.NoError(t, err, tc.name)
+                               for range 2 {
+                                       _, err = tbl.FS(context.Background())
+                                       require.NoError(t, err, tc.name)
+                               }
+                               assert.Equal(t, ec.wantFetches, 
credsCalls.Load()-before, tc.name)
+                               assert.Equal(t, ec.wantKey, 
rec.lastLoad(t)[iceio.S3AccessKeyID], tc.name)
+                       }
+               })
+       }
+}
+
 // TestTableResponseLayersPartialS3Credential pins the existing behavior at the
 // table-wide merge sites: a partial vended S3 credential is layered over the
 // table config rather than replacing the key pair there. Whether a partial
diff --git a/catalog/rest/rest.go b/catalog/rest/rest.go
index e90c8599c..62024c49d 100644
--- a/catalog/rest/rest.go
+++ b/catalog/rest/rest.go
@@ -1287,6 +1287,7 @@ func (r *Catalog) tableFromResponse(
        config iceberg.Properties,
        scanPlanningConfig iceberg.Properties,
        credsVended bool,
+       vended iceberg.Properties,
        labels *iceberg.Labels,
        opts ...table.Option,
 ) (*table.Table, error) {
@@ -1297,6 +1298,7 @@ func (r *Catalog) tableFromResponse(
                        identifier: identifier,
                        location:   loc,
                        props:      config,
+                       vended:     vended,
                        fetchCreds: func(ctx context.Context, ident []string) 
(iceberg.Properties, error) {
                                return r.fetchTableCreds(ctx, ident, loc)
                        },
@@ -1413,7 +1415,7 @@ func (r *Catalog) RefreshTableCredentials(ctx 
context.Context, tbl *table.Table)
                opts = append(opts, table.WithMetricsReporter(reporter))
        }
 
-       return r.tableFromResponse(ctx, tbl.Identifier(), tbl.Metadata(), 
metadataLoc, config, scanCfg, true, tbl.Labels(), opts...)
+       return r.tableFromResponse(ctx, tbl.Identifier(), tbl.Metadata(), 
metadataLoc, config, scanCfg, true, resp, tbl.Labels(), opts...)
 }
 
 type identifierPageFetcher func(pageToken string) ([]table.Identifier, string, 
error)
@@ -1636,9 +1638,10 @@ func (r *Catalog) CreateTable(ctx context.Context, 
identifier table.Identifier,
        maps.Copy(saved, ret.Config)
        scanPlanningConfig := maps.Clone(config)
        credsVended := len(ret.StorageCredentials) > 0
-       mergeVendedCredentials(config, 
resolveStorageCredentials(ret.StorageCredentials, ret.MetadataLoc), 
ret.MetadataLoc)
+       vended := resolveStorageCredentials(ret.StorageCredentials, 
ret.MetadataLoc)
+       mergeVendedCredentials(config, vended, ret.MetadataLoc)
 
-       return r.tableFromResponse(ctx, identifier, ret.Metadata, 
ret.MetadataLoc, config, scanPlanningConfig, credsVended, ret.Labels, 
table.WithSavedConfig(saved))
+       return r.tableFromResponse(ctx, identifier, ret.Metadata, 
ret.MetadataLoc, config, scanPlanningConfig, credsVended, vended, ret.Labels, 
table.WithSavedConfig(saved))
 }
 
 // commitStagedCreate performs the second phase of a staged table
@@ -1866,9 +1869,10 @@ func (r *Catalog) RegisterTable(ctx context.Context, 
identifier table.Identifier
        maps.Copy(saved, ret.Config)
        scanPlanningConfig := maps.Clone(config)
        credsVended := len(ret.StorageCredentials) > 0
-       mergeVendedCredentials(config, 
resolveStorageCredentials(ret.StorageCredentials, ret.MetadataLoc), 
ret.MetadataLoc)
+       vended := resolveStorageCredentials(ret.StorageCredentials, 
ret.MetadataLoc)
+       mergeVendedCredentials(config, vended, ret.MetadataLoc)
 
-       return r.tableFromResponse(ctx, identifier, ret.Metadata, 
ret.MetadataLoc, config, scanPlanningConfig, credsVended, ret.Labels, 
table.WithSavedConfig(saved))
+       return r.tableFromResponse(ctx, identifier, ret.Metadata, 
ret.MetadataLoc, config, scanPlanningConfig, credsVended, vended, ret.Labels, 
table.WithSavedConfig(saved))
 }
 
 // LoadTable loads a table from the catalog. It implements [catalog.Catalog].
@@ -1914,9 +1918,10 @@ func (r *Catalog) loadTableWithMode(ctx context.Context, 
identifier table.Identi
        maps.Copy(saved, ret.Config)
        scanPlanningConfig := maps.Clone(config)
        credsVended := len(ret.StorageCredentials) > 0
-       mergeVendedCredentials(config, 
resolveStorageCredentials(ret.StorageCredentials, ret.MetadataLoc), 
ret.MetadataLoc)
+       vended := resolveStorageCredentials(ret.StorageCredentials, 
ret.MetadataLoc)
+       mergeVendedCredentials(config, vended, ret.MetadataLoc)
 
-       return r.tableFromResponse(ctx, identifier, ret.Metadata, 
ret.MetadataLoc, config, scanPlanningConfig, credsVended, ret.Labels, 
table.WithSavedConfig(saved))
+       return r.tableFromResponse(ctx, identifier, ret.Metadata, 
ret.MetadataLoc, config, scanPlanningConfig, credsVended, vended, ret.Labels, 
table.WithSavedConfig(saved))
 }
 
 func (r *Catalog) UpdateTable(ctx context.Context, ident table.Identifier, 
requirements []table.Requirement, updates []table.Update) (*table.Table, error) 
{
@@ -1965,7 +1970,7 @@ func (r *Catalog) UpdateTable(ctx context.Context, ident 
table.Identifier, requi
        maps.Copy(config, metadata.Properties())
 
        // A commit response carries no labels (they are load-time enrichment).
-       return r.tableFromResponse(ctx, ident, metadata, ret.MetadataLoc, 
config, config, false, nil, table.WithSavedConfig(metadata.Properties()))
+       return r.tableFromResponse(ctx, ident, metadata, ret.MetadataLoc, 
config, config, false, nil, nil, table.WithSavedConfig(metadata.Properties()))
 }
 
 func (r *Catalog) DropTable(ctx context.Context, identifier table.Identifier) 
error {
diff --git a/catalog/rest/vended_creds.go b/catalog/rest/vended_creds.go
index e42c1c53f..76737a34c 100644
--- a/catalog/rest/vended_creds.go
+++ b/catalog/rest/vended_creds.go
@@ -126,6 +126,11 @@ type vendedCredentialRefresher struct {
        identifier []string
        location   string
        props      iceberg.Properties
+       // vended is the credential config resolved for location at table load. 
The
+       // first IO's expiry is read from it alone, and each renewal's from the
+       // credential that renewal fetched. props also carries catalog and table
+       // config, whose expiries belong to other credentials or to an earlier 
vend.
+       vended iceberg.Properties
        // credentials is populated only for scan-plan IO. Unlike table-load
        // credentials, which are already resolved against the metadata 
location,
        // plan credentials must be selected against every file path opened 
later.
@@ -155,6 +160,7 @@ func (v *vendedCredentialRefresher) loadFS(ctx 
context.Context) (iceio.IO, error
        }
 
        var config iceberg.Properties
+       vended := v.vended
        switch {
        case v.cachedIO == nil:
                config = v.props
@@ -180,6 +186,7 @@ func (v *vendedCredentialRefresher) loadFS(ctx 
context.Context) (iceio.IO, error
 
                config = maps.Clone(v.props)
                mergeVendedCredentials(config, freshCreds, v.location)
+               vended = freshCreds
        }
 
        // The IO is cached and shared by every later caller, so it must not
@@ -220,7 +227,7 @@ func (v *vendedCredentialRefresher) loadFS(ctx 
context.Context) (iceio.IO, error
                }
 
                newIO = loaded
-               expiresAt = v.expiresAtFromConfig(config)
+               expiresAt = v.expiresAtFrom(config, vended)
                issuedAt = v.now()
        }
 
@@ -282,18 +289,25 @@ func (v *vendedCredentialRefresher) refreshBuffer() 
time.Duration {
        return buffer
 }
 
-func (v *vendedCredentialRefresher) expiresAtFromConfig(config 
iceberg.Properties) time.Time {
+// expiresAtFrom returns when the IO built from config expires. A refreshable
+// IO takes the expiry of vended, the credential it was built with, or the
+// default TTL without one: config's other expiries belong to other credentials
+// or an earlier vend, and an already-passed one would refetch on every load.
+func (v *vendedCredentialRefresher) expiresAtFrom(config, vended 
iceberg.Properties) time.Time {
        if len(v.credentials) > 0 {
                return time.Time{}
        }
 
-       if exp, ok := parseCredentialExpiry(config); ok {
+       // No re-fetch to trigger, so the fallback TTL doesn't apply: without an
+       // expiry in config, never expires.
+       if v.fetchCreds == nil {
+               exp, _ := parseCredentialExpiry(config)
+
                return exp
        }
 
-       // No re-fetch to trigger, so the fallback TTL doesn't apply: never 
expires.
-       if v.fetchCreds == nil {
-               return time.Time{}
+       if exp, ok := parseCredentialExpiry(vended); ok {
+               return exp
        }
 
        return v.now().Add(defaultVendedCredentialsTTL)
@@ -450,17 +464,11 @@ func (p *prefixScopedIO) propertiesForLocation(name 
string) iceberg.Properties {
 // config, the properties an IO for location is built from. Every site that
 // merges storage credentials goes through here.
 //
-// A nonempty adls.token is the one case that also removes properties. config 
is
+// A nonempty adls.token is the one case that also removes properties:
+// credentials the Azure FileIO selects ahead of the token would shadow it and
+// the read would 403; see adlsauth.ClearTokenShadowingCredentials. config is
 // always a copy built for one IO, and the Azure FileIO serves only location's
-// storage account, so the removals cannot reach another account's IO:
-//   - Credentials the Azure FileIO selects ahead of the token would shadow it 
and
-//     the read would 403; see adlsauth.ClearTokenShadowingCredentials.
-//   - Every inherited credential expiry is dropped, whatever credential or
-//     account it was for. The IO's renewal takes the earliest expiry in 
config,
-//     so any of them would set the token's lifetime in place of the expiry
-//     vended with the token, or the default TTL without one. A server that
-//     vends adls.token for a location outside Azure is misconfigured; its IO
-//     loses inherited expiries too.
+// storage account, so the removals cannot reach another account's IO.
 //
 // Unlike the S3 and GCS clearing in clearOverriddenCredentialProperties, which
 // keys on property presence, this keys on a nonempty value: the Azure FileIO
@@ -470,11 +478,6 @@ func mergeVendedCredentials(config, credentialConfig 
iceberg.Properties, locatio
        if credentialConfig[iceio.ADLSToken] != "" {
                if acct, ok := adlsauth.AccountFor(location); ok {
                        adlsauth.ClearTokenShadowingCredentials(config, acct)
-                       for key := range config {
-                               if isCredentialExpiryKey(key) {
-                                       delete(config, key)
-                               }
-                       }
                }
        }
 
diff --git a/catalog/rest/vended_creds_test.go 
b/catalog/rest/vended_creds_test.go
index 615f1eaa5..463f71da5 100644
--- a/catalog/rest/vended_creds_test.go
+++ b/catalog/rest/vended_creds_test.go
@@ -20,6 +20,7 @@ package rest
 import (
        "context"
        "errors"
+       "maps"
        "net/url"
        "strconv"
        "sync"
@@ -291,10 +292,13 @@ func TestParseCredentialExpiry(t *testing.T) {
        }
 }
 
-func TestVendedCredsExpiresAtFromConfig(t *testing.T) {
+func TestVendedCredsExpiresAtFrom(t *testing.T) {
        t.Parallel()
 
        now := time.Now()
+       refreshable := func(context.Context, []string) (iceberg.Properties, 
error) {
+               return nil, nil
+       }
 
        t.Run("uses server-provided expiry", func(t *testing.T) {
                t.Parallel()
@@ -306,23 +310,41 @@ func TestVendedCredsExpiresAtFromConfig(t *testing.T) {
                        mu:      semaphore.NewWeighted(1),
                        nowFunc: func() time.Time { return now },
                }
-               got := r.expiresAtFromConfig(config)
+               got := r.expiresAtFrom(config, nil)
                assert.Equal(t, serverExpiry.UnixMilli(), got.UnixMilli())
        })
 
        t.Run("refreshable creds fall back to default 60m when no expiry key", 
func(t *testing.T) {
                t.Parallel()
                r := &vendedCredentialRefresher{
-                       mu:      semaphore.NewWeighted(1),
-                       nowFunc: func() time.Time { return now },
-                       fetchCreds: func(context.Context, []string) 
(iceberg.Properties, error) {
-                               return nil, nil
-                       },
+                       mu:         semaphore.NewWeighted(1),
+                       nowFunc:    func() time.Time { return now },
+                       fetchCreds: refreshable,
                }
-               got := r.expiresAtFromConfig(iceberg.Properties{})
+               got := r.expiresAtFrom(iceberg.Properties{}, 
iceberg.Properties{})
                assert.Equal(t, now.Add(60*time.Minute).UnixMilli(), 
got.UnixMilli())
        })
 
+       t.Run("refreshable creds take expiry from the vended credential only", 
func(t *testing.T) {
+               t.Parallel()
+               vendedExpiry := now.Add(30 * time.Minute)
+               stale := strconv.FormatInt(now.Add(-time.Hour).UnixMilli(), 10)
+               config := iceberg.Properties{
+                       keyGcsOAuthExpiresAt:  stale,
+                       keyExpirationTime:     stale,
+                       keyS3TokenExpiresAtMs: 
strconv.FormatInt(vendedExpiry.UnixMilli(), 10),
+               }
+               r := &vendedCredentialRefresher{
+                       mu:         semaphore.NewWeighted(1),
+                       nowFunc:    func() time.Time { return now },
+                       fetchCreds: refreshable,
+               }
+               got := r.expiresAtFrom(config, iceberg.Properties{
+                       keyS3TokenExpiresAtMs: 
strconv.FormatInt(vendedExpiry.UnixMilli(), 10),
+               })
+               assert.Equal(t, vendedExpiry.UnixMilli(), got.UnixMilli())
+       })
+
        t.Run("non-refreshable creds without expiry never expire", func(t 
*testing.T) {
                t.Parallel()
                // fetchCreds nil: no re-fetch to trigger, so no fallback TTL — 
zero time.
@@ -330,11 +352,47 @@ func TestVendedCredsExpiresAtFromConfig(t *testing.T) {
                        mu:      semaphore.NewWeighted(1),
                        nowFunc: func() time.Time { return now },
                }
-               got := r.expiresAtFromConfig(iceberg.Properties{})
+               got := r.expiresAtFrom(iceberg.Properties{}, nil)
                assert.True(t, got.IsZero())
        })
 }
 
+// TestVendedCredsRenewalIgnoresEarlierVendExpiry checks that a renewal whose
+// credential has no expiry gets the default TTL. props still carries the first
+// vend's expiration-time, which has passed; taking it would refetch 
credentials
+// and rebuild the IO on every load.
+func TestVendedCredsRenewalIgnoresEarlierVendExpiry(t *testing.T) {
+       t.Parallel()
+
+       now := time.Now()
+       firstVend := iceberg.Properties{
+               iceio.S3AccessKeyID: "first-key",
+               keyExpirationTime:   
strconv.FormatInt(now.Add(-time.Minute).UnixMilli(), 10),
+       }
+
+       var fetches atomic.Int32
+       r := newTestRefresher(func(context.Context, []string) 
(iceberg.Properties, error) {
+               fetches.Add(1)
+
+               return iceberg.Properties{iceio.S3AccessKeyID: "renewed-key"}, 
nil
+       })
+       r.nowFunc = func() time.Time { return now }
+       r.props = maps.Clone(firstVend)
+       r.vended = firstVend
+       // Force the refresh branch: a cached IO whose credentials have expired.
+       r.cachedIO = iceio.LocalFS{}
+       r.expiresAt = now.Add(-time.Minute)
+
+       _, err := r.loadFS(context.Background())
+       require.NoError(t, err)
+       assert.Equal(t, now.Add(defaultVendedCredentialsTTL).UnixMilli(), 
r.expiresAt.UnixMilli())
+
+       _, err = r.loadFS(context.Background())
+       require.NoError(t, err)
+       assert.Equal(t, int32(1), fetches.Load(),
+               "the renewed credential is valid, so the next load must reuse 
the IO")
+}
+
 func TestVendedCredsServerExpiryUsedOnRefresh(t *testing.T) {
        t.Parallel()
 
@@ -705,11 +763,8 @@ func TestPrefixScopedIOClearsStaleADLSAuthForVendedToken(t 
*testing.T) {
                iceio.ADLSSharedKeyAccountName:             "acct",
                iceio.ADLSSharedKeyAccountKey:              "stale-key",
                iceio.ADLSSasTokenPrefix + host:            "stale-sas",
-               keyAdlsSasExpiresAtMs + "." + host:         "1000",
-               keyAdlsSasExpiresAtMs:                      "1000",
                iceio.ADLSConnectionStringPrefix + "acct":  
"stale-connection-string",
                iceio.ADLSSasTokenPrefix + otherHost:       "other-sas",
-               keyAdlsSasExpiresAtMs + "." + otherHost:    "1000",
                iceio.ADLSConnectionStringPrefix + "other": 
"other-connection-string",
        }, []StorageCredential{{
                Prefix: "abfss://container@" + host + "/",
@@ -727,13 +782,10 @@ func 
TestPrefixScopedIOClearsStaleADLSAuthForVendedToken(t *testing.T) {
        assert.NotContains(t, props, iceio.ADLSSharedKeyAccountName)
        assert.NotContains(t, props, iceio.ADLSSharedKeyAccountKey)
        assert.NotContains(t, props, iceio.ADLSSasTokenPrefix+host)
-       assert.NotContains(t, props, keyAdlsSasExpiresAtMs+"."+host)
-       assert.NotContains(t, props, keyAdlsSasExpiresAtMs)
        assert.NotContains(t, props, iceio.ADLSConnectionStringPrefix+"acct")
 
-       // Another account's SAS expiry would still set this IO's expiry, so it 
goes;
-       // its SAS token and connection string never apply here and are kept.
-       assert.NotContains(t, props, keyAdlsSasExpiresAtMs+"."+otherHost)
+       // Another account's SAS token and connection string never apply here 
and
+       // are kept.
        assert.Equal(t, "other-sas", props[iceio.ADLSSasTokenPrefix+otherHost])
        assert.Equal(t, "other-connection-string", 
props[iceio.ADLSConnectionStringPrefix+"other"])
 }

Reply via email to