mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2026-07-24 09:39:08 +03:00
Compare commits
10 Commits
chore/secr
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0aaf6f8a33 | ||
|
|
00a26b9d32 | ||
|
|
43d4cc61dc | ||
|
|
e85d61a98c | ||
|
|
588e996bd5 | ||
|
|
edb702e326 | ||
|
|
84c2d86a00 | ||
|
|
2da774b8ad | ||
|
|
650cf31f32 | ||
|
|
3dfb3336f9 |
6
.github/workflows/codeql-analysis-go.yml
vendored
6
.github/workflows/codeql-analysis-go.yml
vendored
@@ -54,14 +54,14 @@ jobs:
|
||||
restore-keys: go-artifacts-${{ runner.os }}-codeql-analyze-${{ steps.go.outputs.go-version }}-
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
|
||||
uses: github/codeql-action/init@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
|
||||
with:
|
||||
languages: go
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
|
||||
uses: github/codeql-action/autobuild@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
|
||||
uses: github/codeql-action/analyze@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
|
||||
with:
|
||||
category: 'language:go'
|
||||
|
||||
@@ -75,10 +75,13 @@ type GroupAlerts struct {
|
||||
// ApiRule represents a Rule for web view
|
||||
// see https://github.com/prometheus/compliance/blob/main/alert_generator/specification.md#get-apiv1rules
|
||||
type ApiRule struct {
|
||||
// State must be one of these under following scenarios
|
||||
// "pending": at least 1 alert in the rule in pending state and no other alert in firing ruleState.
|
||||
// "firing": at least 1 alert in the rule in firing state.
|
||||
// "inactive": no alert in the rule in firing or pending state.
|
||||
// Rule state must be one of these under following scenarios:
|
||||
// "pending": at least 1 alert in the rule in pending state and no other alert in firing state. (only for alerting rules)
|
||||
// "firing": at least 1 alert in the rule in firing state. (only for alerting rules)
|
||||
// "inactive": rule's last evaluation was successful but no alert in the rule in firing or pending state. (only for alerting rules)
|
||||
// "unhealthy": rule's last evaluation was failed with error. (for both alerting and recording rules)
|
||||
// "nomatch": rule's last evaluation was successful but no time series matched the rule's expression. (for both alerting and recording rules)
|
||||
// "ok": the recording rule's last evaluation was successful. (only for recording rules)
|
||||
State string `json:"state"`
|
||||
Name string `json:"name"`
|
||||
// Query represents Rule's `expression` field
|
||||
@@ -237,6 +240,7 @@ func NewAlertAPI(ar *AlertingRule, a *notifier.Alert) *ApiAlert {
|
||||
}
|
||||
|
||||
func (r *ApiRule) ExtendState() {
|
||||
// if alerting rule already has alerts, then state is already set to either "pending" or "firing" and we don't need to change it
|
||||
if len(r.Alerts) > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ func (rh *requestHandler) handler(w http.ResponseWriter, r *http.Request) bool {
|
||||
}
|
||||
WriteRule(w, r, rule)
|
||||
return true
|
||||
// current used by old vmalert UI and Grafana Alerts
|
||||
// used by old vmalert UI
|
||||
case "/vmalert/groups", "/rules":
|
||||
rf, err := newRulesFilter(r)
|
||||
if err != nil {
|
||||
@@ -128,6 +128,8 @@ func (rh *requestHandler) handler(w http.ResponseWriter, r *http.Request) bool {
|
||||
state = rf.states[0]
|
||||
rf.states = rf.states[:1]
|
||||
}
|
||||
// enable extendedStates by default for vmalert UI
|
||||
rf.extendedStates = true
|
||||
lr := rh.groups(rf)
|
||||
WriteListGroups(w, r, lr.Data.Groups, state)
|
||||
return true
|
||||
@@ -543,6 +545,8 @@ func (rh *requestHandler) groups(rf *rulesFilter) *listGroupsResponse {
|
||||
if !groupFound && !strings.Contains(strings.ToLower(rule.Name), rf.search) {
|
||||
continue
|
||||
}
|
||||
// extendedStates is used by the vmalert UI to extend the rule state with values such as "nomatch" and "unhealthy".
|
||||
// those states are not supported by Grafana and not part of the Prometheus API spec yet
|
||||
if rf.extendedStates {
|
||||
rule.ExtendState()
|
||||
}
|
||||
|
||||
@@ -130,9 +130,12 @@
|
||||
data-bs-target="#item-{%s g.ID %}"
|
||||
>
|
||||
<span class="d-flex gap-2">
|
||||
{% if g.States["unhealthy"] > 0 %}<span class="badge bg-danger" title="Number of rules with status Error">{%d g.States["unhealthy"] %}</span> {% endif %}
|
||||
{% if g.States["nomatch"] > 0 %}<span class="badge bg-warning" title="Number of rules with status NoMatch">{%d g.States["nomatch"] %}</span> {% endif %}
|
||||
<span class="badge bg-success" title="Number of rules with status Ok">{%d g.States["ok"] %}</span>
|
||||
{% if g.States["inactive"] > 0 %}<span class="badge bg-light text-success border border-success" title="None of the alert instances is in a pending or firing state">{%d g.States["inactive"] %} inactive</span> {% endif %}
|
||||
{% if g.States["pending"] > 0 %}<span class="badge bg-warning text-dark" title="At least one alert instance is pending">{%d g.States["pending"] %} pending</span> {% endif %}
|
||||
{% if g.States["firing"] > 0 %}<span class="badge bg-danger" title="At least one alert instance is firing">{%d g.States["firing"] %} firing</span> {% endif %}
|
||||
{% if g.States["ok"] > 0 %}<span class="badge bg-success" title="Recording rule last evaluation succeeded">{%d g.States["ok"] %} ok</span>{% endif %}
|
||||
{% if g.States["unhealthy"] > 0 %}<span class="badge bg-danger" title="Last evaluation failed with an error">{%d g.States["unhealthy"] %} unhealthy</span> {% endif %}
|
||||
{% if g.States["nomatch"] > 0 %}<span class="badge bg-warning" title="Rule expression matched no time series">{%d g.States["nomatch"] %} nomatch</span> {% endif %}
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
@@ -169,7 +172,7 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="w-60">Rule</th>
|
||||
<th scope="col" class="w-20" class="text-center" title="How many series were produced by the rule">Series</th>
|
||||
<th scope="col" class="w-20" class="text-center" title="How many series were produced by the rule">Series Returned</th>
|
||||
<th scope="col" class="w-20" class="text-center" title="How many seconds ago rule was executed">Updated</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -188,8 +191,21 @@
|
||||
{% else %}
|
||||
<b>record:</b> {%s r.Name %}
|
||||
{% endif %}
|
||||
|
|
||||
{% if r.State == "inactive" %}
|
||||
<span><a class="badge bg-success">{%s r.State %}</a></span>
|
||||
{% elseif r.State == "pending" %}
|
||||
<span><a class="badge bg-warning">{%s r.State %}</a></span>
|
||||
{% elseif r.State == "firing" %}
|
||||
<span><a class="badge bg-danger">{%s r.State %}</a></span>
|
||||
{% elseif r.State == "ok" %}
|
||||
<span><a class="badge bg-success">{%s r.State %}</a></span>
|
||||
{% elseif r.State == "unhealthy" %}
|
||||
<span><a class="badge bg-danger">{%s r.State %}</a></span>
|
||||
{% elseif r.State == "nomatch" %}
|
||||
<span><a class="badge bg-warning">{%s r.State %}</a></span>
|
||||
{% endif %}
|
||||
{%= seriesFetchedWarn(prefix, &r) %}
|
||||
|
|
||||
<span><a target="_blank" href="{%s prefix+r.WebLink() %}">Details</a></span>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
import { FC, useEffect, useRef, useState } from "preact/compat";
|
||||
import { FC, useEffect, useRef } from "preact/compat";
|
||||
import { useTimeDispatch } from "../../../../state/time/TimeStateContext";
|
||||
import { getAppModeEnable } from "../../../../utils/app-mode";
|
||||
import Button from "../../../Main/Button/Button";
|
||||
@@ -9,27 +9,38 @@ import classNames from "classnames";
|
||||
import Tooltip from "../../../Main/Tooltip/Tooltip";
|
||||
import useDeviceDetect from "../../../../hooks/useDeviceDetect";
|
||||
import useBoolean from "../../../../hooks/useBoolean";
|
||||
import { getMillisecondsFromDuration } from "../../../../utils/time";
|
||||
import { useSearchParams } from "react-router";
|
||||
|
||||
interface AutoRefreshOption {
|
||||
seconds: number
|
||||
title: string
|
||||
}
|
||||
|
||||
const delayOptions: AutoRefreshOption[] = [
|
||||
{ seconds: 0, title: "Off" },
|
||||
{ seconds: 1, title: "1s" },
|
||||
{ seconds: 2, title: "2s" },
|
||||
{ seconds: 5, title: "5s" },
|
||||
{ seconds: 10, title: "10s" },
|
||||
{ seconds: 30, title: "30s" },
|
||||
{ seconds: 60, title: "1m" },
|
||||
{ seconds: 300, title: "5m" },
|
||||
{ seconds: 900, title: "15m" },
|
||||
{ seconds: 1800, title: "30m" },
|
||||
{ seconds: 3600, title: "1h" },
|
||||
{ seconds: 7200, title: "2h" }
|
||||
const delayOptions = [
|
||||
"Off",
|
||||
"1s",
|
||||
"2s",
|
||||
"5s",
|
||||
"10s",
|
||||
"30s",
|
||||
"1m",
|
||||
"5m",
|
||||
"15m",
|
||||
"30m",
|
||||
"1h",
|
||||
"2h"
|
||||
];
|
||||
|
||||
const DEFAULT_OPTION = delayOptions[0];
|
||||
|
||||
const MIN_REFRESH_MS = 1000;
|
||||
const MAX_REFRESH_MS = getMillisecondsFromDuration(delayOptions[delayOptions.length - 1]);
|
||||
const REFRESH_URL_PARAM = "refresh";
|
||||
|
||||
const durationToMs = (dur: string | null) => {
|
||||
return dur ? getMillisecondsFromDuration(dur) : 0;
|
||||
};
|
||||
|
||||
const isValidDelay = (ms: number) => {
|
||||
return ms >= MIN_REFRESH_MS && ms <= MAX_REFRESH_MS;
|
||||
};
|
||||
|
||||
interface ExecutionControlsProps {
|
||||
tooltip: string;
|
||||
useAutorefresh?: boolean;
|
||||
@@ -38,12 +49,14 @@ interface ExecutionControlsProps {
|
||||
|
||||
export const ExecutionControls: FC<ExecutionControlsProps> = ({ tooltip, useAutorefresh, closeModal }) => {
|
||||
const { isMobile } = useDeviceDetect();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
|
||||
const dispatch = useTimeDispatch();
|
||||
const appModeEnable = getAppModeEnable();
|
||||
const [autoRefresh, setAutoRefresh] = useState(false);
|
||||
|
||||
const [selectedDelay, setSelectedDelay] = useState<AutoRefreshOption>(delayOptions[0]);
|
||||
const rawDelay = searchParams.get(REFRESH_URL_PARAM);
|
||||
const msDelay = durationToMs(rawDelay);
|
||||
const selectedDelay = isValidDelay(msDelay) ? rawDelay : DEFAULT_OPTION;
|
||||
|
||||
const {
|
||||
value: openOptions,
|
||||
@@ -52,11 +65,20 @@ export const ExecutionControls: FC<ExecutionControlsProps> = ({ tooltip, useAuto
|
||||
} = useBoolean(false);
|
||||
const optionsButtonRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const handleChange = (d: AutoRefreshOption) => {
|
||||
if ((autoRefresh && !d.seconds) || (!autoRefresh && d.seconds)) {
|
||||
setAutoRefresh(prev => !prev);
|
||||
}
|
||||
setSelectedDelay(d);
|
||||
const handleChange = (dur: string) => () => {
|
||||
setSearchParams(prev => {
|
||||
const nextParams = new URLSearchParams(prev);
|
||||
const ms = durationToMs(dur);
|
||||
|
||||
if (ms) {
|
||||
nextParams.set(REFRESH_URL_PARAM, `${dur}`);
|
||||
} else {
|
||||
nextParams.delete(REFRESH_URL_PARAM);
|
||||
}
|
||||
|
||||
return nextParams;
|
||||
});
|
||||
|
||||
handleCloseOptions();
|
||||
};
|
||||
|
||||
@@ -68,23 +90,19 @@ export const ExecutionControls: FC<ExecutionControlsProps> = ({ tooltip, useAuto
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const delay = selectedDelay.seconds;
|
||||
const ms = durationToMs(selectedDelay);
|
||||
let timer: number;
|
||||
if (autoRefresh) {
|
||||
|
||||
if (useAutorefresh && isValidDelay(ms)) {
|
||||
timer = setInterval(() => {
|
||||
dispatch({ type: "RUN_QUERY" });
|
||||
}, delay * 1000) as unknown as number;
|
||||
} else {
|
||||
setSelectedDelay(delayOptions[0]);
|
||||
}, ms) as unknown as number;
|
||||
}
|
||||
return () => {
|
||||
timer && clearInterval(timer);
|
||||
};
|
||||
}, [selectedDelay, autoRefresh]);
|
||||
|
||||
const createHandlerChange = (d: AutoRefreshOption) => () => {
|
||||
handleChange(d);
|
||||
};
|
||||
return () => {
|
||||
clearInterval(timer);
|
||||
};
|
||||
}, [selectedDelay, useAutorefresh]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -106,7 +124,7 @@ export const ExecutionControls: FC<ExecutionControlsProps> = ({ tooltip, useAuto
|
||||
<span className="vm-mobile-option__icon"><RestartIcon/></span>
|
||||
<div className="vm-mobile-option-text">
|
||||
<span className="vm-mobile-option-text__label">Auto-refresh</span>
|
||||
<span className="vm-mobile-option-text__value">{selectedDelay.title}</span>
|
||||
<span className="vm-mobile-option-text__value">{selectedDelay}</span>
|
||||
</div>
|
||||
<span className="vm-mobile-option__arrow"><ArrowDownIcon/></span>
|
||||
</div>
|
||||
@@ -139,7 +157,7 @@ export const ExecutionControls: FC<ExecutionControlsProps> = ({ tooltip, useAuto
|
||||
)}
|
||||
onClick={toggleOpenOptions}
|
||||
>
|
||||
{selectedDelay.title}
|
||||
{selectedDelay}
|
||||
</Button>
|
||||
</div>
|
||||
</Tooltip>
|
||||
@@ -187,12 +205,12 @@ export const ExecutionControls: FC<ExecutionControlsProps> = ({ tooltip, useAuto
|
||||
className={classNames({
|
||||
"vm-list-item": true,
|
||||
"vm-list-item_mobile": isMobile,
|
||||
"vm-list-item_active": d.seconds === selectedDelay.seconds
|
||||
"vm-list-item_active": d === selectedDelay
|
||||
})}
|
||||
key={d.seconds}
|
||||
onClick={createHandlerChange(d)}
|
||||
key={d}
|
||||
onClick={handleChange(d)}
|
||||
>
|
||||
{d.title}
|
||||
{d}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import dayjs from "dayjs";
|
||||
import { getNanoTimestamp, parseSupportedDuration } from "./time";
|
||||
import { getMillisecondsFromDuration, getNanoTimestamp, parseSupportedDuration } from "./time";
|
||||
|
||||
describe("Time utils", () => {
|
||||
describe("getNanoTimestamp", () => {
|
||||
@@ -82,4 +82,19 @@ describe("Time utils", () => {
|
||||
expect(parseSupportedDuration(" ")).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("getMillisecondsFromDuration", () => {
|
||||
it("should convert valid durations to milliseconds", () => {
|
||||
expect(getMillisecondsFromDuration("1s")).toBe(1000);
|
||||
expect(getMillisecondsFromDuration("1.5s")).toBe(1500);
|
||||
expect(getMillisecondsFromDuration("1m30s")).toBe(90000);
|
||||
expect(getMillisecondsFromDuration("1h 30m")).toBe(5400000);
|
||||
expect(getMillisecondsFromDuration("500ms")).toBe(500);
|
||||
});
|
||||
|
||||
it("should return zero when duration cannot be parsed", () => {
|
||||
expect(getMillisecondsFromDuration("garbage")).toBe(0);
|
||||
expect(getMillisecondsFromDuration("")).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -100,6 +100,10 @@ export const getSecondsFromDuration = (dur: string) => {
|
||||
return dayjs.duration(durObject).asSeconds();
|
||||
};
|
||||
|
||||
export const getMillisecondsFromDuration = (dur: string): number => {
|
||||
return getSecondsFromDuration(dur) * 1000;
|
||||
};
|
||||
|
||||
const instantQueryViews = [DisplayType.table, DisplayType.code];
|
||||
export const getStepFromDuration = (dur: number, histogram?: boolean, displayType?: DisplayType): string => {
|
||||
if (displayType && instantQueryViews.includes(displayType)) return roundStep(dur);
|
||||
@@ -276,4 +280,3 @@ export const getNanoTimestamp = (dateStr: string): bigint => {
|
||||
// Return the full timestamp in nanoseconds as a BigInt
|
||||
return BigInt(baseMs) * 1000000n + BigInt(extraNano);
|
||||
};
|
||||
|
||||
|
||||
@@ -5136,6 +5136,110 @@
|
||||
],
|
||||
"title": "Major page faults rate ($instance)",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "$ds"
|
||||
},
|
||||
"description": "Average duration of fsync system calls. Spikes or high latency indicates that storage I/O cannot keep up with the write rate, which may slow down data ingestion.\n\nIf this value is elevated:\n- Check disk-related metrics.\n- If using cloud storage, check IOPS and throughput limits.\n- If using NFS, check network performance, server resource usage, and any errors on the NFS server side.\n- Check for known bugs in the filesystem or kernel version being used.",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"axisSoftMin": 0,
|
||||
"barAlignment": 0,
|
||||
"barWidthFactor": 0.6,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 0,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"insertNulls": false,
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "never",
|
||||
"showValues": false,
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"links": [],
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "s"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 305
|
||||
},
|
||||
"id": 230,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [
|
||||
"lastNotNull",
|
||||
"max"
|
||||
],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true,
|
||||
"sortBy": "Last *",
|
||||
"sortDesc": true
|
||||
},
|
||||
"tooltip": {
|
||||
"hideZeros": true,
|
||||
"mode": "multi",
|
||||
"sort": "desc"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "12.2.0",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "$ds"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"expr": "rate(vm_filestream_fsync_duration_seconds_total{job=~\"$job_storage\", instance=~\"$instance\"}[$__rate_interval]) / rate(vm_filestream_fsync_calls_total{job=~\"$job_storage\", instance=~\"$instance\"}[$__rate_interval])",
|
||||
"format": "time_series",
|
||||
"instant": false,
|
||||
"legendFormat": "{{instance}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Fsync avg duration ($instance)",
|
||||
"type": "timeseries"
|
||||
}
|
||||
],
|
||||
"title": "Troubleshooting",
|
||||
|
||||
@@ -5181,6 +5181,110 @@
|
||||
],
|
||||
"title": "Major page faults rate",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "$ds"
|
||||
},
|
||||
"description": "Average duration of fsync system calls. Spikes or high latency indicates that storage I/O cannot keep up with the write rate, which may slow down data ingestion.\n\nIf this value is elevated:\n- Check disk-related metrics.\n- If using cloud storage, check IOPS and throughput limits.\n- If using NFS, check network performance, server resource usage, and any errors on the NFS server side.\n- Check for known bugs in the filesystem or kernel version being used.",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"axisSoftMin": 0,
|
||||
"barAlignment": 0,
|
||||
"barWidthFactor": 0.6,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 0,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"insertNulls": false,
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "never",
|
||||
"showValues": false,
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"links": [],
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "s"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 81
|
||||
},
|
||||
"id": 159,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [
|
||||
"lastNotNull",
|
||||
"max"
|
||||
],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true,
|
||||
"sortBy": "Last *",
|
||||
"sortDesc": true
|
||||
},
|
||||
"tooltip": {
|
||||
"hideZeros": true,
|
||||
"mode": "multi",
|
||||
"sort": "desc"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "12.2.0",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "$ds"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"expr": "rate(vm_filestream_fsync_duration_seconds_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]) / rate(vm_filestream_fsync_calls_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])",
|
||||
"format": "time_series",
|
||||
"instant": false,
|
||||
"legendFormat": "{{instance}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Fsync avg duration ($instance)",
|
||||
"type": "timeseries"
|
||||
}
|
||||
],
|
||||
"title": "Troubleshooting",
|
||||
@@ -8742,4 +8846,4 @@
|
||||
"uid": "wNf0q_kZk",
|
||||
"version": 1,
|
||||
"weekStart": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5137,6 +5137,110 @@
|
||||
],
|
||||
"title": "Major page faults rate ($instance)",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "victoriametrics-metrics-datasource",
|
||||
"uid": "$ds"
|
||||
},
|
||||
"description": "Average duration of fsync system calls. Spikes or high latency indicates that storage I/O cannot keep up with the write rate, which may slow down data ingestion.\n\nIf this value is elevated:\n- Check disk-related metrics.\n- If using cloud storage, check IOPS and throughput limits.\n- If using NFS, check network performance, server resource usage, and any errors on the NFS server side.\n- Check for known bugs in the filesystem or kernel version being used.",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"axisSoftMin": 0,
|
||||
"barAlignment": 0,
|
||||
"barWidthFactor": 0.6,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 0,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"insertNulls": false,
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "never",
|
||||
"showValues": false,
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"links": [],
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "s"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 305
|
||||
},
|
||||
"id": 230,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [
|
||||
"lastNotNull",
|
||||
"max"
|
||||
],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true,
|
||||
"sortBy": "Last *",
|
||||
"sortDesc": true
|
||||
},
|
||||
"tooltip": {
|
||||
"hideZeros": true,
|
||||
"mode": "multi",
|
||||
"sort": "desc"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "12.2.0",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "victoriametrics-metrics-datasource",
|
||||
"uid": "$ds"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"expr": "rate(vm_filestream_fsync_duration_seconds_total{job=~\"$job_storage\", instance=~\"$instance\"}[$__rate_interval]) / rate(vm_filestream_fsync_calls_total{job=~\"$job_storage\", instance=~\"$instance\"}[$__rate_interval])",
|
||||
"format": "time_series",
|
||||
"instant": false,
|
||||
"legendFormat": "{{instance}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Fsync avg duration ($instance)",
|
||||
"type": "timeseries"
|
||||
}
|
||||
],
|
||||
"title": "Troubleshooting",
|
||||
|
||||
@@ -5182,6 +5182,110 @@
|
||||
],
|
||||
"title": "Major page faults rate",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "victoriametrics-metrics-datasource",
|
||||
"uid": "$ds"
|
||||
},
|
||||
"description": "Average duration of fsync system calls. Spikes or high latency indicates that storage I/O cannot keep up with the write rate, which may slow down data ingestion.\n\nIf this value is elevated:\n- Check disk-related metrics.\n- If using cloud storage, check IOPS and throughput limits.\n- If using NFS, check network performance, server resource usage, and any errors on the NFS server side.\n- Check for known bugs in the filesystem or kernel version being used.",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"axisSoftMin": 0,
|
||||
"barAlignment": 0,
|
||||
"barWidthFactor": 0.6,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 0,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"insertNulls": false,
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "never",
|
||||
"showValues": false,
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"links": [],
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "s"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 81
|
||||
},
|
||||
"id": 159,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [
|
||||
"lastNotNull",
|
||||
"max"
|
||||
],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true,
|
||||
"sortBy": "Last *",
|
||||
"sortDesc": true
|
||||
},
|
||||
"tooltip": {
|
||||
"hideZeros": true,
|
||||
"mode": "multi",
|
||||
"sort": "desc"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "12.2.0",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "victoriametrics-metrics-datasource",
|
||||
"uid": "$ds"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"expr": "rate(vm_filestream_fsync_duration_seconds_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]) / rate(vm_filestream_fsync_calls_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])",
|
||||
"format": "time_series",
|
||||
"instant": false,
|
||||
"legendFormat": "{{instance}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Fsync avg duration ($instance)",
|
||||
"type": "timeseries"
|
||||
}
|
||||
],
|
||||
"title": "Troubleshooting",
|
||||
@@ -8743,4 +8847,4 @@
|
||||
"uid": "wNf0q_kZk_vm",
|
||||
"version": 1,
|
||||
"weekStart": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4581,6 +4581,110 @@
|
||||
],
|
||||
"title": "Rows ignored for last 1h ($instance)",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "victoriametrics-metrics-datasource",
|
||||
"uid": "$ds"
|
||||
},
|
||||
"description": "Average duration of fsync system calls. Spikes or high latency indicates that storage I/O cannot keep up with the write rate, which may slow down data ingestion.\n\nIf this value is elevated:\n- Check disk-related metrics.\n- If using cloud storage, check IOPS and throughput limits.\n- If using NFS, check network performance, server resource usage, and any errors on the NFS server side.\n- Check for known bugs in the filesystem or kernel version being used.",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"axisSoftMin": 0,
|
||||
"barAlignment": 0,
|
||||
"barWidthFactor": 0.6,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 0,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"insertNulls": false,
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "never",
|
||||
"showValues": false,
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"links": [],
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "s"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 189
|
||||
},
|
||||
"id": 171,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [
|
||||
"lastNotNull",
|
||||
"max"
|
||||
],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true,
|
||||
"sortBy": "Last *",
|
||||
"sortDesc": true
|
||||
},
|
||||
"tooltip": {
|
||||
"hideZeros": true,
|
||||
"mode": "multi",
|
||||
"sort": "desc"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "12.2.0",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "victoriametrics-metrics-datasource",
|
||||
"uid": "$ds"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"expr": "rate(vm_filestream_fsync_duration_seconds_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]) / rate(vm_filestream_fsync_calls_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])",
|
||||
"format": "time_series",
|
||||
"instant": false,
|
||||
"legendFormat": "{{instance}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Fsync avg duration ($instance)",
|
||||
"type": "timeseries"
|
||||
}
|
||||
],
|
||||
"title": "Troubleshooting",
|
||||
|
||||
@@ -4580,6 +4580,110 @@
|
||||
],
|
||||
"title": "Rows ignored for last 1h ($instance)",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "$ds"
|
||||
},
|
||||
"description": "Average duration of fsync system calls. Spikes or high latency indicates that storage I/O cannot keep up with the write rate, which may slow down data ingestion.\n\nIf this value is elevated:\n- Check disk-related metrics.\n- If using cloud storage, check IOPS and throughput limits.\n- If using NFS, check network performance, server resource usage, and any errors on the NFS server side.\n- Check for known bugs in the filesystem or kernel version being used.",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"axisSoftMin": 0,
|
||||
"barAlignment": 0,
|
||||
"barWidthFactor": 0.6,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 0,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"insertNulls": false,
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "never",
|
||||
"showValues": false,
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"links": [],
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "s"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 189
|
||||
},
|
||||
"id": 171,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [
|
||||
"lastNotNull",
|
||||
"max"
|
||||
],
|
||||
"displayMode": "table",
|
||||
"placement": "bottom",
|
||||
"showLegend": true,
|
||||
"sortBy": "Last *",
|
||||
"sortDesc": true
|
||||
},
|
||||
"tooltip": {
|
||||
"hideZeros": true,
|
||||
"mode": "multi",
|
||||
"sort": "desc"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "12.2.0",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "$ds"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"expr": "rate(vm_filestream_fsync_duration_seconds_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]) / rate(vm_filestream_fsync_calls_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])",
|
||||
"format": "time_series",
|
||||
"instant": false,
|
||||
"legendFormat": "{{instance}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Fsync avg duration ($instance)",
|
||||
"type": "timeseries"
|
||||
}
|
||||
],
|
||||
"title": "Troubleshooting",
|
||||
|
||||
@@ -163,6 +163,8 @@ The list of alerting rules is the following:
|
||||
alerting rules related to [vmauth](https://docs.victoriametrics.com/victoriametrics/vmauth/) component;
|
||||
* [alerts-vmanomaly.yml](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/deployment/docker/rules/alerts-vmanomaly.yml):
|
||||
alerting rules related to [VictoriaMetrics Anomaly Detection](https://docs.victoriametrics.com/anomaly-detection/);
|
||||
* [alerts-vmbackupmanager.yml](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/deployment/docker/rules/alerts-vmbackupmanager.yml):
|
||||
alerting rules related to [vmbackupmanager](https://docs.victoriametrics.com/victoriametrics/vmbackupmanager/) component;
|
||||
|
||||
Please, also see [how to monitor VictoriaMetrics installations](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#monitoring).
|
||||
## Troubleshooting
|
||||
|
||||
@@ -129,6 +129,7 @@ services:
|
||||
- ./rules/alerts-health.yml:/etc/alerts/alerts-health.yml
|
||||
- ./rules/alerts-vmagent.yml:/etc/alerts/alerts-vmagent.yml
|
||||
- ./rules/alerts-vmalert.yml:/etc/alerts/alerts-vmalert.yml
|
||||
- ./rules/alerts-vmbackupmanager.yml:/etc/alerts/alerts-vmbackupmanager.yml
|
||||
command:
|
||||
- "--datasource.url=http://vmauth:8427/select/0/prometheus"
|
||||
- "--datasource.basicAuth.username=foo"
|
||||
|
||||
@@ -70,6 +70,7 @@ services:
|
||||
- ./rules/alerts-health.yml:/etc/alerts/alerts-health.yml
|
||||
- ./rules/alerts-vmagent.yml:/etc/alerts/alerts-vmagent.yml
|
||||
- ./rules/alerts-vmalert.yml:/etc/alerts/alerts-vmalert.yml
|
||||
- ./rules/alerts-vmbackupmanager.yml:/etc/alerts/alerts-vmbackupmanager.yml
|
||||
command:
|
||||
- "--datasource.url=http://victoriametrics:8428/"
|
||||
- "--remoteRead.url=http://victoriametrics:8428/"
|
||||
|
||||
110
deployment/docker/rules/alerts-vmbackupmanager.yml
Normal file
110
deployment/docker/rules/alerts-vmbackupmanager.yml
Normal file
@@ -0,0 +1,110 @@
|
||||
# File contains default list of alerts for vmbackupmanager.
|
||||
# The alerts below are just recommendations and may require some updates
|
||||
# and threshold calibration according to every specific setup.
|
||||
groups:
|
||||
- name: vmbackupmanager
|
||||
rules:
|
||||
- alert: NoLatestBackupWithinLastDay
|
||||
expr: |
|
||||
(
|
||||
vm_backup_last_success_at{type="latest"} == 0
|
||||
and on(job, instance)
|
||||
vm_app_uptime_seconds > 24 * 3600
|
||||
)
|
||||
or
|
||||
(
|
||||
vm_backup_last_success_at{type="latest"} > 0
|
||||
and time() - vm_backup_last_success_at{type="latest"} > 24 * 3600
|
||||
)
|
||||
for: 1m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "latest backup hasn't completed successfully for more than 1 day on \"{{ $labels.job }}\"(\"{{ $labels.instance }}\")"
|
||||
description: >
|
||||
vmbackupmanager on "{{ $labels.job }}"("{{ $labels.instance }}") hasn't completed the latest backup for more than 1 day.
|
||||
Check error logs on vmbackupmanager for root cause.
|
||||
|
||||
- alert: NoHourlyBackupWithinLastDay
|
||||
expr: |
|
||||
(
|
||||
vm_backup_last_success_at{type="hourly"} == 0
|
||||
and on(job, instance)
|
||||
vm_app_uptime_seconds > 24 * 3600
|
||||
)
|
||||
or
|
||||
(
|
||||
vm_backup_last_success_at{type="hourly"} > 0
|
||||
and time() - vm_backup_last_success_at{type="hourly"} > 24 * 3600
|
||||
)
|
||||
for: 1m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "hourly backup hasn't completed successfully for more than 1 day on \"{{ $labels.job }}\"(\"{{ $labels.instance }}\")"
|
||||
description: >
|
||||
vmbackupmanager on "{{ $labels.job }}"("{{ $labels.instance }}") hasn't completed an hourly backup for more than 1 day.
|
||||
Check error logs on vmbackupmanager for root cause.
|
||||
|
||||
- alert: NoDailyBackupWithinLast3Days
|
||||
expr: |
|
||||
(
|
||||
vm_backup_last_success_at{type="daily"} == 0
|
||||
and on(job, instance)
|
||||
vm_app_uptime_seconds > 3 * 24 * 3600
|
||||
)
|
||||
or
|
||||
(
|
||||
vm_backup_last_success_at{type="daily"} > 0
|
||||
and time() - vm_backup_last_success_at{type="daily"} > 3 * 24 * 3600
|
||||
)
|
||||
for: 1m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "daily backup hasn't completed successfully for more than 3 days on \"{{ $labels.job }}\"(\"{{ $labels.instance }}\")"
|
||||
description: >
|
||||
vmbackupmanager on "{{ $labels.job }}"("{{ $labels.instance }}") hasn't completed a daily backup for more than 3 days.
|
||||
Check error logs on vmbackupmanager for root cause.
|
||||
|
||||
- alert: NoWeeklyBackupWithinLast14Days
|
||||
expr: |
|
||||
(
|
||||
vm_backup_last_success_at{type="weekly"} == 0
|
||||
and on(job, instance)
|
||||
vm_app_uptime_seconds > 14 * 24 * 3600
|
||||
)
|
||||
or
|
||||
(
|
||||
vm_backup_last_success_at{type="weekly"} > 0
|
||||
and time() - vm_backup_last_success_at{type="weekly"} > 14 * 24 * 3600
|
||||
)
|
||||
for: 1m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "weekly backup hasn't completed successfully for more than 14 days on \"{{ $labels.job }}\"(\"{{ $labels.instance }}\")"
|
||||
description: >
|
||||
vmbackupmanager on "{{ $labels.job }}"("{{ $labels.instance }}") hasn't completed a weekly backup for more than 14 days.
|
||||
Check error logs on vmbackupmanager for root cause.
|
||||
|
||||
- alert: NoMonthlyBackupWithinLast62Days
|
||||
expr: |
|
||||
(
|
||||
vm_backup_last_success_at{type="monthly"} == 0
|
||||
and on(job, instance)
|
||||
vm_app_uptime_seconds > 62 * 24 * 3600
|
||||
)
|
||||
or
|
||||
(
|
||||
vm_backup_last_success_at{type="monthly"} > 0
|
||||
and time() - vm_backup_last_success_at{type="monthly"} > 62 * 24 * 3600
|
||||
)
|
||||
for: 1m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "monthly backup hasn't completed successfully for more than 62 days on \"{{ $labels.job }}\"(\"{{ $labels.instance }}\")"
|
||||
description: >
|
||||
vmbackupmanager on "{{ $labels.job }}"("{{ $labels.instance }}") hasn't completed a monthly backup for more than 62 days.
|
||||
Check error logs on vmbackupmanager for root cause.
|
||||
@@ -829,12 +829,9 @@ See also [minimum downtime strategy](#minimum-downtime-strategy).
|
||||
|
||||
## Slowness-based re-routing
|
||||
|
||||
By default, `vminsert` nodes limit the cluster's overall ingestion rate to the throughput of the slowest `vmstorage` node.
|
||||
This ensures that incoming metrics are evenly distributed across all `vmstorage` nodes.
|
||||
The downside is that a single slow vmstorage node can throttle the entire cluster.
|
||||
|
||||
When `-disableRerouting=false` is enabled on `vminsert`,
|
||||
the cluster will automatically re-route writes away from the slowest vmstorage node to preserve maximum ingestion throughput.
|
||||
By default{{% available_from "#" %}}, `vminsert` automatically re-routes writes away from the slowest `vmstorage` node
|
||||
to preserve maximum ingestion throughput. This prevents a single slow `vmstorage` node
|
||||
from throttling the entire cluster.
|
||||
|
||||
Re-routing occurs only when all of the following conditions hold:
|
||||
- the storage send buffer is full.
|
||||
@@ -842,11 +839,15 @@ Re-routing occurs only when all of the following conditions hold:
|
||||
- the vmstorage cluster have much lower saturation overall.
|
||||
- the vmstorage cluster has at least three ready nodes.
|
||||
|
||||
Enable slowness-based re-routing when peak write throughput matters more
|
||||
than minimizing the number of [active time series](https://docs.victoriametrics.com/victoriametrics/faq/#what-is-an-active-time-series)
|
||||
or keeping metrics perfectly balanced across nodes.
|
||||
Disable slowness-based re-routing with `-disableRerouting=true` when keeping metrics
|
||||
perfectly balanced across nodes or minimizing the number of [active time series](https://docs.victoriametrics.com/victoriametrics/faq/#what-is-an-active-time-series)
|
||||
matters more than peak write throughput.
|
||||
|
||||
The rerouting and node saturation could be seen at [VictoriaMetrics - cluster](https://grafana.com/grafana/dashboards/11176) dashboard.
|
||||
Slowness-based re-routing is automatically disabled{{% available_from "#" %}} when `-replicationFactor` is greater than `1`,
|
||||
because rerouting does not guarantee that replicated copies land on distinct storage nodes,
|
||||
which violates the replication contract.
|
||||
|
||||
The rerouting and node saturation could be seen at [VictoriaMetrics - cluster](https://grafana.com/grafana/dashboards/11176) dashboard.
|
||||
|
||||
## Capacity planning
|
||||
|
||||
|
||||
@@ -26,7 +26,16 @@ See also [LTS releases](https://docs.victoriametrics.com/victoriametrics/lts-rel
|
||||
|
||||
## tip
|
||||
|
||||
**Update Note 1:** `vminsert` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/): the default value of `-disableRerouting` flag has changed from `true` to `false`, enabling [slowness-based re-routing](https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/#slowness-based-re-routing) by default. Slowness re-routing is automatically disabled when `-replicationFactor` is greater than 1. If you rely on the old behavior, pass `-disableRerouting` command-line flag to `vminsert`. See [#11287](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/11287).
|
||||
|
||||
* FEATURE: [vmagent](https://docs.victoriametrics.com/victoriametrics/vmagent/): add `name` label identifying the corresponding `-remoteWrite.url` target to the `vm_persistentqueue_*` metrics exposed by persistent queue. See [#7944](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7944). Thanks to @tIGO for contribution.
|
||||
* FEATURE: `vminsert` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/): enable [slowness-based re-routing](https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/#slowness-based-re-routing) by default. Previously, `-disableRerouting` defaulted to `true`, which limited ingestion throughput to the slowest `vmstorage` node. Now `-disableRerouting` defaults to `false`, so `vminsert` automatically routes data away from the slowest `vmstorage` node, improving overall ingestion performance. Slowness re-routing is automatically disabled when `-replicationFactor` is greater than 1. See [#11287](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/11287).
|
||||
* FEATURE: [vmui](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#vmui): persist the selected auto-refresh interval in the URL. See [VictoriaLogs#1310](https://github.com/VictoriaMetrics/VictoriaLogs/issues/1310).
|
||||
* FEATURE: [dashboards](https://github.com/VictoriaMetrics/VictoriaMetrics/tree/master/dashboards): add `Fsync avg duration` panel to the Troubleshooting section of the single-node, cluster, and vmagent dashboards. This panel surfaces degradation of IO operation for faster incident triage. See [#10432](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/10432).
|
||||
* FEATURE: [vmbackupmanager](https://docs.victoriametrics.com/victoriametrics/vmbackupmanager/) and [alerts](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/deployment/docker/rules): introduce `vm_backup_last_success_at` metric to track the last successful backup by type. Add [alerting rules](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/deployment/docker/rules/alerts-vmbackupmanager.yml) `NoLatestBackupWithinLastDay`, `NoHourlyBackupWithinLastDay`, `NoDailyBackupWithinLast3Days`, `NoWeeklyBackupWithinLast14Days` and `NoMonthlyBackupWithinLast62Days` to remind users about the missing backups. See [#11217](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/11217).
|
||||
|
||||
* BUGFIX: [vmalert](https://docs.victoriametrics.com/victoriametrics/vmalert/): fixed the display of rule state badges on the `Groups` page in the web UI. See [#11160](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/11160).
|
||||
* BUGFIX: [vmbackupmanager](https://docs.victoriametrics.com/victoriametrics/vmbackupmanager/): previously, `vmbackupmanager` was crashing on startup when it failed to restore backup state from remote storage, causing a crash loop. Now it logs the error and continues running, retrying the state restore before each scheduled backup. Added `vm_backup_errors_total{type="restoreState"}` metric to track backup state restore failures. See [#11217](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/11217).
|
||||
|
||||
## [v1.148.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.148.0)
|
||||
|
||||
@@ -53,6 +62,7 @@ Released at 2026-07-20
|
||||
* BUGFIX: [vmui](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#vmui): hide `Total metric names` stats on [Cardinality Explorer](https://docs.victoriametrics.com/victoriametrics/#cardinality-explorer) page when user selects a specific metric or label to focus. See [#11154](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/11154) for details. Thanks to @lghuy05 for the contribution.
|
||||
* BUGFIX: [vmui](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#vmui): keep only one header navigation dropdown (`Explore`, `Tools`) open at a time. Previously, hovering across two dropdowns could briefly leave both open due to the close delay. See [#11224](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/11224). Thanks to @antedotee for contribution.
|
||||
* BUGFIX: [vmauth](https://docs.victoriametrics.com/victoriametrics/vmauth/): return `408 Request Timeout` instead of `400 Bad Request` when the request body isn't received within `-maxQueueDuration`. This prevents `vmagent` from incorrectly downgrading the remote write protocol and dropping data when `vmauth` is used as a proxy for a remote write endpoint. See [#11272](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/11272).
|
||||
|
||||
## [v1.147.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.147.0)
|
||||
|
||||
Released at 2026-07-06
|
||||
@@ -112,7 +122,6 @@ Released at 2026-06-22
|
||||
* BUGFIX: [vmsingle](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/) and `vmselect` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/): properly escape `metricFamilyName` at metrics metadata response. See [#11129](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/11129). Thanks for @fxrlv for the contribution.
|
||||
* BUGFIX: [vmsingle](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/) and `vmstorage` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/): prevent more cases of panic during directory deletion on `NFS`-based mounts. See [#11060](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/11060).
|
||||
|
||||
|
||||
## [v1.145.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.145.0)
|
||||
|
||||
Released at 2026-06-08
|
||||
|
||||
@@ -478,6 +478,12 @@ Clusters here are referred to as `source` and `destination`.
|
||||
|
||||
`vmbackupmanager` exports various metrics in Prometheus exposition format at `http://vmbackupmanager:8300/metrics` page. It is recommended to set up regular scraping of this page either via [vmagent](https://docs.victoriametrics.com/victoriametrics/vmagent/) or via Prometheus, so the exported metrics could be analyzed later.
|
||||
|
||||
To verify that `vmbackupmanager` is executing backup tasks normally, the following metrics can help:
|
||||
|
||||
* `vm_backup_last_success_at{type="<backup_type>"}` - unix timestamp of the last successful backup{{% available_from "#" %}}. Remains `0` if no backup has completed successfully since startup. Check error logs and verify remote storage accessibility if this persists.
|
||||
* `vm_backup_last_run_failed{type="<backup_type>"}` - whether the last backup task for the given backup type failed. The value `1` means the last task failed. Check the error logs of `vmbackupmanager` for the root cause
|
||||
* `vm_backup_errors_total{type="<backup_type>"}` - total number of backup errors for the given backup type.
|
||||
|
||||
Use the official [Grafana dashboard](https://grafana.com/grafana/dashboards/17798) for `vmbackupmanager` overview.
|
||||
Graphs on this dashboard contain useful hints - hover the `i` icon in the top left corner of each graph in order to read it.
|
||||
If you have suggestions for improvements or have found a bug - please open an issue on github or add a review to the dashboard.
|
||||
|
||||
130
go.mod
130
go.mod
@@ -3,7 +3,7 @@ module github.com/VictoriaMetrics/VictoriaMetrics
|
||||
go 1.26.5
|
||||
|
||||
require (
|
||||
cloud.google.com/go/storage v1.62.3
|
||||
cloud.google.com/go/storage v1.64.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.22.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.14.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.8.0
|
||||
@@ -12,65 +12,65 @@ require (
|
||||
github.com/VictoriaMetrics/fastcache v1.13.3
|
||||
github.com/VictoriaMetrics/metrics v1.44.0
|
||||
github.com/VictoriaMetrics/metricsql v0.87.3
|
||||
github.com/aws/aws-sdk-go-v2 v1.42.0
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.25
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.22.27
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.103.3
|
||||
github.com/aws/aws-sdk-go-v2 v1.43.0
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.31
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.22.35
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.106.0
|
||||
github.com/bmatcuk/doublestar/v4 v4.10.0
|
||||
github.com/cespare/xxhash/v2 v2.3.0
|
||||
github.com/cheggaaa/pb/v3 v3.1.7
|
||||
github.com/cheggaaa/pb/v3 v3.2.0
|
||||
github.com/gogo/protobuf v1.3.2
|
||||
github.com/golang/snappy v1.0.0
|
||||
github.com/google/go-cmp v0.7.0
|
||||
github.com/googleapis/gax-go/v2 v2.22.0
|
||||
github.com/googleapis/gax-go/v2 v2.23.0
|
||||
github.com/influxdata/influxdb v1.12.4
|
||||
github.com/klauspost/compress v1.18.6
|
||||
github.com/klauspost/compress v1.19.1
|
||||
github.com/oklog/ulid/v2 v2.1.1
|
||||
github.com/prometheus/prometheus v0.312.0
|
||||
github.com/prometheus/prometheus v0.313.1
|
||||
github.com/urfave/cli/v2 v2.27.7
|
||||
github.com/valyala/fastjson v1.6.10
|
||||
github.com/valyala/fastrand v1.1.0
|
||||
github.com/valyala/fasttemplate v1.2.2
|
||||
github.com/valyala/gozstd v1.24.0
|
||||
github.com/valyala/gozstd v1.25.0
|
||||
github.com/valyala/histogram v1.2.0
|
||||
github.com/valyala/quicktemplate v1.8.0
|
||||
golang.org/x/net v0.57.0
|
||||
golang.org/x/oauth2 v0.36.0
|
||||
golang.org/x/sys v0.47.0
|
||||
google.golang.org/api v0.284.0
|
||||
google.golang.org/api v0.290.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
cel.dev/expr v0.25.2 // indirect
|
||||
cloud.google.com/go v0.123.0 // indirect
|
||||
cloud.google.com/go/auth v0.20.0 // indirect
|
||||
cloud.google.com/go/auth v0.22.0 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.9.0 // indirect
|
||||
cloud.google.com/go/iam v1.11.0 // indirect
|
||||
cloud.google.com/go/monitoring v1.29.0 // indirect
|
||||
cloud.google.com/go/iam v1.12.0 // indirect
|
||||
cloud.google.com/go/monitoring v1.30.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.12.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.7.2 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.33.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.57.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.57.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.34.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.58.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.58.0 // indirect
|
||||
github.com/VividCortex/ewma v1.2.0 // indirect
|
||||
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.13 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.24 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.29 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.29 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.29 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.30 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.12 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.22 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.29 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.29 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.2.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.31.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.36.6 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.43.3 // indirect
|
||||
github.com/aws/smithy-go v1.27.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.14 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.30 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.31 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.31 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.31 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.32 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.13 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.24 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.31 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.32 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.5.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.33.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.45.0 // indirect
|
||||
github.com/aws/smithy-go v1.27.4 // indirect
|
||||
github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||
@@ -85,14 +85,14 @@ require (
|
||||
github.com/felixge/httpsnoop v1.1.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.9.2 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.1.4 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/logr v1.4.4 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
|
||||
github.com/gobwas/glob v0.2.3 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.16 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.18 // indirect
|
||||
github.com/grafana/regexp v0.0.0-20250905093917-f7b3be9d1853 // indirect
|
||||
github.com/hashicorp/go-version v1.9.0 // indirect
|
||||
github.com/jpillora/backoff v1.0.0 // indirect
|
||||
@@ -102,7 +102,7 @@ require (
|
||||
github.com/knadh/koanf/v2 v2.3.5 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.15 // indirect
|
||||
github.com/mattn/go-isatty v0.0.22 // indirect
|
||||
github.com/mattn/go-isatty v0.0.23 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.24 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
@@ -110,37 +110,36 @@ require (
|
||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.154.0 // indirect
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.154.0 // indirect
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/processor/deltatocumulativeprocessor v0.154.0 // indirect
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.157.0 // indirect
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.157.0 // indirect
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/processor/deltatocumulativeprocessor v0.157.0 // indirect
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_golang/exp v0.0.0-20260602051030-3537b20ac86b // indirect
|
||||
github.com/prometheus/client_golang v1.24.0 // indirect
|
||||
github.com/prometheus/client_golang/exp v0.0.0-20260723095000-436bf2e0fb60 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.68.1 // indirect
|
||||
github.com/prometheus/common v0.70.1 // indirect
|
||||
github.com/prometheus/otlptranslator v1.0.0 // indirect
|
||||
github.com/prometheus/procfs v0.20.1 // indirect
|
||||
github.com/prometheus/procfs v0.21.1 // indirect
|
||||
github.com/prometheus/sigv4 v0.4.1 // indirect
|
||||
github.com/puzpuzpuz/xsync/v4 v4.5.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/spiffe/go-spiffe/v2 v2.7.0 // indirect
|
||||
github.com/spiffe/go-spiffe/v2 v2.8.1 // indirect
|
||||
github.com/stretchr/testify v1.11.1 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342 // indirect
|
||||
github.com/yuin/goldmark v1.8.4 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/collector/component v1.60.0 // indirect
|
||||
go.opentelemetry.io/collector/confmap v1.60.0 // indirect
|
||||
go.opentelemetry.io/collector/confmap/xconfmap v0.154.0 // indirect
|
||||
go.opentelemetry.io/collector/consumer v1.60.0 // indirect
|
||||
go.opentelemetry.io/collector/featuregate v1.60.0 // indirect
|
||||
go.opentelemetry.io/collector/internal/componentalias v0.154.0 // indirect
|
||||
go.opentelemetry.io/collector/pdata v1.60.0 // indirect
|
||||
go.opentelemetry.io/collector/pipeline v1.60.0 // indirect
|
||||
go.opentelemetry.io/collector/processor v1.60.0 // indirect
|
||||
go.opentelemetry.io/collector/component v1.63.0 // indirect
|
||||
go.opentelemetry.io/collector/confmap v1.63.0 // indirect
|
||||
go.opentelemetry.io/collector/confmap/xconfmap v0.157.0 // indirect
|
||||
go.opentelemetry.io/collector/consumer v1.63.0 // indirect
|
||||
go.opentelemetry.io/collector/featuregate v1.63.0 // indirect
|
||||
go.opentelemetry.io/collector/internal/componentalias v0.157.0 // indirect
|
||||
go.opentelemetry.io/collector/pdata v1.63.0 // indirect
|
||||
go.opentelemetry.io/collector/pipeline v1.63.0 // indirect
|
||||
go.opentelemetry.io/collector/processor v1.63.0 // indirect
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.44.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.69.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.69.0 // indirect
|
||||
@@ -158,31 +157,24 @@ require (
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.54.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20260718201538-764159d718ef // indirect
|
||||
golang.org/x/mod v0.38.0 // indirect
|
||||
golang.org/x/sync v0.22.0 // indirect
|
||||
golang.org/x/telemetry v0.0.0-20260717140457-bdb89881bb75 // indirect
|
||||
golang.org/x/term v0.45.0 // indirect
|
||||
golang.org/x/text v0.40.0 // indirect
|
||||
golang.org/x/time v0.15.0 // indirect
|
||||
golang.org/x/tools v0.48.0 // indirect
|
||||
golang.org/x/tools/go/expect v0.1.1-deprecated // indirect
|
||||
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect
|
||||
golang.org/x/tools/godoc v0.1.0-deprecated // indirect
|
||||
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
|
||||
google.golang.org/genproto v0.0.0-20260615183401-62b3387ff324 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260615183401-62b3387ff324 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260615183401-62b3387ff324 // indirect
|
||||
google.golang.org/grpc v1.81.1 // indirect
|
||||
google.golang.org/genproto v0.0.0-20260720211330-0afa2a65878a // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260720211330-0afa2a65878a // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260720211330-0afa2a65878a // indirect
|
||||
google.golang.org/grpc v1.82.1 // indirect
|
||||
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/apimachinery v0.36.2 // indirect
|
||||
k8s.io/client-go v0.36.2 // indirect
|
||||
k8s.io/apimachinery v0.36.3 // indirect
|
||||
k8s.io/client-go v0.36.3 // indirect
|
||||
k8s.io/klog/v2 v2.140.0 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20260603220949-865597e52e25 // indirect
|
||||
k8s.io/utils v0.0.0-20260507154919-ff6756f316d2 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20260721132016-d427ff9ee9ad // indirect
|
||||
k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.4.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.4.2 // indirect
|
||||
sigs.k8s.io/yaml v1.6.0 // indirect
|
||||
)
|
||||
|
||||
429
go.sum
429
go.sum
@@ -2,22 +2,22 @@ cel.dev/expr v0.25.2 h1:K6j46C81hXtZQfuX60cVWQFBJahKSE2gfRbNuvr5bFs=
|
||||
cel.dev/expr v0.25.2/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4=
|
||||
cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE=
|
||||
cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU=
|
||||
cloud.google.com/go/auth v0.20.0 h1:kXTssoVb4azsVDoUiF8KvxAqrsQcQtB53DcSgta74CA=
|
||||
cloud.google.com/go/auth v0.20.0/go.mod h1:942/yi/itH1SsmpyrbnTMDgGfdy2BUqIKyd0cyYLc5Q=
|
||||
cloud.google.com/go/auth v0.22.0 h1:Xp9wAKkLoeaYb5pYZZoQGz4E9sdPxIbzS3gywZE3ciQ=
|
||||
cloud.google.com/go/auth v0.22.0/go.mod h1:M9o2Oz+YI2jAfxewJgb1vyI3vceHF+eohmxyzmrl+9s=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
|
||||
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
|
||||
cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
|
||||
cloud.google.com/go/iam v1.11.0 h1:KieQ9Pb+LLPak1O3Rv3GgCxhnmkYf7Xyh0P5HfF1jFM=
|
||||
cloud.google.com/go/iam v1.11.0/go.mod h1:KP+nKGugNJW4LcLx1uEZcq1ok5sQHFaQehQNl4QDgV4=
|
||||
cloud.google.com/go/logging v1.18.0 h1:KhzZq+1cSkPH9YUaKLLhLtQxIHitVayBmk0sGfoM9+k=
|
||||
cloud.google.com/go/logging v1.18.0/go.mod h1:ZGKnpBaURITh+g/uom2VhbiFoFWvejcrHPDhxFtU/gI=
|
||||
cloud.google.com/go/longrunning v1.0.0 h1:lwzWEYD8+NkYV7dhexOz6kmlvajZA70+bW/xMhRVVdY=
|
||||
cloud.google.com/go/longrunning v1.0.0/go.mod h1:8nqFBPOO1U/XkhWl0I19AMZEphrHi73VNABIpKYaTwM=
|
||||
cloud.google.com/go/monitoring v1.29.0 h1:AHhDsFaSax1/4k+qlIDX/SDGe6hggnfXJ9dkgD9qBPY=
|
||||
cloud.google.com/go/monitoring v1.29.0/go.mod h1:72NOVjJXHY/HBfoLT0+qlCZBT059+9VXLeAnL2PeeVM=
|
||||
cloud.google.com/go/storage v1.62.3 h1:SZq1t23NCI+e96dH77Dg3PEfsNNEjqO8zE5AnD8gVD0=
|
||||
cloud.google.com/go/storage v1.62.3/go.mod h1:cpYz/kRVZ+UQAF1uHeea10/9ewcRbxGoGNKsS9daSXA=
|
||||
cloud.google.com/go/iam v1.12.0 h1:Aki3bX9aHUDKPHfnRJfDcTdVedvy6quGBQcTqx3DRXk=
|
||||
cloud.google.com/go/iam v1.12.0/go.mod h1:FEZ4lXpADAC2AIpQY7LANNjjwyQ2jK439CI2VaD+sLY=
|
||||
cloud.google.com/go/logging v1.19.0 h1:NCqhdVUg3wQ8Cobdf16FDSuTGi3+6+hdSBHrY5TsR6Q=
|
||||
cloud.google.com/go/logging v1.19.0/go.mod h1:i40NZCHC9Gqvod4yE+yQfDWwlgwW/SrshkkGibCHxcA=
|
||||
cloud.google.com/go/longrunning v1.2.0 h1:WjYH3YHBGCxGJP9M4dWGHBfXr/cFIjMkNgWcJj7/iMM=
|
||||
cloud.google.com/go/longrunning v1.2.0/go.mod h1:5KMQALFGOCtFoi2xSOA1u3H7WKlhmckgiyFw7+LGQp0=
|
||||
cloud.google.com/go/monitoring v1.30.0 h1:r/d+JUbyKmJ8b07iznuKfzVzrIXTWxHQ3lBRm3x2LlY=
|
||||
cloud.google.com/go/monitoring v1.30.0/go.mod h1:htlUR0QWVMrjFzZmN4LGnMAve9xB/eduwjmINxVZ8RM=
|
||||
cloud.google.com/go/storage v1.64.0 h1:KLpxI/oX9LxeRsNqn877d2WyeT3ryiEwnGt8pwcSPZg=
|
||||
cloud.google.com/go/storage v1.64.0/go.mod h1:lWyAtwvDZHdL3k68WVKbESP6bmWaV23ZJJ/JEVw/ZaQ=
|
||||
cloud.google.com/go/trace v1.16.0 h1:GmQovzFc5F0CNfl0VLgL64aoTtu7xsM0YajW2GlG9+E=
|
||||
cloud.google.com/go/trace v1.16.0/go.mod h1:r+bdAn16dKLSV1G2D5v3e58IlQlizfxWrUfjx7kM7X0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.22.0 h1:aokoqcHvaGjiM3VpjKDfMMnF/8epJ+Q1HLJ7CudztqE=
|
||||
@@ -42,14 +42,14 @@ github.com/AzureAD/microsoft-authentication-library-for-go v1.7.2 h1:RHK7bS+HQMs
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.7.2/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk=
|
||||
github.com/Code-Hex/go-generics-cache v1.5.1 h1:6vhZGc5M7Y/YD8cIUcY8kcuQLB4cHR7U+0KMqAA0KcU=
|
||||
github.com/Code-Hex/go-generics-cache v1.5.1/go.mod h1:qxcC9kRVrct9rHeiYpFWSoW1vxyillCVzX13KZG8dl4=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.33.0 h1:l7+6kwRMJNwdCvYdDl7Eax+wzEYHSnNY7zrrfbhDdTA=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.33.0/go.mod h1:pJTkW8hEUIIi3Pf65lPZOnn4Y81yCllX6IWk2jNXdkM=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.57.0 h1:jLdiS1vO+XJFyDSWRHBx56r4s/NNtcl5J6KyCcWUX/w=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.57.0/go.mod h1:8lmpHY+1VRoteiOwyrQMDt1YGXOrFKCz+1wJW7n3ODY=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.57.0 h1:cSjUzZ7KU8hicTgzaSv9NmSyM9fTVK3y5lsBUl3wOis=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.57.0/go.mod h1:dzcEjy1WJ0Q4u9twNR3LcLhNoYMRCrMCMafpxa0TjPQ=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.57.0 h1:RoO5+d7uCmDqovLrHCr2/BuViUXvdcrNxyNM1pN9dDQ=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.57.0/go.mod h1:YqwkQPrWSC7+byyc1VlKbWLBF5JsW5IoL6xUkemYSXk=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.34.0 h1:yzIYdwuro811Z27D3T80Wkd3rqZzb0K43nner7Eh1yE=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.34.0/go.mod h1:pJTkW8hEUIIi3Pf65lPZOnn4Y81yCllX6IWk2jNXdkM=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.58.0 h1:ZYGajzJNcirVZpT1rltgf9iM+j9zZ4v8V9DrF+xKRJ8=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.58.0/go.mod h1:PDQyYBOzGtQgvshQI//UiXyzuMHCz0ndyu+4W8X82vM=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.58.0 h1:IBF8BbhKJkMsON/eY+LMu3aF3XMiotCb9KvkUmEkOJo=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.58.0/go.mod h1:dzcEjy1WJ0Q4u9twNR3LcLhNoYMRCrMCMafpxa0TjPQ=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.58.0 h1:SBZzZCiPmDrUV7NSCWY54OnKikO/oTydPCvyEyYaDDE=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.58.0/go.mod h1:YqwkQPrWSC7+byyc1VlKbWLBF5JsW5IoL6xUkemYSXk=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/VictoriaMetrics/VictoriaLogs v1.51.1-0.20260624061259-dc94972a8708 h1:D9/Jzlm3B8PBnrWxg4ft8KYZdG607dV3lpBfPCoiJD8=
|
||||
@@ -60,8 +60,6 @@ github.com/VictoriaMetrics/fastcache v1.13.3 h1:rBabE0iIxcqKEMCwUmwHZ9dgEqXerg8F
|
||||
github.com/VictoriaMetrics/fastcache v1.13.3/go.mod h1:hHXhl4DA2fTL2HTZDJFXWgW0LNjo6B+4aj2Wmng3TjU=
|
||||
github.com/VictoriaMetrics/metrics v1.44.0 h1:Fr8yqQSV+ZfYaDD/anqk1E8e9YPgfleSleJmAI0M0Tw=
|
||||
github.com/VictoriaMetrics/metrics v1.44.0/go.mod h1:xDM82ULLYCYdFRgQ2JBxi8Uf1+8En1So9YUwlGTOqTc=
|
||||
github.com/VictoriaMetrics/metricsql v0.87.2 h1:7OsrcDBWREWKqqpnFyIUEOM4FNv2qHvCoww2GYz3Tc0=
|
||||
github.com/VictoriaMetrics/metricsql v0.87.2/go.mod h1:d4EisFO6ONP/HIGDYTAtwrejJBBeKGQYiRl095bS4QQ=
|
||||
github.com/VictoriaMetrics/metricsql v0.87.3 h1:JU4JnVKSC5Vp3b4AvogXyOAjkz1iFF9n1KBMphS4WO8=
|
||||
github.com/VictoriaMetrics/metricsql v0.87.3/go.mod h1:d4EisFO6ONP/HIGDYTAtwrejJBBeKGQYiRl095bS4QQ=
|
||||
github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
|
||||
@@ -74,56 +72,56 @@ github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJ
|
||||
github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
|
||||
github.com/aws/aws-sdk-go v1.55.8 h1:JRmEUbU52aJQZ2AjX4q4Wu7t4uZjOu71uyNmaWlUkJQ=
|
||||
github.com/aws/aws-sdk-go v1.55.8/go.mod h1:ZkViS9AqA6otK+JBBNH2++sx1sgxrPKcSzPPvQkUtXk=
|
||||
github.com/aws/aws-sdk-go-v2 v1.42.0 h1:XvXMJTkFQtpBKIWZnmr9ZEOc2InWM2yldjXEJ/bymhA=
|
||||
github.com/aws/aws-sdk-go-v2 v1.42.0/go.mod h1:27+ACypSLljLAEKsCYOmrjKh83vuTRkuAe9Uv/3A4bg=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.13 h1:p1BBrg/Hhp6uK7zpejeI8QFXHJeC/mynzi04Sl03k9g=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.13/go.mod h1:8cIfkE9MDhkRZGpQ22aV6/lkYeYSozpz16Smrs5x4Ls=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.25 h1:ACCejvStYoilgwrfegSt5ZntCbPrk52qfwyNcnl3omM=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.25/go.mod h1:LJyU8sDRbXUxFn8xMJIGP+v9QYYwveNLI8a/giAOiAs=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.24 h1:2hQqYCV9yqyePQ9o6dCrZc/zO8U3TwPr9mIKlZnPu/I=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.24/go.mod h1:IDwpACtwqHLISdzfwUUNq4P9DsB/h5BLg4FwJPNfqFY=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.29 h1:r6qZHbT+wxgWO/e9vYNUEtg7lv5+UN3pRqKhLXvnArg=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.29/go.mod h1:QRnaRcTVGKPGRy8w78HMQtKUGRYcnMZAANATkeVA6Mo=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.22.27 h1:gb+HtIZdwcIoLxv/xwGumQr1DmGmGGCQnjKKVVSMYsU=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.22.27/go.mod h1:2b/8jZl/qwUMBZpSAcxX+IdM3zj6RUyfnB2IdLt9I+I=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.29 h1:f3vKqSo13fhTYb+JEcXwXefZQE26I1FB5eTSniU67ko=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.29/go.mod h1:MzoLFUArKGpGD+ukmPiTPG1X5x4o6M2kq4v2dr1FiEc=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.29 h1:RdwIf/CuUsvJX3RgJagbOyotl/cxoLY4xviKuE7p2GY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.29/go.mod h1:71wt8W2EgswdZy9Mf9KNnzxZ3TiZlv4caKghPktDOkA=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.30 h1:VTGy885W5DKBxWRUJbym9hytNaYzsyaPkCHGRRMAOhU=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.30/go.mod h1:AS0HycUvJRFvTt613AYDOgO2jzw+00cVSMny8XB3yMY=
|
||||
github.com/aws/aws-sdk-go-v2/service/ec2 v1.304.0 h1:wZthLlYdKxBo7NpWLbl0A/8DB/QNDB+8RJa9WboK9Q0=
|
||||
github.com/aws/aws-sdk-go-v2/service/ec2 v1.304.0/go.mod h1:Y95W0Hm6FYLPa6o0hbnJ+sWgmdc4ifcLFjGkdobWVhY=
|
||||
github.com/aws/aws-sdk-go-v2/service/ecs v1.81.0 h1:2Sp9EwK7giQpJnQ54k0zdUh6aykmmbpEurEEygr104c=
|
||||
github.com/aws/aws-sdk-go-v2/service/ecs v1.81.0/go.mod h1:TIKZ9zIFS6W2k9FeW+r5sGVnlxp+aUt9oQ/St3Suj1o=
|
||||
github.com/aws/aws-sdk-go-v2/service/elasticache v1.52.2 h1:5wbCUfyxXcjIqesyVfJBBJs0bDMyejthtHyy48mfZCI=
|
||||
github.com/aws/aws-sdk-go-v2/service/elasticache v1.52.2/go.mod h1:o4vQxDt6oteknUjkXIEskp0ccy+93NRTPKXw3HlVMFE=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.12 h1:ZD2+BSw9vFsNlKYIasSNt3uDbjqqXIBcM13UJv/Lx2k=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.12/go.mod h1:Ms4zlcVBbXbiP7EVLhl+lgjvA/a7YphqQ3Ih3174EmI=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.22 h1:V51LGlOq/1VsDsHUdoklAQi7rMmx4qQubvFYAlP2254=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.22/go.mod h1:4Pzhyz8hJOm2bepgl+NjvRx8vlUFAIIvJnZ/MkcNPpU=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.29 h1:DRebniUGZ2MqiiIVmQJ04vIXr918hubdHMnarSLEWyU=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.29/go.mod h1:LfRkPCD8YHDM2E5eTkos2UpwYeZnBcVarTa8L59bJHA=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.29 h1:hiME6pBzC7OTl9LMtlyTWBuEl1f4QBcUmFDKC7MLXtc=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.29/go.mod h1:G7RP+uhagpKtKhd1BM9N6JQqjCcGEU47K5lBVZQyRQw=
|
||||
github.com/aws/aws-sdk-go-v2/service/kafka v1.52.0 h1:jalIJqKvZMvJRvs6ABLX+FhHz8E9pjU03Pyml4D9r3k=
|
||||
github.com/aws/aws-sdk-go-v2/service/kafka v1.52.0/go.mod h1:pW4pYNuVeScl13yqwsjLY0F/7g2YD8E0AvR6SOQsJZE=
|
||||
github.com/aws/aws-sdk-go-v2/service/lightsail v1.54.0 h1:07DKnL5eKSel3XEM2UxlD/z9zUZZ6XMHLGDXkAdY4u8=
|
||||
github.com/aws/aws-sdk-go-v2/service/lightsail v1.54.0/go.mod h1:Etcg8xorq1b0g0V2KMNgFjubYITZseJv08qtX/3szko=
|
||||
github.com/aws/aws-sdk-go-v2/service/rds v1.118.2 h1:pkEeQneYFpTAnGhyqSbyp/DlCPPJTGt0GkWahlLYzMA=
|
||||
github.com/aws/aws-sdk-go-v2/service/rds v1.118.2/go.mod h1:7gS+cGrKF0mH253QHFlStmx79ws+DlNk+04ZRfmw3U0=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.103.3 h1:JRseEu/vIDMaWis4bSw0QbXL+cvIGc1XnX076H5ZXLE=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.103.3/go.mod h1:77ZAgynvx1txMvDG8gGWoWkO1augYDxkp9JElWFgjQU=
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.2.0 h1:3nXpRcFwRCW8n7HgO2QGy0Dc20eQNfBuUemGQhpF8m8=
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.2.0/go.mod h1:LxYujSTLPRlp2vTtcUO/+1ilrew8ytt6SvQyOgejzFQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.31.3 h1:ey1XLTYXb9PcLt4535632o5kCGXNXEhNb620Dqwuylo=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.31.3/go.mod h1:Lk7PlmoTYryQmyBG0EXqj5BcUbj3whXdU2s3yGI3EAc=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.36.6 h1:yLr03zQE/5Eu5l3QU0Si+xMbLMbSDF2YXsigqXngs6g=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.36.6/go.mod h1:Q5N6icH+KJZDLh+ESNwzdv6cZ6vLFF/egy3IOxWhmz4=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.43.3 h1:VrIhKRCSK1umelSgB9RghvA9RTUYeQffyAS5ApXehNI=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.43.3/go.mod h1:r8wkDOuLaaMFqFiYAb8dGY2A3gJCOujMc6CFOVC4Zhc=
|
||||
github.com/aws/smithy-go v1.27.2 h1:y9NPmSE6am6LjEFPfqHqG/jJk7AauQvhCJONKh7kpzk=
|
||||
github.com/aws/smithy-go v1.27.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
|
||||
github.com/aws/aws-sdk-go-v2 v1.43.0 h1:fharf/WhbRAVZ1du0QL7roNFxZ6T/sWr+4Ni617bwSI=
|
||||
github.com/aws/aws-sdk-go-v2 v1.43.0/go.mod h1:5pKeft2eJj+gElQ38Jqg4ibCqh+/AK33/0X3hip7IjM=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.14 h1:3IZY0XAJquT3aHzbkHfPzy4ACPcEjVG0x87KOwtpqGY=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.14/go.mod h1:zwM6veDkhGgQFqkBy+uT28AAYpLu+uFMlPl+rCg/73E=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.31 h1:n4nY9O3QKoHIkL85EX+V8RcMFtOhlpTFhGArg915PXk=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.31/go.mod h1:PN0NYDCCoOpGGsZ2+elDUidmHfQBPyYzN2GCgl8HEBs=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.30 h1:TTCvvzFU6gXa4iJecNG/0F/B0oYTiazoRECr2XyLHrY=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.30/go.mod h1:jKxAp2AEncnliinzpgOSZDFv6+VjvWhjw/AtbfsWT9U=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.31 h1:kfVL5wAunCJycL6MOQ6aNh6PlAYEymflcjuKmrWUA0o=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.31/go.mod h1:nWfRNDAppujCQgOUd43lKT4yeLv9z3nJ3bw1G3BgQKo=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.22.35 h1:TwCjUC1rnFKTtfqEpQY9ClYPFpGpUaouODrdGPB5b3Y=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.22.35/go.mod h1:V0zqtP3iJk9zu86GxuQGN09RYyQB+3mjcPiyfLC6wlg=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.31 h1:Z8F3hfCY33IGpJjFAnv0wvtv1FIKj1GHmRDEYqy64tw=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.31/go.mod h1:aVyUoytEyOViR6jhq6jula0xkc5NfBE2hgeF6BvOrao=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.31 h1:hyOxUyXdh3AyjE93gBgsfziJag9ACwcs+ZpDBLzi8mw=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.31/go.mod h1:OERqI9k0draSLB8O8woxY3q25ZWTELRK4RRoLMuMZFo=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.32 h1:0MrUL35H/Y4kdFfItoR5jCgtDQ4Z/8LudAoIHRfA4hE=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.32/go.mod h1:2tNZkuWz54arj8mHVf+8Y7cKkcD8Wr/fBpENgEXpjLc=
|
||||
github.com/aws/aws-sdk-go-v2/service/ec2 v1.307.0 h1:ZQMhFWDFhwJbq3xCggO0gh3AW+yu65QtcT9F5HfdZhY=
|
||||
github.com/aws/aws-sdk-go-v2/service/ec2 v1.307.0/go.mod h1:8mrDF7OtbuL0QpwP4YCvLuoOE4/5lL7D33MXgp069/Y=
|
||||
github.com/aws/aws-sdk-go-v2/service/ecs v1.83.0 h1:LQKIHuVHqdbU9LUt5c2G9f+CcQAzolxQmAch3RTORMc=
|
||||
github.com/aws/aws-sdk-go-v2/service/ecs v1.83.0/go.mod h1:0vahPCh3slyORHbSuAP8YDyJKLEUQAMX7+bzYGxEnVI=
|
||||
github.com/aws/aws-sdk-go-v2/service/elasticache v1.54.3 h1:KZDlMf8V5riU8xBCMJLWhfa+RP/MIagz2qJFwRg/b1g=
|
||||
github.com/aws/aws-sdk-go-v2/service/elasticache v1.54.3/go.mod h1:nsMdHtF/ned4F5GCAfoerJaa/Q6cx+G+WYNsb/TFN7Q=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.13 h1:mbRIur/BiHK6SKPjoBIXSE/hJ6g6JGRLuxQy1jGjlN4=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.13/go.mod h1:ITg9em2KbJx1s0y4aqRX5OYWG6HBZ5TVR//OdpEZ2CQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.24 h1:mdPwDQPqxlw9Sc62Nt15yjEcARaDbPXkjRYtXsUripo=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.24/go.mod h1:ls5ytnwLTcQaUu32fMYXFI3MjpKuTwL840PAm9iqyEg=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.31 h1:w2SIhW92DZPFrSL4ksVCr8IYff5OZwIcxg8+95tzvAI=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.31/go.mod h1:wAhpCQbkov+IcvjozJbd2xRCoZybUEHNkcFunssNACg=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.32 h1:jWXtZdCnhXa9sGFixRaU2AxT4DIVse9HS4E2f+/KwV0=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.32/go.mod h1:9JS1UpfVvyD/ZPX8GsKb/Pq8scEM+7GP5fqh9SwH7po=
|
||||
github.com/aws/aws-sdk-go-v2/service/kafka v1.52.6 h1:1Cn7pNj5Knye9dx2KFY0UmSdXM+DZdzQaeBx72QHgSQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/kafka v1.52.6/go.mod h1:5SCWP3gW59x0gRYHuwzXoj/ZuxEoa+j9/OeynrJd/sk=
|
||||
github.com/aws/aws-sdk-go-v2/service/lightsail v1.56.1 h1:bbOZEcMgnUQocfDoaaU2f148Te/MpUk6FkOGtJyfwlg=
|
||||
github.com/aws/aws-sdk-go-v2/service/lightsail v1.56.1/go.mod h1:428ttHou5n2J4/oQAQS9EmOU6LrBv48F2bGk+Ta7EF4=
|
||||
github.com/aws/aws-sdk-go-v2/service/rds v1.119.3 h1:SIGdk+wA+xGXgN+L7Jr3Ot83Mjh3jpjyJIwZd3DqAnU=
|
||||
github.com/aws/aws-sdk-go-v2/service/rds v1.119.3/go.mod h1:zCRPUdp05FEZG3OO7LmJq9xkSDjMEhkiVrZV0oJs2a0=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.106.0 h1:7QZWVJZWzHivHWIa+5TELLaBBkbuoj0GPwQtMlJ0sqk=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.106.0/go.mod h1:fcvq5L7dK+5cQFicEJwpI6e6Wn8NY2i6yT5wRLYVc7s=
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.5.0 h1:OHH5iTQvVGmfHjX/5Q+vFuA/Rf2x6/95aJ/75QCQSm4=
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.5.0/go.mod h1:mCF3AK9PpL49oOrhniUXWAfhVBVQ/XbytoE5eccZUIs=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.33.0 h1:CaJyYhxBE0M/HJX/YvSaSmQlsI91VHB0lKU8LtLxL3A=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.33.0/go.mod h1:+e6BMRMPjBQoCw/WovYR9GLy2IU0z4Q77smOB1DraSg=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.0 h1:tC323YV77QdafeBr6LUhLDTsboyuyHLNRwAyCP44kGU=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.0/go.mod h1:SfLK1sgviHmbI+MozR9iDwDjL4cdCVZtahsjoR+z7wg=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.45.0 h1:Pd6PNlp4t8PTXxqzstICl52Wsy78vpjFZ7PRUj44mJc=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.45.0/go.mod h1:rmQ0TnHzuLPmabgjPcsywhsSOmaBDgzR4zvDxSPsGdg=
|
||||
github.com/aws/smithy-go v1.27.4 h1:JQcphmBN4f0q/sPqXqROIItRNV/hy10cgu7CsFy616M=
|
||||
github.com/aws/smithy-go v1.27.4/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
|
||||
github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 h1:6df1vn4bBlDDo4tARvBm7l6KA9iVMnE3NWizDeWSrps=
|
||||
github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3/go.mod h1:CIWtjkly68+yqLPbvwwR/fjNJA/idrtULjZWh2v1ys0=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
@@ -134,8 +132,8 @@ github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1x
|
||||
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cheggaaa/pb/v3 v3.1.7 h1:2FsIW307kt7A/rz/ZI2lvPO+v3wKazzE4K/0LtTWsOI=
|
||||
github.com/cheggaaa/pb/v3 v3.1.7/go.mod h1:/Ji89zfVPeC/u5j8ukD0MBPHt2bzTYp74lQ7KlgFWTQ=
|
||||
github.com/cheggaaa/pb/v3 v3.2.0 h1:ziC7JV5/Ge2iZNa9ckxdXBxHHyPgC+p/QGzhWRoPlHU=
|
||||
github.com/cheggaaa/pb/v3 v3.2.0/go.mod h1:KtXGzgipYGqY3avGtFmlQTgiT88AEFvc1LvPk7oA9fM=
|
||||
github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
|
||||
github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
|
||||
github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik=
|
||||
@@ -152,8 +150,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE=
|
||||
github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA=
|
||||
github.com/digitalocean/godo v1.193.0 h1:CSbbUl5LufT75KPNvex3vDnBYjY2RfJWs7T3Ac7dHpA=
|
||||
github.com/digitalocean/godo v1.193.0/go.mod h1:xQsWpVCCbkDrWisHA72hPzPlnC+4W5w/McZY5ij9uvU=
|
||||
github.com/digitalocean/godo v1.196.0 h1:32bkla5iESoGaCHmXD2+fUXAepR23wWwbzPjwenIhik=
|
||||
github.com/digitalocean/godo v1.196.0/go.mod h1:xQsWpVCCbkDrWisHA72hPzPlnC+4W5w/McZY5ij9uvU=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/go-connections v0.7.0 h1:6SsRfJddP22WMrCkj19x9WKjEDTB+ahsdiGYf0mN39c=
|
||||
@@ -185,38 +183,38 @@ github.com/fxamacker/cbor/v2 v2.9.2/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj2
|
||||
github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA=
|
||||
github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8=
|
||||
github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-openapi/jsonpointer v0.23.1 h1:1HBACs7XIwR2RcmItfdSFlALhGbe6S92p0ry4d1GWg4=
|
||||
github.com/go-openapi/jsonpointer v0.23.1/go.mod h1:iWRmZTrGn7XwYhtPt/fvdSFj1OfNBngqRT2UG3BxSqY=
|
||||
github.com/go-openapi/jsonreference v0.21.5 h1:6uCGVXU/aNF13AQNggxfysJ+5ZcU4nEAe+pJyVWRdiE=
|
||||
github.com/go-openapi/jsonreference v0.21.5/go.mod h1:u25Bw85sX4E2jzFodh1FOKMTZLcfifd1Q+iKKOUxExw=
|
||||
github.com/go-openapi/swag v0.25.5 h1:pNkwbUEeGwMtcgxDr+2GBPAk4kT+kJ+AaB+TMKAg+TU=
|
||||
github.com/go-openapi/swag v0.25.5/go.mod h1:B3RT6l8q7X803JRxa2e59tHOiZlX1t8viplOcs9CwTA=
|
||||
github.com/go-openapi/swag/cmdutils v0.25.5 h1:yh5hHrpgsw4NwM9KAEtaDTXILYzdXh/I8Whhx9hKj7c=
|
||||
github.com/go-openapi/swag/cmdutils v0.25.5/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0=
|
||||
github.com/go-openapi/swag/conv v0.25.5 h1:wAXBYEXJjoKwE5+vc9YHhpQOFj2JYBMF2DUi+tGu97g=
|
||||
github.com/go-openapi/swag/conv v0.25.5/go.mod h1:CuJ1eWvh1c4ORKx7unQnFGyvBbNlRKbnRyAvDvzWA4k=
|
||||
github.com/go-openapi/swag/fileutils v0.25.5 h1:B6JTdOcs2c0dBIs9HnkyTW+5gC+8NIhVBUwERkFhMWk=
|
||||
github.com/go-openapi/swag/fileutils v0.25.5/go.mod h1:V3cT9UdMQIaH4WiTrUc9EPtVA4txS0TOmRURmhGF4kc=
|
||||
github.com/go-openapi/swag/jsonname v0.26.0 h1:gV1NFX9M8avo0YSpmWogqfQISigCmpaiNci8cGECU5w=
|
||||
github.com/go-openapi/swag/jsonname v0.26.0/go.mod h1:urBBR8bZNoDYGr653ynhIx+gTeIz0ARZxHkAPktJK2M=
|
||||
github.com/go-openapi/swag/jsonutils v0.25.5 h1:XUZF8awQr75MXeC+/iaw5usY/iM7nXPDwdG3Jbl9vYo=
|
||||
github.com/go-openapi/swag/jsonutils v0.25.5/go.mod h1:48FXUaz8YsDAA9s5AnaUvAmry1UcLcNVWUjY42XkrN4=
|
||||
github.com/go-openapi/swag/loading v0.25.5 h1:odQ/umlIZ1ZVRteI6ckSrvP6e2w9UTF5qgNdemJHjuU=
|
||||
github.com/go-openapi/swag/loading v0.25.5/go.mod h1:I8A8RaaQ4DApxhPSWLNYWh9NvmX2YKMoB9nwvv6oW6g=
|
||||
github.com/go-openapi/swag/mangling v0.25.5 h1:hyrnvbQRS7vKePQPHHDso+k6CGn5ZBs5232UqWZmJZw=
|
||||
github.com/go-openapi/swag/mangling v0.25.5/go.mod h1:6hadXM/o312N/h98RwByLg088U61TPGiltQn71Iw0NY=
|
||||
github.com/go-openapi/swag/netutils v0.25.5 h1:LZq2Xc2QI8+7838elRAaPCeqJnHODfSyOa7ZGfxDKlU=
|
||||
github.com/go-openapi/swag/netutils v0.25.5/go.mod h1:lHbtmj4m57APG/8H7ZcMMSWzNqIQcu0RFiXrPUara14=
|
||||
github.com/go-openapi/swag/stringutils v0.25.5 h1:NVkoDOA8YBgtAR/zvCx5rhJKtZF3IzXcDdwOsYzrB6M=
|
||||
github.com/go-openapi/swag/stringutils v0.25.5/go.mod h1:PKK8EZdu4QJq8iezt17HM8RXnLAzY7gW0O1KKarrZII=
|
||||
github.com/go-openapi/swag/typeutils v0.25.5 h1:EFJ+PCga2HfHGdo8s8VJXEVbeXRCYwzzr9u4rJk7L7E=
|
||||
github.com/go-openapi/swag/typeutils v0.25.5/go.mod h1:itmFmScAYE1bSD8C4rS0W+0InZUBrB2xSPbWt6DLGuc=
|
||||
github.com/go-openapi/swag/yamlutils v0.25.5 h1:kASCIS+oIeoc55j28T4o8KwlV2S4ZLPT6G0iq2SSbVQ=
|
||||
github.com/go-openapi/swag/yamlutils v0.25.5/go.mod h1:Gek1/SjjfbYvM+Iq4QGwa/2lEXde9n2j4a3wI3pNuOQ=
|
||||
github.com/go-openapi/jsonpointer v1.0.0 h1:kR9tHqY0CtZaOPVFm622dPVNhrvYpwr4uCxgL3h1H8s=
|
||||
github.com/go-openapi/jsonpointer v1.0.0/go.mod h1:Z3rw7dWu1p9IgitXCFamSlA5lmDiklEB6vkaxcNZW5Y=
|
||||
github.com/go-openapi/jsonreference v1.0.0 h1:jlmTr6torcd1YgDQvSfNmRtKzYDO4FGBkrAdlAVWnpY=
|
||||
github.com/go-openapi/jsonreference v1.0.0/go.mod h1:jtwdyGbJk0Xhe5Y+rwtglQP6Sb1WZST4rT32LWB+sv0=
|
||||
github.com/go-openapi/swag v0.27.1 h1:VotvOLWW8q/EAxB0YdsBBGC8XYyeL1YwBj2ungAGPNg=
|
||||
github.com/go-openapi/swag v0.27.1/go.mod h1:GTkJPwHfhJp6MWr4/rCh64HVI3Ofu+tcsbfjfHmTxpE=
|
||||
github.com/go-openapi/swag/cmdutils v0.27.1 h1:I7sYqaWVl5mq0NEmNQkAmFDyNin9ufvMX/p2zwtQaOE=
|
||||
github.com/go-openapi/swag/cmdutils v0.27.1/go.mod h1:Sm1MVFMkF6guJJ+pQqHnQA3N0j9qALV3NxzDSv6bETM=
|
||||
github.com/go-openapi/swag/conv v0.27.1 h1:8wi9ZG+olmY1wXphl93EWniPtbSPkXM/feH7FgjsvrU=
|
||||
github.com/go-openapi/swag/conv v0.27.1/go.mod h1:QbqMivkpKhC3g1B1GGGOJ6ANewI3S62dbzYu3Duowqs=
|
||||
github.com/go-openapi/swag/fileutils v0.27.1 h1:QQqBSoi5mW4XpU85nS0mLcA+zAE6vLzrb0QkmLKf9oM=
|
||||
github.com/go-openapi/swag/fileutils v0.27.1/go.mod h1:VvJFZLTZS0AI854gEQz5tk7dBESdLjiNUMSZ/th2ry8=
|
||||
github.com/go-openapi/swag/jsonutils v0.27.1 h1:SVgK3i4USzCU5mibOOS/l4ea2h9UQXy7J7RNLTjuXjU=
|
||||
github.com/go-openapi/swag/jsonutils v0.27.1/go.mod h1:tdlEpZqdcQ17uj6J4YdK9vd8It5qWMwjWXOs0tjpRlk=
|
||||
github.com/go-openapi/swag/loading v0.27.1 h1:/DxUgDXKbBX4bcn7r9uEXfJyzN5XpiJmZplzQTjrRCY=
|
||||
github.com/go-openapi/swag/loading v0.27.1/go.mod h1:jvGh3iA2+zyUUycB5fgJWzeHnhrpvGnJJM0RVE9ZShE=
|
||||
github.com/go-openapi/swag/mangling v0.27.1 h1:yC9D0HyUE8gbP+BfmGx9+AA89ikwZTMjESK3OnnoaqA=
|
||||
github.com/go-openapi/swag/mangling v0.27.1/go.mod h1:jtBE2+V+3pILxOR7Vgce+Cwp6A2PgZbvVqfNntbVs0w=
|
||||
github.com/go-openapi/swag/netutils v0.27.1 h1:mICMFoS82F5TZ4Zy3cqmcQk+BFeCp3Uyq3Np7GI0/qU=
|
||||
github.com/go-openapi/swag/netutils v0.27.1/go.mod h1:J+WYyFMLtvtCGqa6jLv+YNUmIKI3ZRQRrvfNDMoQoEQ=
|
||||
github.com/go-openapi/swag/pools v0.27.1 h1:9LeadcMyb2GJCbXX5hVQDbZ2Lq9TL4dCs/nx1j5DO0E=
|
||||
github.com/go-openapi/swag/pools v0.27.1/go.mod h1:kVQefhSK5RWuRe7BXsL8htgBPAMpN7HDGpGEknqugeE=
|
||||
github.com/go-openapi/swag/stringutils v0.27.1 h1:ZXePZ0r2p1qSjo8tD3Un4vFj8+FqlCkczxDrJIhYUp8=
|
||||
github.com/go-openapi/swag/stringutils v0.27.1/go.mod h1:lzRN95CxXmA03XcDWHLOb6nOMcxCqR5rGY0lOgsfRoM=
|
||||
github.com/go-openapi/swag/typeutils v0.27.1 h1:KSTdFlfnse4r6dP9IrEnwMldjE+zs71UeEB3//PtVXc=
|
||||
github.com/go-openapi/swag/typeutils v0.27.1/go.mod h1:Srm0xFNRZ1Y+vCxJclo5qzx8aj+1pAKda/YfFPrG0dQ=
|
||||
github.com/go-openapi/swag/yamlutils v0.27.1 h1:ftxv6xvXb1E3zohUc+okZ9nSqNb9StQX/FXnKZ98sQA=
|
||||
github.com/go-openapi/swag/yamlutils v0.27.1/go.mod h1:bnxFIB1qewGRiZHypXGZ3fNgf13/0HfRgnS/iZBDrOo=
|
||||
github.com/go-resty/resty/v2 v2.17.2 h1:FQW5oHYcIlkCNrMD2lloGScxcHJ0gkjshV3qcQAyHQk=
|
||||
github.com/go-resty/resty/v2 v2.17.2/go.mod h1:kCKZ3wWmwJaNc7S29BRtUhJwy7iqmn+2mLtQrOyQlVA=
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
|
||||
@@ -246,10 +244,10 @@ github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
|
||||
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.16 h1:F/VPrx0YPBdksZJQdCAp0WUsqnNmZpUZszzfYt0M5Dw=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.16/go.mod h1:9Yb0eAkH/Xqhvv3zbeKf/+wMJqCeocWc6KIhDvEAuYE=
|
||||
github.com/googleapis/gax-go/v2 v2.22.0 h1:PjIWBpgGIVKGoCXuiCoP64altEJCj3/Ei+kSU5vlZD4=
|
||||
github.com/googleapis/gax-go/v2 v2.22.0/go.mod h1:irWBbALSr0Sk3qlqb9SyJ1h68WjgeFuiOzI4Rqw5+aY=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.18 h1:hvVi34VucdrV1IIsiWuqYM8kutw/92MxNEFxCJZEh0k=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.18/go.mod h1:rSEsBUemEBZEexP2y6jPp16LUmUbjmSbcPMQizR0o4k=
|
||||
github.com/googleapis/gax-go/v2 v2.23.0 h1:Tchl7qkvE7Ip3y+ztvNufYFvkfqTe7NfLTYGIdJRLuE=
|
||||
github.com/googleapis/gax-go/v2 v2.23.0/go.mod h1:rBQKOVJCdb8IFEzg+FCwlt1LP/xMDGuqUXhUG+XMXEg=
|
||||
github.com/gophercloud/gophercloud/v2 v2.12.0 h1:Gxmc/Bog1UDKkxTcQW7MSPTDviJXpLeEgVeN5KrxoCo=
|
||||
github.com/gophercloud/gophercloud/v2 v2.12.0/go.mod h1:H7TTOxbLy8RIaHSNhI2GCrWIzw4Xpw8Xn2mBhCUT5kA=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
|
||||
@@ -278,16 +276,16 @@ github.com/hashicorp/go-version v1.9.0 h1:CeOIz6k+LoN3qX9Z0tyQrPtiB1DFYRPfCIBtaX
|
||||
github.com/hashicorp/go-version v1.9.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4=
|
||||
github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/nomad/api v0.0.0-20260528135333-5b027732945f h1:sdf4a6FF3tC1/c0buuizLAwZa/xLu4gWD87qWrzQLvo=
|
||||
github.com/hashicorp/nomad/api v0.0.0-20260528135333-5b027732945f/go.mod h1:Kr8imJwigbQ/50BqVae2+JL+AyX+FnzbnuCoIFb6iYg=
|
||||
github.com/hashicorp/nomad/api v0.0.0-20260616181215-ea1ca2d932bf h1:pU9wD+K2z1mY8ypEmMlfnuxPURG6Vf/OCZsyuWP/3AE=
|
||||
github.com/hashicorp/nomad/api v0.0.0-20260616181215-ea1ca2d932bf/go.mod h1:Kr8imJwigbQ/50BqVae2+JL+AyX+FnzbnuCoIFb6iYg=
|
||||
github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY=
|
||||
github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
|
||||
github.com/hetznercloud/hcloud-go/v2 v2.41.2 h1:fO5zsMgp5oejrtnFj8mYuqlp+iMuirpaKv4b5FYNRdQ=
|
||||
github.com/hetznercloud/hcloud-go/v2 v2.41.2/go.mod h1:9OGvC//jbHE4sv2Oyo0bQ2vEWuUMKYoNMyj9Qxz2qcc=
|
||||
github.com/hetznercloud/hcloud-go/v2 v2.43.0 h1:soqEUxJJqbf8UICQmDXfUwY/khfROAk0fi1s0bnBtd8=
|
||||
github.com/hetznercloud/hcloud-go/v2 v2.43.0/go.mod h1:d0s2WLe7jSoStamv3eHoWgBSOxc/K17tYSXsqUkbse0=
|
||||
github.com/influxdata/influxdb v1.12.4 h1:vn/1rvFYkYpg9efRw79+PUPPnMX7HwyJV+hDIB9IrOQ=
|
||||
github.com/influxdata/influxdb v1.12.4/go.mod h1:czsGl4TCm2kWtzEHsGh74Nye77o/KgmKsLtF4/L9QVc=
|
||||
github.com/ionos-cloud/sdk-go/v6 v6.3.7 h1:t773JkC/asnyVqeQ+OvN9WCRZuosSoPtJfyM82EFCWY=
|
||||
github.com/ionos-cloud/sdk-go/v6 v6.3.7/go.mod h1:nUGHP4kZHAZngCVr4v6C8nuargFrtvt7GrzH/hqn7c4=
|
||||
github.com/ionos-cloud/sdk-go/v6 v6.3.8 h1:CUZzrNciLM2IlmZtnclIznjST29tAYQbtQ8epiX5RUo=
|
||||
github.com/ionos-cloud/sdk-go/v6 v6.3.8/go.mod h1:nUGHP4kZHAZngCVr4v6C8nuargFrtvt7GrzH/hqn7c4=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
|
||||
@@ -298,8 +296,8 @@ github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRt
|
||||
github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.18.6 h1:2jupLlAwFm95+YDR+NwD2MEfFO9d4z4Prjl1XXDjuao=
|
||||
github.com/klauspost/compress v1.18.6/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
|
||||
github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk=
|
||||
github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
|
||||
github.com/knadh/koanf/maps v0.1.2 h1:RBfmAW5CnZT+PJ1CVc1QSJKf4Xu9kxfQgYVQSu8hpbo=
|
||||
github.com/knadh/koanf/maps v0.1.2/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI=
|
||||
github.com/knadh/koanf/providers/confmap v1.0.0 h1:mHKLJTE7iXEys6deO5p6olAiZdG5zwp8Aebir+/EaRE=
|
||||
@@ -318,8 +316,8 @@ github.com/linode/linodego v1.69.1 h1:f45N2MHR/oece2/ktTTCYmrlfse4//k3NgwcF5zbGZ
|
||||
github.com/linode/linodego v1.69.1/go.mod h1:Fha0NYsQSx5VZK1HQNJY/z/dIxxkFp+vb5veawbmAUw=
|
||||
github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY=
|
||||
github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4=
|
||||
github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
|
||||
github.com/mattn/go-isatty v0.0.23 h1:cYwCQTQf3HB6xUC+BtyCLZNr7IzbOmoZbmssVNzSyiQ=
|
||||
github.com/mattn/go-isatty v0.0.23/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A=
|
||||
github.com/mattn/go-runewidth v0.0.24 h1:cpokDiIn0MGnhdHwuWnJBITySJ20QyNGnY2kR/ay2DU=
|
||||
github.com/mattn/go-runewidth v0.0.24/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||
github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI=
|
||||
@@ -350,12 +348,12 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s=
|
||||
github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.154.0 h1:WS8HkUa6p8iVJ2v0mmGEK1a9R2b+Uro6tSG+4IfX6rk=
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.154.0/go.mod h1:9QPTx+XgZE7ktvh5jT5TvSisIkh2Fwc7mrfuf6+j2/U=
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.154.0 h1:Kda+8F8o5QATBLP5K2MKmI2t7ddr7sBaV0EhZpjlvB0=
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.154.0/go.mod h1:iVnoGSVXYhnyuQ6TQNhBIHqtu7h0LTXbSyWy584eBjg=
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/processor/deltatocumulativeprocessor v0.154.0 h1:U/MRkEeVwZ3zl8hOlUBP/Q/RMgLfMbTHQoATlLXhI4I=
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/processor/deltatocumulativeprocessor v0.154.0/go.mod h1:dFTV2c6rjph2ZMtkq9xHN5QuYbUSQ+o/25UQfIY3QUQ=
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.157.0 h1:WzyLbYQ5GswNa/3Jma/bYYbn2ziLoQct2VEoN5u1j74=
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.157.0/go.mod h1:TmipmukIEZQwvWXuFMaSnDBlaNzgsyiHcv54luc76pk=
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.157.0 h1:oQWc2BKFkPqo14Zh+qDEWZItxJacKSubLjtFirojFnk=
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.157.0/go.mod h1:fMeXcxEg6tHlCPRjf2jQ6KavnvDrwoGvJ8q8ihDk3BE=
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/processor/deltatocumulativeprocessor v0.157.0 h1:y/Uf4K+H3WOWIFEbqymmBcw6s5QQe/hxTy23UERke7w=
|
||||
github.com/open-telemetry/opentelemetry-collector-contrib/processor/deltatocumulativeprocessor v0.157.0/go.mod h1:2J1/XjEfj6pQkRGOjE81TjDFUxH+v0JnMtELt0VhOtA=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||
@@ -372,20 +370,20 @@ github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_golang/exp v0.0.0-20260602051030-3537b20ac86b h1:633sracZPrB7O7T6r5skFtwqXDOrXlQkE9Wr5DnYVJE=
|
||||
github.com/prometheus/client_golang/exp v0.0.0-20260602051030-3537b20ac86b/go.mod h1:7hAEIbflIgnK0HubVroVy6UgJYYKryF6p3mP/dcyay8=
|
||||
github.com/prometheus/client_golang v1.24.0 h1:5XStIklKuAtJSNpdD3s8XJj/Yv78IQmE1kbNk87JrAI=
|
||||
github.com/prometheus/client_golang v1.24.0/go.mod h1:QcsNdotprC2nS4BTM2ucbcqxd2CeXTEa9jW7zHO9iDE=
|
||||
github.com/prometheus/client_golang/exp v0.0.0-20260723095000-436bf2e0fb60 h1:n7SAxoEJEzwf8mrZLQzxCAs3agUbBU3g7hEffGZP7v0=
|
||||
github.com/prometheus/client_golang/exp v0.0.0-20260723095000-436bf2e0fb60/go.mod h1:CoLfLGxCH1vzpdmZ+p2uaUGH43j+99HYmnK1Wak6rS4=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.68.1 h1:omjRRl4QP4komogpXuhfeOiisQg7xdy8VM1UY+pStaY=
|
||||
github.com/prometheus/common v0.68.1/go.mod h1:ZzL3f6u94qUxh9p+tJTrF+FvBS1XXbbRAZCQkytAL0Y=
|
||||
github.com/prometheus/common v0.70.1 h1:1HvjP4D5oL3t8RsPlwxA9onvvStjtIHYE5XuuwOi/PY=
|
||||
github.com/prometheus/common v0.70.1/go.mod h1:VdFUQDMZK3VLkurFUVhia6uys/0suUp86TJz5qbJRhc=
|
||||
github.com/prometheus/otlptranslator v1.0.0 h1:s0LJW/iN9dkIH+EnhiD3BlkkP5QVIUVEoIwkU+A6qos=
|
||||
github.com/prometheus/otlptranslator v1.0.0/go.mod h1:vRYWnXvI6aWGpsdY/mOT/cbeVRBlPWtBNDb7kGR3uKM=
|
||||
github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc=
|
||||
github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo=
|
||||
github.com/prometheus/prometheus v0.312.0 h1:f9jdv2fQhQ1fks9a9YwlGZrKr4hih0rRP/rh0mu3Q18=
|
||||
github.com/prometheus/prometheus v0.312.0/go.mod h1:8oAYd2XPgHXLP4fFKam594R/ZLlPicrrBkVdaWt74Sw=
|
||||
github.com/prometheus/procfs v0.21.1 h1:GljZCt+zSTS+NZq88cyQ1LjZ+RCHp3uVuabBWA5+OJI=
|
||||
github.com/prometheus/procfs v0.21.1/go.mod h1:aB55Cww9pdSJVHk0hUf0inxWyyjPogFIjmHKYgMKmtY=
|
||||
github.com/prometheus/prometheus v0.313.1 h1:BOyoPuxCL+58NpuZ0ovKuKo8ALmVLTCTIM7r8znt6z8=
|
||||
github.com/prometheus/prometheus v0.313.1/go.mod h1:Kq9A+EPun2WyVusbQxO7Tx1RxKqLKFclfiBGJA1mFkk=
|
||||
github.com/prometheus/sigv4 v0.4.1 h1:EIc3j+8NBea9u1iV6O5ZAN8uvPq2xOIUPcqCTivHuXs=
|
||||
github.com/prometheus/sigv4 v0.4.1/go.mod h1:eu+ZbRvsc5TPiHwqh77OWuCnWK73IdkETYY46P4dXOU=
|
||||
github.com/puzpuzpuz/xsync/v4 v4.5.0 h1:vOSWu6b57/emh+L/Cw0BeQfvxa/cogFywXHeGUxQxAg=
|
||||
@@ -398,8 +396,8 @@ github.com/scaleway/scaleway-sdk-go v1.0.0-beta.36 h1:ObX9hZmK+VmijreZO/8x9pQ8/P
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.36/go.mod h1:LEsDu4BubxK7/cWhtlQWfuxwL4rf/2UEpxXz1o1EMtM=
|
||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spiffe/go-spiffe/v2 v2.7.0 h1:uXe1MflJoHw58wAUvxVlcM7WpKtijWG7I1UidcGh6g4=
|
||||
github.com/spiffe/go-spiffe/v2 v2.7.0/go.mod h1:47Q0Q9/AqGha8QLHp+kxpH4Wca7X7EnOtlIJy3mxZ3U=
|
||||
github.com/spiffe/go-spiffe/v2 v2.8.1 h1:eXZMLsu+3MLEPJyGJkolqtVrteZfQdUpOWj6LTiDl/E=
|
||||
github.com/spiffe/go-spiffe/v2 v2.8.1/go.mod h1:47Q0Q9/AqGha8QLHp+kxpH4Wca7X7EnOtlIJy3mxZ3U=
|
||||
github.com/stackitcloud/stackit-sdk-go/core v0.26.0 h1:jQEb9gkehfp6VCP6TcYk7BI10cz4l0KM2L6hqYBH2QA=
|
||||
github.com/stackitcloud/stackit-sdk-go/core v0.26.0/go.mod h1:WU1hhxnjXw2EV7CYa1nlEvNpMiRY6CvmIOaHuL3pOaA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@@ -424,8 +422,8 @@ github.com/valyala/fastrand v1.1.0 h1:f+5HkLW4rsgzdNoleUOB69hyT9IlD2ZQh9GyDMfb5G
|
||||
github.com/valyala/fastrand v1.1.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ=
|
||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/valyala/gozstd v1.24.0 h1:M/9L3h7bVwbj2gZwrmuoaxzwVrmBUvos2jG9cZtuhlc=
|
||||
github.com/valyala/gozstd v1.24.0/go.mod h1:y5Ew47GLlP37EkTB+B4s7r6A5rdaeB7ftbl9zoYiIPQ=
|
||||
github.com/valyala/gozstd v1.25.0 h1:7gS7+5zwidZT1BFQqGPAPII8ekZ3tvYTp5IvOEWC34Y=
|
||||
github.com/valyala/gozstd v1.25.0/go.mod h1:y5Ew47GLlP37EkTB+B4s7r6A5rdaeB7ftbl9zoYiIPQ=
|
||||
github.com/valyala/histogram v1.2.0 h1:wyYGAZZt3CpwUiIb9AU/Zbllg1llXyrtApRS815OLoQ=
|
||||
github.com/valyala/histogram v1.2.0/go.mod h1:Hb4kBwb4UxsaNbbbh+RRz8ZR6pdodR57tzWUS3BUzXY=
|
||||
github.com/valyala/quicktemplate v1.8.0 h1:zU0tjbIqTRgKQzFY1L42zq0qR3eh4WoQQdIdqCysW5k=
|
||||
@@ -438,46 +436,44 @@ github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342 h1:FnBeRrxr7OU4VvAz
|
||||
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.8.4 h1:oat/nd3U6NeQqFEL3xpEJq7d7c86NI+DbSNGAs4xnjA=
|
||||
github.com/yuin/goldmark v1.8.4/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/collector/component v1.60.0 h1:LpIjHMn7OOjUsFR84ROc2kqPbP1xnKyDCGi7ZVqEaKU=
|
||||
go.opentelemetry.io/collector/component v1.60.0/go.mod h1:Rag+NNgiGIkcGYlcTfJtMh2l0T5XS1KNv9Wjw9yofAk=
|
||||
go.opentelemetry.io/collector/component/componentstatus v0.154.0 h1:4ifSCy2Y332iZ5AldHt9ujVjY6XKxhVe/hND4TSDarg=
|
||||
go.opentelemetry.io/collector/component/componentstatus v0.154.0/go.mod h1:ZsBIax7tvvODn0XqTyhTfKZjm96zVKnLUKvlN8SHFjo=
|
||||
go.opentelemetry.io/collector/component/componenttest v0.154.0 h1:uH06tUatG4S45A/f3sFENMMAMzWURmgxKK3MAbVZAUI=
|
||||
go.opentelemetry.io/collector/component/componenttest v0.154.0/go.mod h1:SQ1JRosjFAZ7kN2yNHNcNakOliqrP0QxglKcYyUrUpQ=
|
||||
go.opentelemetry.io/collector/confmap v1.60.0 h1:TEBi/N3kac/JI4VTEq9LjqRCFdF2JS2MHOCEiHq8GSM=
|
||||
go.opentelemetry.io/collector/confmap v1.60.0/go.mod h1:Z693ETewV4n8JsOO2jp/iLe1PGGpFCIzuNsF1xLeiSY=
|
||||
go.opentelemetry.io/collector/confmap/xconfmap v0.154.0 h1:tarvY9S02jkYNYW/4+yD02RRatwJAojMD430Bs4JD/4=
|
||||
go.opentelemetry.io/collector/confmap/xconfmap v0.154.0/go.mod h1:zcVRrY1gS8qVwBrTrhzVI67tMAUu5BONTsIXzjXu1Ho=
|
||||
go.opentelemetry.io/collector/consumer v1.60.0 h1:SWP/0HvDnWiiy/4S366CiatAZ4gFl410UmggrZEcWVg=
|
||||
go.opentelemetry.io/collector/consumer v1.60.0/go.mod h1:nkp1NBtKQzme7WFF7fkgRgDlQLs49VIMOn8rO0jfmYU=
|
||||
go.opentelemetry.io/collector/consumer/consumertest v0.154.0 h1:G9gFP86ZsglC3mTLA6cqOrW5lvdcEBJrVgHtThE+Sc4=
|
||||
go.opentelemetry.io/collector/consumer/consumertest v0.154.0/go.mod h1:FRLGgy8gFYjm3A+yby1bctz5ZIAn6EUOpuV49KnKbFY=
|
||||
go.opentelemetry.io/collector/consumer/xconsumer v0.154.0 h1:I3rB+S5ORE1XLzqopFXvP6UmYrsj5n1tFlcEAPg96Zw=
|
||||
go.opentelemetry.io/collector/consumer/xconsumer v0.154.0/go.mod h1:WNT9BoyLE/nE5N6WEL4c1GXcfGcRUmSTCSr6e/tyfO4=
|
||||
go.opentelemetry.io/collector/featuregate v1.60.0 h1:/HxHB8hq4N5Fhq5N0C8G6xbXTHxnGcWIryyJzmP7pdc=
|
||||
go.opentelemetry.io/collector/featuregate v1.60.0/go.mod h1:4ga1QBMPEejXXmpyJS8lmaRpknJ3Lb9Bvk6e420bUFU=
|
||||
go.opentelemetry.io/collector/internal/componentalias v0.154.0 h1:g0y8F/qez9cbsgF5+/uU6YC6l5oXVkccIhsXVHmF3xQ=
|
||||
go.opentelemetry.io/collector/internal/componentalias v0.154.0/go.mod h1:F2tudJ/Zcm8w8b768sU65nZc4q2rgY1MhfX5FxDeUgA=
|
||||
go.opentelemetry.io/collector/internal/testutil v0.154.0 h1:iUYHOM8+wONW01A4jFnzauanOYGVBGchKWWtm51is6c=
|
||||
go.opentelemetry.io/collector/internal/testutil v0.154.0/go.mod h1:Jkjs6rkqs973LqgZ0Fe3zrokQRKULYXPIf4HuqStiEE=
|
||||
go.opentelemetry.io/collector/pdata v1.60.0 h1:YcGMHzeJucHen41AoR4mxHro8reUr9SVqt7P0KacKzQ=
|
||||
go.opentelemetry.io/collector/pdata v1.60.0/go.mod h1:Ca8VgZX2wOr6wW4nihPWaCpkJVvzeo6Txa7BJ7/WO90=
|
||||
go.opentelemetry.io/collector/pdata/pprofile v0.154.0 h1:dWrHnKBzzMhkZXfKmSuFpGVAApSUcrQ+mBFzAsO6/8s=
|
||||
go.opentelemetry.io/collector/pdata/pprofile v0.154.0/go.mod h1:BE9oOmAEHVqE+yHRe5Z3qz7co+2SU249DIxVGPRsYf8=
|
||||
go.opentelemetry.io/collector/pdata/testdata v0.154.0 h1:PSc3gogHpJoVHenvMhcxkOPTnEKpaykURxtSNyVXYK4=
|
||||
go.opentelemetry.io/collector/pdata/testdata v0.154.0/go.mod h1:zIT+sag/xmSM6VAMhv2tnEzlQF9n266OcQm4V6roWdU=
|
||||
go.opentelemetry.io/collector/pipeline v1.60.0 h1:ZLk/8K/Xzz+JRBWLmqLlVMwEWVnQvmly6nWeKs+lh6s=
|
||||
go.opentelemetry.io/collector/pipeline v1.60.0/go.mod h1:RD90NG3Jbk965Xaqym3JyHkuol4uZJjQVUkD9ddXJIs=
|
||||
go.opentelemetry.io/collector/processor v1.60.0 h1:B3YgiKa+4tMuJ6v4bSaKUtTCwNRzugbEDei8j7jiPpI=
|
||||
go.opentelemetry.io/collector/processor v1.60.0/go.mod h1:ZRNUW8FHZ+0CW+HoIG0/h+fQq8aYjMz9ccy2w2jguag=
|
||||
go.opentelemetry.io/collector/processor/processortest v0.154.0 h1:2Lu7JGqH3fzg9BE0rmzBwCQB7oRWzM8fs+X5SSZO/4M=
|
||||
go.opentelemetry.io/collector/processor/processortest v0.154.0/go.mod h1:E813PIbkBcwgoDnZ9cjuw70MUNmqxAHIvmDC8gOZiP8=
|
||||
go.opentelemetry.io/collector/processor/xprocessor v0.154.0 h1:ert+SRk5DPSqIxqpOEnywrwVLYSvqEvXwy60F94VtFE=
|
||||
go.opentelemetry.io/collector/processor/xprocessor v0.154.0/go.mod h1:93XyfiqPYokF1i8NQvWsKggt5Si5qZvOcZ2P0l+uxII=
|
||||
go.opentelemetry.io/collector/component v1.63.0 h1:l98ZCxfCTt/O6dYB0JVKKtewaFLe/a6N2qQe61Tbf2o=
|
||||
go.opentelemetry.io/collector/component v1.63.0/go.mod h1:yLGMmT7jUiqvuGvkqlfR1CBi0dRkSV67tq22I08ZMPk=
|
||||
go.opentelemetry.io/collector/component/componentstatus v0.157.0 h1:6aARK84axselDP/YGM1cKVPvg6eIyN7Bg9x8x5GzJb4=
|
||||
go.opentelemetry.io/collector/component/componentstatus v0.157.0/go.mod h1:R1nsiV3JluCaffVfjDmglZ0cU3jJUsiaMXgsAZfc670=
|
||||
go.opentelemetry.io/collector/component/componenttest v0.157.0 h1:kTMapOVJ3YMKf5Lu2j/FdcKipn90KkIrnHkKca8uNfk=
|
||||
go.opentelemetry.io/collector/component/componenttest v0.157.0/go.mod h1:AUzvlwDat8AHaNRDm+dzQ59uaEXQO1qTWccjkRjqq00=
|
||||
go.opentelemetry.io/collector/confmap v1.63.0 h1:1THBabHoQc8t/9r6ztMsghiO1OxDPZpYtn0cuwwsxYI=
|
||||
go.opentelemetry.io/collector/confmap v1.63.0/go.mod h1:ksJNAmLTiMkBjMYwXFW1MRRfXYnRsHXA0fW+ZGwb/1U=
|
||||
go.opentelemetry.io/collector/confmap/xconfmap v0.157.0 h1:jZV8p2wMQhq0ktl1/LAFGOXMCzzfMq56r80r41kKoEs=
|
||||
go.opentelemetry.io/collector/confmap/xconfmap v0.157.0/go.mod h1:W1wZk6YJ3+IyvIZEmkXH/ejwkUtBV2zCThY6ewZYd6E=
|
||||
go.opentelemetry.io/collector/consumer v1.63.0 h1:0eOZh0qmDg6HCJaiUqI9FAb4BD4fKJNNO+ygMV/WW0w=
|
||||
go.opentelemetry.io/collector/consumer v1.63.0/go.mod h1:IVhjv4d+PmSf4Ttz/guJFbWJtRM3Ld3nRcZ12gxy6PA=
|
||||
go.opentelemetry.io/collector/consumer/consumertest v0.157.0 h1:zehAVaLn67AWLhhi/LrUY0Tv06XWx5LYCvvmu7xHXHU=
|
||||
go.opentelemetry.io/collector/consumer/consumertest v0.157.0/go.mod h1:HRxCIepTczx1uWnm3VPPNbt0k+N9fG/ENZDF1dGrkQc=
|
||||
go.opentelemetry.io/collector/consumer/xconsumer v0.157.0 h1:DPbDCHDwbwVa0OoikTktkbXAobN7EgC4XbYaNJIyooI=
|
||||
go.opentelemetry.io/collector/consumer/xconsumer v0.157.0/go.mod h1:IepWZ5ZNBUuS5OiCPQaD/Q1buqriiItxaaMYD7nqYdc=
|
||||
go.opentelemetry.io/collector/featuregate v1.63.0 h1:6EWX1C5AtmIh8hFH97DwK6R7R8Jk3fTLxAUfZPXGutY=
|
||||
go.opentelemetry.io/collector/featuregate v1.63.0/go.mod h1:4ga1QBMPEejXXmpyJS8lmaRpknJ3Lb9Bvk6e420bUFU=
|
||||
go.opentelemetry.io/collector/internal/componentalias v0.157.0 h1:bvVANHVkXRhoRBc92rDsbiC0OHlu9/EbRqPROD9qrPc=
|
||||
go.opentelemetry.io/collector/internal/componentalias v0.157.0/go.mod h1:PCLANRXGlMhf9NmU+JPFHtZuY4WpMOsccXlDHTDTu1w=
|
||||
go.opentelemetry.io/collector/internal/testutil v0.157.0 h1:plojUQwFC5l1ex9KUDaLmCFY/mTxEmf3zrlP7M23IEw=
|
||||
go.opentelemetry.io/collector/internal/testutil v0.157.0/go.mod h1:Jkjs6rkqs973LqgZ0Fe3zrokQRKULYXPIf4HuqStiEE=
|
||||
go.opentelemetry.io/collector/pdata v1.63.0 h1:fY2xSG2MnyoBwA4GUhzoogGZMuNS0qHpCoODqaKwiVQ=
|
||||
go.opentelemetry.io/collector/pdata v1.63.0/go.mod h1:jzozYYhQEkTQ/CCbCBNC+hYUeju9S2J8HIqIDHdxZWk=
|
||||
go.opentelemetry.io/collector/pdata/pprofile v0.157.0 h1:YRTPhwWzdG0pfJmb8p/qpQm1EdX+JfV20qzwG3ypDqI=
|
||||
go.opentelemetry.io/collector/pdata/pprofile v0.157.0/go.mod h1:kwy/ufNUBkw8PsFPQnAqCvD12OpGU8h9A1cz5S7xS6g=
|
||||
go.opentelemetry.io/collector/pdata/testdata v0.157.0 h1:TEee4jvYe8b0nPPKQnOnLz3LaA/XRtv3ja8J56DWIZc=
|
||||
go.opentelemetry.io/collector/pdata/testdata v0.157.0/go.mod h1:ht50rAkY2bonM0eL+IvGDcAKWPNKdFE+8LjdaFjcOAA=
|
||||
go.opentelemetry.io/collector/pipeline v1.63.0 h1:D97Nb1Jsgp8Ks+74jXs24kBZVd4pPdhuKe9dVogjcEo=
|
||||
go.opentelemetry.io/collector/pipeline v1.63.0/go.mod h1:RD90NG3Jbk965Xaqym3JyHkuol4uZJjQVUkD9ddXJIs=
|
||||
go.opentelemetry.io/collector/processor v1.63.0 h1:Aj1MLNiG9TJKOMywmojjbVFe1qtTLLMjRqmViEpPHeM=
|
||||
go.opentelemetry.io/collector/processor v1.63.0/go.mod h1:dUyL11sxKBZn1XSqsiDyg76k+jZtYlRL7CkOuFWwVLI=
|
||||
go.opentelemetry.io/collector/processor/processortest v0.157.0 h1:dtpyoIvbB3VLqZ+cV96EAsyCCUVX3mBFg9KMPRRyhlo=
|
||||
go.opentelemetry.io/collector/processor/processortest v0.157.0/go.mod h1:gkRzdmNYfKJAmGCk/x8qDsIavVbNI0wTs+uhN7rY7B0=
|
||||
go.opentelemetry.io/collector/processor/xprocessor v0.157.0 h1:+WyLGrHwcPk3TK+qt7T8CH+oADEMY4r+U5fIMTBvrAc=
|
||||
go.opentelemetry.io/collector/processor/xprocessor v0.157.0/go.mod h1:DPmoWlks+CihSRjTGKvPKK6a8bl9mHk8hxthrJ+lvBI=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.44.0 h1:NmLfL734pJhM0JKaYd2Y28+nY9dPRWYAAbxhRCrKXPw=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.44.0/go.mod h1:tNAsgd8avTGke1+MndXlU5Cru4PQ9Ai/cCNWQv/ZJ/s=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.69.0 h1:2yEATaop1/a1I4psnSLgWVPLWwCzkqWakgJy7xTDVy0=
|
||||
@@ -488,8 +484,8 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 h1:8tvICD4
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0/go.mod h1:z9+yiacE0IHRqM4qFfkbt/JYlmYXgss8GY/jXoNuPJI=
|
||||
go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU=
|
||||
go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0 h1:TC+BewnDpeiAmcscXbGMfxkO+mwYUwE/VySwvw88PfA=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0/go.mod h1:J/ZyF4vfPwsSr9xJSPyQ4LqtcTPULFR64KwTikGLe+A=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.44.0 h1:hqxVTu/GtBF+vJ8d1fzW7fRxZFvgoDjWcxwwCaFDYpU=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.44.0/go.mod h1:z5fVEF4X5v0ESvlJqBrrFlBVoj5EQuefZpzsu7R+x5Q=
|
||||
go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc=
|
||||
go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo=
|
||||
go.opentelemetry.io/otel/metric/x v0.66.0 h1:YkCrx1zLOChi9ZcZ6euupOcsgzbVlec7D/xoEU1+cTA=
|
||||
@@ -521,26 +517,18 @@ go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto=
|
||||
golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio=
|
||||
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
|
||||
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
|
||||
golang.org/x/exp v0.0.0-20260611194520-c48552f49976 h1:X8Hz2ImujgbmetVuW+w2YkyZChE3cBpZi2P158rTG9M=
|
||||
golang.org/x/exp v0.0.0-20260611194520-c48552f49976/go.mod h1:vnf4pv9iKZXY58sQE1L86zmNWJ4159e1RkcWiLCkeEY=
|
||||
golang.org/x/exp v0.0.0-20260718201538-764159d718ef h1:LkZ48HFgy/TvhTI0bcWkjgFkgLyKUwcTbDjS0DUjw+A=
|
||||
golang.org/x/exp v0.0.0-20260718201538-764159d718ef/go.mod h1:EdfpwwqSu+0Li0mzskwHU6FWDV3t9Q+RZDo3QMUtL3Q=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
|
||||
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
|
||||
golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk=
|
||||
golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
|
||||
golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
|
||||
golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
|
||||
golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU=
|
||||
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
|
||||
@@ -548,28 +536,18 @@ golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
|
||||
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
|
||||
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
|
||||
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
|
||||
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/telemetry v0.0.0-20260717140457-bdb89881bb75 h1:I9ygRooEYoVHV0SRNOSr/KVjTf5EeJ52BuNkVjsP2GU=
|
||||
golang.org/x/telemetry v0.0.0-20260717140457-bdb89881bb75/go.mod h1:LV7u5Oco+Z/g6XI7PqN+EUUUGGkEcmB1uj2ceI0fOVg=
|
||||
golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc=
|
||||
golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y=
|
||||
golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
|
||||
golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE=
|
||||
golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4=
|
||||
golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
|
||||
golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY=
|
||||
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
|
||||
@@ -578,35 +556,24 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.46.0 h1:7jTurBkPZu4moS/Uy4OQT1M+QBlsj3wejyZwsT8Z7rk=
|
||||
golang.org/x/tools v0.46.0/go.mod h1:FrD85F8l+NWL+9XWBSyVSHO6Ne4jutsfIFba7AWQ5Ys=
|
||||
golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q=
|
||||
golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE=
|
||||
golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk=
|
||||
golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM=
|
||||
golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
|
||||
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=
|
||||
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8=
|
||||
golang.org/x/tools/godoc v0.1.0-deprecated h1:o+aZ1BOj6Hsx/GBdJO/s815sqftjSnrZZwyYTHODvtk=
|
||||
golang.org/x/tools/godoc v0.1.0-deprecated/go.mod h1:qM63CriJ961IHWmnWa9CjZnBndniPt4a3CK0PVB9bIg=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY=
|
||||
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
|
||||
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||
google.golang.org/api v0.284.0 h1:i+cKTgeQRcRySkP7QTl5PDO7/pAm8EcMFIUMlNbk4Vc=
|
||||
google.golang.org/api v0.284.0/go.mod h1:AU44fU+XVZOCcd8uLaBIa/ZgzgPf/0qqY3+m7lQaado=
|
||||
google.golang.org/genproto v0.0.0-20260615183401-62b3387ff324 h1:r7/+bt4yKglJiN8eUY8enbRjglCvFm1eh8ezYdYoKTM=
|
||||
google.golang.org/genproto v0.0.0-20260615183401-62b3387ff324/go.mod h1:V5M1lxGXNUICs0aOqAMsK6HtmLnCyuzY031uOQS9rJE=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260615183401-62b3387ff324 h1:g0RAkxK/smSu/iRwC/KIX1mwUoVJtk2OjbgaeS4DmUM=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260615183401-62b3387ff324/go.mod h1:Z4WJ5pJOYWFWcHEQUelD5QaZDknIQkpIL/+fyJOT9+A=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260615183401-62b3387ff324 h1:9HZDLIdYBJXAnaFOr9WHrKVycfpY+75s9HGadC0305A=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260615183401-62b3387ff324/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ=
|
||||
google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I=
|
||||
google.golang.org/api v0.290.0 h1:eMw0Xo+IfbbMlKmW7aHvpyQRv9RCXuWx/vs8AD+0x9A=
|
||||
google.golang.org/api v0.290.0/go.mod h1:weJZ3lldHFYI0DBFNKpJelUDNnusTt5YaOEgxvt8ci8=
|
||||
google.golang.org/genproto v0.0.0-20260720211330-0afa2a65878a h1:MVNwR9RFj7qfpMtNK71pq97FgrLG0lVHZh+VbM2LZeI=
|
||||
google.golang.org/genproto v0.0.0-20260720211330-0afa2a65878a/go.mod h1:0qnvndM9dUhat9AtF1jqYN6WZ+tMxEAFImo3WNvUX7w=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260720211330-0afa2a65878a h1:97PfJ4tCxY5C7NzzgGqQEMZmXbISdvSArNNEOoUGKBg=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260720211330-0afa2a65878a/go.mod h1:1brfde68Npq6+WA75c1EHWPijZEG1kMus61ygPZfn4A=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260720211330-0afa2a65878a h1:qI/YMH1ep2qQtqcp00gMQyoU7mjvbhg88GJKCvfoLj0=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260720211330-0afa2a65878a/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/grpc v1.82.1 h1:NnAxzGRA0677vCa4BUkOAnO5+FfQqVl9iUXeD0IqcGE=
|
||||
google.golang.org/grpc v1.82.1/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA=
|
||||
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI=
|
||||
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
@@ -623,23 +590,23 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/api v0.36.2 h1:TF6YDLIzKfccK7cq9YpTcGX8TJmEkHVRv78DM51fRYY=
|
||||
k8s.io/api v0.36.2/go.mod h1:F4LbMO4brjZYh7yFkXWhynSvtB7YauxV4c+HHkNRGNg=
|
||||
k8s.io/apimachinery v0.36.2 h1:0PE/W/WNy1UX61NLbXY5TMbJ6UwLL6E6lAPkYrKFxbQ=
|
||||
k8s.io/apimachinery v0.36.2/go.mod h1:fvf/HOLXq9RId0rnDIbN1OEBvHXdQbLMM8nu0LcBUf4=
|
||||
k8s.io/client-go v0.36.2 h1:bfgxmFKc9CgqsgX4xKLAAdmTQlWee7Ob/HlDOrJ5TBI=
|
||||
k8s.io/client-go v0.36.2/go.mod h1:1vgO4OAlfPnoLcb+Rze2GF5rAr14w8qjrYMoyXJzQj0=
|
||||
k8s.io/api v0.36.3 h1:NxB+05W2UGqXWFXcLO0RB5cnqnUPP5v5sVlaOH0Iz4w=
|
||||
k8s.io/api v0.36.3/go.mod h1:JzLQKqRHC5+I8RVj/lS3lCg0mg6nWI9Fo/Sk3ElxHzg=
|
||||
k8s.io/apimachinery v0.36.3 h1:PkzMRBRG8joFD8EhCuQAtNPvJlxb82FwplP26HIzvAM=
|
||||
k8s.io/apimachinery v0.36.3/go.mod h1:cTSjBWgPe/6CQyBKzY/hDIRWCQQQeK0mfLbml0UYFHE=
|
||||
k8s.io/client-go v0.36.3 h1:M4JdVzXxYcZk4fGpfDdYnxSwhLKWCFoQsHW6t+z8Hfg=
|
||||
k8s.io/client-go v0.36.3/go.mod h1:gcPwr0c87vjjG6HB6pWEqOeuYVoXSsREjzux2j6GF30=
|
||||
k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc=
|
||||
k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0=
|
||||
k8s.io/kube-openapi v0.0.0-20260603220949-865597e52e25 h1:mPMaPMpBij2V1Wv/fR+HW124vVGXXvOSS9ver/9yjWs=
|
||||
k8s.io/kube-openapi v0.0.0-20260603220949-865597e52e25/go.mod h1:V/QaCUYDa+0QpcHhVVc5l99Uz56wEMEXBSj9oCDkNDY=
|
||||
k8s.io/utils v0.0.0-20260507154919-ff6756f316d2 h1:wU4tMEhLGgIbLvXQb1cfN+EcM0wf7zC6CPF+C79jroc=
|
||||
k8s.io/utils v0.0.0-20260507154919-ff6756f316d2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
|
||||
k8s.io/kube-openapi v0.0.0-20260721132016-d427ff9ee9ad h1:oXImqH8mQNk7PmvzKhmN3ddJoY6OnyM225MXwGHPm0A=
|
||||
k8s.io/kube-openapi v0.0.0-20260721132016-d427ff9ee9ad/go.mod h1:0/mqHCVhlumdJ3BhCfnjSZQE037nAhNodh1/hK0T8/I=
|
||||
k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3 h1:jVkFFVfXdXP74B/zbO3hM3hpSFD0xvhQ5U686DPurkE=
|
||||
k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3/go.mod h1:M2s5JB1lIYP3jzZdorPLHXIPJzt9vv2muW5a6L9DtNM=
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
||||
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.4.0 h1:qmp2e3ZfFi1/jJbDGpD4mt3wyp6PE1NfKHCYLqgNQJo=
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.4.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.4.2 h1:qdOxHwrl2Kaag1aQEarlYcOA9vSyGCp3CIki3aW8c4Q=
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.4.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
|
||||
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
|
||||
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
|
||||
|
||||
20
vendor/cloud.google.com/go/auth/CHANGES.md
generated
vendored
20
vendor/cloud.google.com/go/auth/CHANGES.md
generated
vendored
@@ -1,5 +1,25 @@
|
||||
# Changes
|
||||
|
||||
## [0.22.0](https://github.com/googleapis/google-cloud-go/compare/auth/v0.21.0...auth/v0.22.0) (2026-07-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **auth:** Populate http.response.status_code in http transport ([#20053](https://github.com/googleapis/google-cloud-go/issues/20053)) ([bff5d7c](https://github.com/googleapis/google-cloud-go/commit/bff5d7c9bc7f8ea8c0059f7d8e2d4294ba92c5bc))
|
||||
|
||||
## [0.21.0](https://github.com/googleapis/google-cloud-go/compare/auth/v0.20.0...auth/v0.21.0) (2026-07-07)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **auth:** Implement updated design for regional access boundary ([#13417](https://github.com/googleapis/google-cloud-go/issues/13417)) ([fadb6c7](https://github.com/googleapis/google-cloud-go/commit/fadb6c764dbe869fca736d9f0446b5010f21d2f2))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **auth:** Avoid double impersonation in idtoken and clarify docs ([#14474](https://github.com/googleapis/google-cloud-go/issues/14474)) ([995bfc3](https://github.com/googleapis/google-cloud-go/commit/995bfc36199ba6ae1c88803c71f39a0b19fc8c0f)), closes [#11105](https://github.com/googleapis/google-cloud-go/issues/11105)
|
||||
* **auth:** Correct go min version ([#20094](https://github.com/googleapis/google-cloud-go/issues/20094)) ([6bb4358](https://github.com/googleapis/google-cloud-go/commit/6bb4358dca69b803e52eb2af882fa5afc24d54e2))
|
||||
|
||||
## [0.20.0](https://github.com/googleapis/google-cloud-go/releases/tag/auth%2Fv0.20.0) (2026-04-06)
|
||||
|
||||
## [0.19.0](https://github.com/googleapis/google-cloud-go/releases/tag/auth%2Fv0.19.0) (2026-03-23)
|
||||
|
||||
16
vendor/cloud.google.com/go/auth/credentials/detect.go
generated
vendored
16
vendor/cloud.google.com/go/auth/credentials/detect.go
generated
vendored
@@ -27,7 +27,7 @@ import (
|
||||
"cloud.google.com/go/auth"
|
||||
"cloud.google.com/go/auth/internal"
|
||||
"cloud.google.com/go/auth/internal/credsfile"
|
||||
"cloud.google.com/go/auth/internal/trustboundary"
|
||||
"cloud.google.com/go/auth/internal/regionalaccessboundary"
|
||||
"cloud.google.com/go/compute/metadata"
|
||||
"github.com/googleapis/gax-go/v2/internallog"
|
||||
)
|
||||
@@ -138,11 +138,15 @@ func OnGCE() bool {
|
||||
// Google APIs can compromise the security of your systems and data. For
|
||||
// more information, refer to [Validate credential configurations from
|
||||
// external sources](https://cloud.google.com/docs/authentication/external/externally-sourced-credentials).
|
||||
//
|
||||
// Note: If the detected credential configuration file contains a
|
||||
// `service_account_impersonation_url` field, the returned credentials will
|
||||
// yield tokens that are already impersonated to that target service account.
|
||||
func DetectDefault(opts *DetectOptions) (*auth.Credentials, error) {
|
||||
if err := opts.validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
trustBoundaryEnabled, err := trustboundary.IsEnabled()
|
||||
regionalAccessBoundaryEnabled, err := regionalaccessboundary.IsEnabled()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -175,12 +179,12 @@ func DetectDefault(opts *DetectOptions) (*auth.Credentials, error) {
|
||||
}
|
||||
|
||||
tp := computeTokenProvider(opts, metadataClient)
|
||||
if trustBoundaryEnabled {
|
||||
gceConfigProvider := trustboundary.NewGCEConfigProvider(gceUniverseDomainProvider)
|
||||
if regionalAccessBoundaryEnabled {
|
||||
gceConfigProvider := regionalaccessboundary.NewGCEConfigProvider(gceUniverseDomainProvider)
|
||||
var err error
|
||||
tp, err = trustboundary.NewProvider(opts.client(), gceConfigProvider, opts.logger(), tp)
|
||||
tp, err = regionalaccessboundary.NewProvider(opts.client(), gceConfigProvider, opts.logger(), tp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("credentials: failed to initialize GCE trust boundary provider: %w", err)
|
||||
return nil, fmt.Errorf("credentials: failed to initialize GCE Regional Access Boundary provider: %w", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
46
vendor/cloud.google.com/go/auth/credentials/filetypes.go
generated
vendored
46
vendor/cloud.google.com/go/auth/credentials/filetypes.go
generated
vendored
@@ -25,7 +25,7 @@ import (
|
||||
"cloud.google.com/go/auth/credentials/internal/impersonate"
|
||||
internalauth "cloud.google.com/go/auth/internal"
|
||||
"cloud.google.com/go/auth/internal/credsfile"
|
||||
"cloud.google.com/go/auth/internal/trustboundary"
|
||||
"cloud.google.com/go/auth/internal/regionalaccessboundary"
|
||||
)
|
||||
|
||||
const cloudPlatformScope = "https://www.googleapis.com/auth/cloud-platform"
|
||||
@@ -159,15 +159,15 @@ func handleServiceAccount(f *credsfile.ServiceAccountFile, opts *DetectOptions)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
trustBoundaryEnabled, err := trustboundary.IsEnabled()
|
||||
regionalAccessBoundaryEnabled, err := regionalaccessboundary.IsEnabled()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !trustBoundaryEnabled {
|
||||
if !regionalAccessBoundaryEnabled {
|
||||
return tp, nil
|
||||
}
|
||||
saConfig := trustboundary.NewServiceAccountConfigProvider(opts2LO.Email, opts2LO.UniverseDomain)
|
||||
return trustboundary.NewProvider(opts.client(), saConfig, opts.logger(), tp)
|
||||
saConfig := regionalaccessboundary.NewServiceAccountConfigProvider(opts2LO.Email, opts2LO.UniverseDomain)
|
||||
return regionalaccessboundary.NewProvider(opts.client(), saConfig, opts.logger(), tp)
|
||||
}
|
||||
|
||||
func handleUserCredential(f *credsfile.UserCredentialsFile, opts *DetectOptions) (auth.TokenProvider, error) {
|
||||
@@ -210,35 +210,35 @@ func handleExternalAccount(f *credsfile.ExternalAccountFile, opts *DetectOptions
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
trustBoundaryEnabled, err := trustboundary.IsEnabled()
|
||||
regionalAccessBoundaryEnabled, err := regionalaccessboundary.IsEnabled()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !trustBoundaryEnabled {
|
||||
if !regionalAccessBoundaryEnabled {
|
||||
return tp, nil
|
||||
}
|
||||
|
||||
ud := resolveUniverseDomain(opts.UniverseDomain, f.UniverseDomain)
|
||||
var configProvider trustboundary.ConfigProvider
|
||||
var configProvider regionalaccessboundary.ConfigProvider
|
||||
|
||||
if f.ServiceAccountImpersonationURL == "" {
|
||||
// No impersonation, this is a direct external account credential.
|
||||
// The trust boundary is based on the workload/workforce pool.
|
||||
// The Regional Access Boundary is based on the workload/workforce pool.
|
||||
var err error
|
||||
configProvider, err = trustboundary.NewExternalAccountConfigProvider(f.Audience, ud)
|
||||
configProvider, err = regionalaccessboundary.NewExternalAccountConfigProvider(f.Audience, ud)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// Impersonation is used. The trust boundary is based on the target service account.
|
||||
// Impersonation is used. The Regional Access Boundary is based on the target service account.
|
||||
targetSAEmail, err := impersonate.ExtractServiceAccountEmail(f.ServiceAccountImpersonationURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("credentials: could not extract target service account email for trust boundary: %w", err)
|
||||
return nil, fmt.Errorf("credentials: could not extract target service account email for Regional Access Boundary: %w", err)
|
||||
}
|
||||
configProvider = trustboundary.NewServiceAccountConfigProvider(targetSAEmail, ud)
|
||||
configProvider = regionalaccessboundary.NewServiceAccountConfigProvider(targetSAEmail, ud)
|
||||
}
|
||||
|
||||
return trustboundary.NewProvider(opts.client(), configProvider, opts.logger(), tp)
|
||||
return regionalaccessboundary.NewProvider(opts.client(), configProvider, opts.logger(), tp)
|
||||
}
|
||||
|
||||
func handleExternalAccountAuthorizedUser(f *credsfile.ExternalAccountAuthorizedUserFile, opts *DetectOptions) (auth.TokenProvider, error) {
|
||||
@@ -257,20 +257,20 @@ func handleExternalAccountAuthorizedUser(f *credsfile.ExternalAccountAuthorizedU
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
trustBoundaryEnabled, err := trustboundary.IsEnabled()
|
||||
regionalAccessBoundaryEnabled, err := regionalaccessboundary.IsEnabled()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !trustBoundaryEnabled {
|
||||
if !regionalAccessBoundaryEnabled {
|
||||
return tp, nil
|
||||
}
|
||||
|
||||
ud := resolveUniverseDomain(opts.UniverseDomain, f.UniverseDomain)
|
||||
configProvider, err := trustboundary.NewExternalAccountConfigProvider(f.Audience, ud)
|
||||
configProvider, err := regionalaccessboundary.NewExternalAccountConfigProvider(f.Audience, ud)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return trustboundary.NewProvider(opts.client(), configProvider, opts.logger(), tp)
|
||||
return regionalaccessboundary.NewProvider(opts.client(), configProvider, opts.logger(), tp)
|
||||
}
|
||||
|
||||
func handleImpersonatedServiceAccount(f *credsfile.ImpersonatedServiceAccountFile, opts *DetectOptions) (auth.TokenProvider, error) {
|
||||
@@ -306,19 +306,19 @@ func handleImpersonatedServiceAccount(f *credsfile.ImpersonatedServiceAccountFil
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
trustBoundaryEnabled, err := trustboundary.IsEnabled()
|
||||
regionalAccessBoundaryEnabled, err := regionalaccessboundary.IsEnabled()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !trustBoundaryEnabled {
|
||||
if !regionalAccessBoundaryEnabled {
|
||||
return tp, nil
|
||||
}
|
||||
targetSAEmail, err := impersonate.ExtractServiceAccountEmail(f.ServiceAccountImpersonationURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("credentials: could not extract target service account email for trust boundary: %w", err)
|
||||
return nil, fmt.Errorf("credentials: could not extract target service account email for Regional Access Boundary: %w", err)
|
||||
}
|
||||
targetSAConfig := trustboundary.NewServiceAccountConfigProvider(targetSAEmail, ud)
|
||||
return trustboundary.NewProvider(opts.client(), targetSAConfig, opts.logger(), tp)
|
||||
targetSAConfig := regionalaccessboundary.NewServiceAccountConfigProvider(targetSAEmail, ud)
|
||||
return regionalaccessboundary.NewProvider(opts.client(), targetSAConfig, opts.logger(), tp)
|
||||
}
|
||||
func handleGDCHServiceAccount(f *credsfile.GDCHServiceAccountFile, opts *DetectOptions) (auth.TokenProvider, error) {
|
||||
return gdch.NewTokenProvider(f, &gdch.Options{
|
||||
|
||||
4
vendor/cloud.google.com/go/auth/grpctransport/directpath.go
generated
vendored
4
vendor/cloud.google.com/go/auth/grpctransport/directpath.go
generated
vendored
@@ -120,7 +120,7 @@ func configureDirectPath(grpcOpts []grpc.DialOption, opts *Options, endpoint str
|
||||
})
|
||||
if isDirectPathEnabled(endpoint, opts) && compute.OnComputeEngine() && isTokenProviderDirectPathCompatible(creds, opts) {
|
||||
// Overwrite all of the previously specific DialOptions, DirectPath uses its own set of credentials and certificates.
|
||||
defaultCredetialsOptions := grpcgoogle.DefaultCredentialsOptions{PerRPCCreds: &grpcCredentialsProvider{creds: creds}}
|
||||
defaultCredetialsOptions := grpcgoogle.DefaultCredentialsOptions{PerRPCCreds: &grpcCredentialsProvider{creds: creds, endpoint: endpoint}}
|
||||
if isDirectPathBoundTokenEnabled(opts.InternalOptions) && isTokenProviderComputeEngine(creds) {
|
||||
optsClone := opts.resolveDetectOptions()
|
||||
optsClone.TokenBindingType = credentials.ALTSHardBinding
|
||||
@@ -128,7 +128,7 @@ func configureDirectPath(grpcOpts []grpc.DialOption, opts *Options, endpoint str
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
defaultCredetialsOptions.ALTSPerRPCCreds = &grpcCredentialsProvider{creds: altsCreds}
|
||||
defaultCredetialsOptions.ALTSPerRPCCreds = &grpcCredentialsProvider{creds: altsCreds, endpoint: endpoint}
|
||||
}
|
||||
grpcOpts = []grpc.DialOption{
|
||||
grpc.WithCredentialsBundle(grpcgoogle.NewDefaultCredentialsWithOptions(defaultCredetialsOptions))}
|
||||
|
||||
4
vendor/cloud.google.com/go/auth/grpctransport/grpctransport.go
generated
vendored
4
vendor/cloud.google.com/go/auth/grpctransport/grpctransport.go
generated
vendored
@@ -358,6 +358,7 @@ func dial(ctx context.Context, secure bool, opts *Options) (*grpc.ClientConn, er
|
||||
creds: creds,
|
||||
metadata: metadata,
|
||||
clientUniverseDomain: opts.UniverseDomain,
|
||||
endpoint: transportCreds.Endpoint,
|
||||
}),
|
||||
)
|
||||
// Attempt Direct Path
|
||||
@@ -405,6 +406,7 @@ type grpcCredentialsProvider struct {
|
||||
// Additional metadata attached as headers.
|
||||
metadata map[string]string
|
||||
clientUniverseDomain string
|
||||
endpoint string
|
||||
}
|
||||
|
||||
// getClientUniverseDomain returns the default service domain for a given Cloud
|
||||
@@ -447,7 +449,7 @@ func (c *grpcCredentialsProvider) GetRequestMetadata(ctx context.Context, uri ..
|
||||
}
|
||||
}
|
||||
metadata := make(map[string]string, len(c.metadata)+1)
|
||||
headers.SetAuthMetadata(token, metadata)
|
||||
headers.SetAuthMetadata(ctx, token, c.endpoint, metadata)
|
||||
for k, v := range c.metadata {
|
||||
metadata[k] = v
|
||||
}
|
||||
|
||||
5
vendor/cloud.google.com/go/auth/httptransport/transport.go
generated
vendored
5
vendor/cloud.google.com/go/auth/httptransport/transport.go
generated
vendored
@@ -284,6 +284,11 @@ func (t *otelAttributeTransport) RoundTrip(req *http.Request) (*http.Response, e
|
||||
}
|
||||
|
||||
resp, err := t.base.RoundTrip(req)
|
||||
if gax.IsFeatureEnabled("METRICS") {
|
||||
if data != nil && resp != nil {
|
||||
data.SetHTTPStatusCode(resp.StatusCode)
|
||||
}
|
||||
}
|
||||
|
||||
var logger *slog.Logger
|
||||
if gax.IsFeatureEnabled("LOGGING") {
|
||||
|
||||
47
vendor/cloud.google.com/go/auth/internal/internal.go
generated
vendored
47
vendor/cloud.google.com/go/auth/internal/internal.go
generated
vendored
@@ -48,11 +48,8 @@ const (
|
||||
// Universe domain is the default service domain for a given Cloud universe.
|
||||
DefaultUniverseDomain = "googleapis.com"
|
||||
|
||||
// TrustBoundaryNoOp is a constant indicating no trust boundary is enforced.
|
||||
TrustBoundaryNoOp = "0x0"
|
||||
|
||||
// TrustBoundaryDataKey is the key used to store trust boundary data in a token's metadata.
|
||||
TrustBoundaryDataKey = "google.auth.trust_boundary_data"
|
||||
// RegionalAccessBoundaryDataKey is the key used to store regional access boundary data in a token's metadata.
|
||||
RegionalAccessBoundaryDataKey = "google.auth.regional_access_boundary_data"
|
||||
)
|
||||
|
||||
type clonableTransport interface {
|
||||
@@ -231,55 +228,35 @@ func FormatIAMServiceAccountResource(name string) string {
|
||||
return fmt.Sprintf("projects/-/serviceAccounts/%s", name)
|
||||
}
|
||||
|
||||
// TrustBoundaryData represents the trust boundary data associated with a token.
|
||||
// RegionalAccessBoundaryData represents the regional access boundary data associated with a token.
|
||||
// It contains information about the regions or environments where the token is valid.
|
||||
type TrustBoundaryData struct {
|
||||
type RegionalAccessBoundaryData struct {
|
||||
// Locations is the list of locations that the token is allowed to be used in.
|
||||
Locations []string
|
||||
// EncodedLocations represents the locations in an encoded format.
|
||||
EncodedLocations string
|
||||
}
|
||||
|
||||
// NewTrustBoundaryData returns a new TrustBoundaryData with the specified locations and encoded locations.
|
||||
func NewTrustBoundaryData(locations []string, encodedLocations string) *TrustBoundaryData {
|
||||
// NewRegionalAccessBoundaryData returns a new RegionalAccessBoundaryData with the specified locations and encoded locations.
|
||||
func NewRegionalAccessBoundaryData(locations []string, encodedLocations string) *RegionalAccessBoundaryData {
|
||||
// Ensure consistency by treating a nil slice as an empty slice.
|
||||
if locations == nil {
|
||||
locations = []string{}
|
||||
}
|
||||
locationsCopy := make([]string, len(locations))
|
||||
copy(locationsCopy, locations)
|
||||
return &TrustBoundaryData{
|
||||
return &RegionalAccessBoundaryData{
|
||||
Locations: locationsCopy,
|
||||
EncodedLocations: encodedLocations,
|
||||
}
|
||||
}
|
||||
|
||||
// NewNoOpTrustBoundaryData returns a new TrustBoundaryData with no restrictions.
|
||||
func NewNoOpTrustBoundaryData() *TrustBoundaryData {
|
||||
return &TrustBoundaryData{
|
||||
Locations: []string{},
|
||||
EncodedLocations: TrustBoundaryNoOp,
|
||||
}
|
||||
}
|
||||
|
||||
// TrustBoundaryHeader returns the value for the x-allowed-locations header and a bool
|
||||
// indicating if the header should be set. The return values are structured to
|
||||
// handle three distinct states required by the backend:
|
||||
// 1. Header not set: (value="", present=false) -> data is empty.
|
||||
// 2. Header set to an empty string: (value="", present=true) -> data is a no-op.
|
||||
// 3. Header set to a value: (value="...", present=true) -> data has locations.
|
||||
func (t TrustBoundaryData) TrustBoundaryHeader() (value string, present bool) {
|
||||
// RegionalAccessBoundaryHeader returns the value for the x-allowed-locations header and a bool
|
||||
// indicating if the header should be set. If EncodedLocations is empty, the header
|
||||
// should not be present. Otherwise, it should be present with the value of EncodedLocations.
|
||||
func (t RegionalAccessBoundaryData) RegionalAccessBoundaryHeader() (value string, present bool) {
|
||||
if t.EncodedLocations == "" {
|
||||
// If the data is empty, the header should not be present.
|
||||
return "", false
|
||||
}
|
||||
|
||||
// If data is not empty, the header should always be present.
|
||||
present = true
|
||||
value = ""
|
||||
if t.EncodedLocations != TrustBoundaryNoOp {
|
||||
value = t.EncodedLocations
|
||||
}
|
||||
// For a no-op, the backend requires an empty string.
|
||||
return value, present
|
||||
return t.EncodedLocations, true
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package trustboundary
|
||||
package regionalaccessboundary
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -21,13 +21,13 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
workloadAllowedLocationsEndpoint = "https://iamcredentials.%s/v1/projects/%s/locations/global/workloadIdentityPools/%s/allowedLocations"
|
||||
workforceAllowedLocationsEndpoint = "https://iamcredentials.%s/v1/locations/global/workforcePools/%s/allowedLocations"
|
||||
workloadAllowedLocationsEndpoint = "https://iamcredentials.googleapis.com/v1/projects/%s/locations/global/workloadIdentityPools/%s/allowedLocations"
|
||||
workforceAllowedLocationsEndpoint = "https://iamcredentials.googleapis.com/v1/locations/global/workforcePools/%s/allowedLocations"
|
||||
)
|
||||
|
||||
var (
|
||||
workforceAudiencePattern = regexp.MustCompile(`//iam\.([^/]+)/locations/global/workforcePools/([^/]+)`)
|
||||
workloadAudiencePattern = regexp.MustCompile(`//iam\.([^/]+)/projects/([^/]+)/locations/global/workloadIdentityPools/([^/]+)`)
|
||||
workforceAudiencePattern = regexp.MustCompile(`^//iam\.([^/]+)/locations/([^/]+)/workforcePools/([^/]+)/providers/[^/]+$`)
|
||||
workloadAudiencePattern = regexp.MustCompile(`^//iam\.([^/]+)/projects/([^/]+)/locations/([^/]+)/workloadIdentityPools/([^/]+)/providers/[^/]+$`)
|
||||
)
|
||||
|
||||
// NewExternalAccountConfigProvider creates a new ConfigProvider for external accounts.
|
||||
@@ -36,19 +36,19 @@ func NewExternalAccountConfigProvider(audience, inputUniverseDomain string) (Con
|
||||
var isWorkload bool
|
||||
|
||||
matches := workloadAudiencePattern.FindStringSubmatch(audience)
|
||||
if len(matches) == 4 { // Expecting full match, domain, projectNumber, poolID
|
||||
if len(matches) == 5 { // Expecting full match, domain, projectNumber, location, poolID
|
||||
audienceDomain = matches[1]
|
||||
projectNumber = matches[2]
|
||||
poolID = matches[3]
|
||||
poolID = matches[4]
|
||||
isWorkload = true
|
||||
} else {
|
||||
matches = workforceAudiencePattern.FindStringSubmatch(audience)
|
||||
if len(matches) == 3 { // Expecting full match, domain, poolID
|
||||
if len(matches) == 4 { // Expecting full match, domain, location, poolID
|
||||
audienceDomain = matches[1]
|
||||
poolID = matches[2]
|
||||
poolID = matches[3]
|
||||
isWorkload = false
|
||||
} else {
|
||||
return nil, fmt.Errorf("trustboundary: unknown audience format: %q", audience)
|
||||
return nil, fmt.Errorf("regionalaccessboundary: unknown audience format: %q", audience)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ func NewExternalAccountConfigProvider(audience, inputUniverseDomain string) (Con
|
||||
if effectiveUniverseDomain == "" {
|
||||
effectiveUniverseDomain = audienceDomain
|
||||
} else if audienceDomain != "" && effectiveUniverseDomain != audienceDomain {
|
||||
return nil, fmt.Errorf("trustboundary: provided universe domain (%q) does not match domain in audience (%q)", inputUniverseDomain, audienceDomain)
|
||||
return nil, fmt.Errorf("regionalaccessboundary: provided universe domain (%q) does not match domain in audience (%q)", inputUniverseDomain, audienceDomain)
|
||||
}
|
||||
|
||||
if isWorkload {
|
||||
@@ -77,8 +77,8 @@ type workforcePoolConfigProvider struct {
|
||||
universeDomain string
|
||||
}
|
||||
|
||||
func (p *workforcePoolConfigProvider) GetTrustBoundaryEndpoint(ctx context.Context) (string, error) {
|
||||
return fmt.Sprintf(workforceAllowedLocationsEndpoint, p.universeDomain, p.poolID), nil
|
||||
func (p *workforcePoolConfigProvider) GetRegionalAccessBoundaryEndpoint(ctx context.Context) (string, error) {
|
||||
return fmt.Sprintf(workforceAllowedLocationsEndpoint, p.poolID), nil
|
||||
}
|
||||
|
||||
func (p *workforcePoolConfigProvider) GetUniverseDomain(ctx context.Context) (string, error) {
|
||||
@@ -91,8 +91,8 @@ type workloadIdentityPoolConfigProvider struct {
|
||||
universeDomain string
|
||||
}
|
||||
|
||||
func (p *workloadIdentityPoolConfigProvider) GetTrustBoundaryEndpoint(ctx context.Context) (string, error) {
|
||||
return fmt.Sprintf(workloadAllowedLocationsEndpoint, p.universeDomain, p.projectNumber, p.poolID), nil
|
||||
func (p *workloadIdentityPoolConfigProvider) GetRegionalAccessBoundaryEndpoint(ctx context.Context) (string, error) {
|
||||
return fmt.Sprintf(workloadAllowedLocationsEndpoint, p.projectNumber, p.poolID), nil
|
||||
}
|
||||
|
||||
func (p *workloadIdentityPoolConfigProvider) GetUniverseDomain(ctx context.Context) (string, error) {
|
||||
503
vendor/cloud.google.com/go/auth/internal/regionalaccessboundary/regional_access_boundary.go
generated
vendored
Normal file
503
vendor/cloud.google.com/go/auth/internal/regionalaccessboundary/regional_access_boundary.go
generated
vendored
Normal file
@@ -0,0 +1,503 @@
|
||||
// Copyright 2026 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package regionalaccessboundary
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"maps"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"cloud.google.com/go/auth"
|
||||
"cloud.google.com/go/auth/internal"
|
||||
"cloud.google.com/go/auth/internal/retry"
|
||||
"github.com/googleapis/gax-go/v2/internallog"
|
||||
)
|
||||
|
||||
// ProviderKey is the key to fetch the DataProvider from Token Metadata.
|
||||
const ProviderKey = "regionalaccessboundary.ProviderKey"
|
||||
|
||||
const (
|
||||
// serviceAccountAllowedLocationsEndpoint is the URL for fetching allowed locations for a given service account email.
|
||||
serviceAccountAllowedLocationsEndpoint = "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/%s/allowedLocations"
|
||||
|
||||
// cacheTTL is the duration cached RAB data remains valid before hard expiry.
|
||||
cacheTTL = 6 * time.Hour
|
||||
// cacheSoftExpiry is the threshold before hard expiry where a background refresh is triggered.
|
||||
cacheSoftExpiry = 1 * time.Hour
|
||||
// baseCooldownDuration is the initial delay after a failed background fetch.
|
||||
baseCooldownDuration = 15 * time.Minute
|
||||
)
|
||||
|
||||
var (
|
||||
// retryOptions configures the retry behavior for Regional Access Boundary lookups.
|
||||
retryOptions = &retry.Options{
|
||||
Initial: 1 * time.Second,
|
||||
Max: 60 * time.Second,
|
||||
Multiplier: 2.0,
|
||||
MaxAttempts: 6,
|
||||
}
|
||||
)
|
||||
|
||||
// isEnabled wraps isRegionalAccessBoundaryEnabled with sync.OnceValues to ensure it's
|
||||
// called only once.
|
||||
var isEnabled = sync.OnceValues(isRegionalAccessBoundaryEnabled)
|
||||
|
||||
// IsEnabled returns if the Regional Access Boundary feature is enabled and an error if
|
||||
// the configuration is invalid. The underlying check is performed only once.
|
||||
func IsEnabled() (bool, error) {
|
||||
return isEnabled()
|
||||
}
|
||||
|
||||
// isRegionalAccessBoundaryEnabled checks if the Regional Access Boundary feature
|
||||
// is enabled via the GOOGLE_AUTH_TRUST_BOUNDARY_ENABLED environment variable.
|
||||
//
|
||||
// If the environment variable is not set or empty, it is considered false.
|
||||
//
|
||||
// The environment variable is interpreted as a boolean with the following
|
||||
// (case-insensitive) rules:
|
||||
// - "true", "1" are considered true.
|
||||
// - All other values (including "false", "0", or invalid strings) are considered false.
|
||||
func isRegionalAccessBoundaryEnabled() (bool, error) {
|
||||
val := strings.ToLower(os.Getenv("GOOGLE_AUTH_TRUST_BOUNDARY_ENABLED"))
|
||||
return val == "true" || val == "1", nil
|
||||
}
|
||||
|
||||
// ConfigProvider provides specific configuration for Regional Access Boundary lookups.
|
||||
type ConfigProvider interface {
|
||||
// GetRegionalAccessBoundaryEndpoint returns the endpoint URL for the Regional Access Boundary lookup.
|
||||
GetRegionalAccessBoundaryEndpoint(ctx context.Context) (url string, err error)
|
||||
// GetUniverseDomain returns the universe domain associated with the credential.
|
||||
// It may return an error if the universe domain cannot be determined.
|
||||
GetUniverseDomain(ctx context.Context) (string, error)
|
||||
}
|
||||
|
||||
// AllowedLocationsResponse is the structure of the response from the Regional Access Boundary API.
|
||||
type AllowedLocationsResponse struct {
|
||||
// Locations is the list of allowed locations.
|
||||
Locations []string `json:"locations"`
|
||||
// EncodedLocations is the encoded representation of the allowed locations.
|
||||
EncodedLocations string `json:"encodedLocations"`
|
||||
}
|
||||
|
||||
// fetchRegionalAccessBoundaryData fetches the Regional Access Boundary data from the API.
|
||||
func fetchRegionalAccessBoundaryData(ctx context.Context, client *http.Client, url string, token *auth.Token, logger *slog.Logger) (*internal.RegionalAccessBoundaryData, error) {
|
||||
if logger == nil {
|
||||
logger = slog.New(slog.NewTextHandler(io.Discard, nil))
|
||||
}
|
||||
if client == nil {
|
||||
return nil, errors.New("regionalaccessboundary: HTTP client is required")
|
||||
}
|
||||
|
||||
if url == "" {
|
||||
return nil, errors.New("regionalaccessboundary: URL cannot be empty")
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("regionalaccessboundary: failed to create Regional Access Boundary request: %w", err)
|
||||
}
|
||||
|
||||
if token == nil || token.Value == "" {
|
||||
return nil, errors.New("regionalaccessboundary: access token required for lookup API authentication")
|
||||
}
|
||||
typ := token.Type
|
||||
if typ == "" {
|
||||
typ = internal.TokenTypeBearer
|
||||
}
|
||||
req.Header.Set("Authorization", typ+" "+token.Value)
|
||||
logger.DebugContext(ctx, "Regional Access Boundary request", "request", internallog.HTTPRequest(req, nil))
|
||||
|
||||
retryer := retry.NewWithOptions(retryOptions)
|
||||
startTime := time.Now()
|
||||
var response *http.Response
|
||||
for {
|
||||
response, err = client.Do(req)
|
||||
|
||||
var statusCode int
|
||||
if response != nil {
|
||||
statusCode = response.StatusCode
|
||||
}
|
||||
pause, shouldRetry := retryer.Retry(statusCode, err)
|
||||
|
||||
// Enforce a maximum 1 minute retry window for specific server errors.
|
||||
if shouldRetry && (statusCode == 500 || statusCode == 502 || statusCode == 503 || statusCode == 504) {
|
||||
if time.Since(startTime)+pause > 1*time.Minute {
|
||||
shouldRetry = false
|
||||
}
|
||||
}
|
||||
|
||||
if !shouldRetry {
|
||||
break
|
||||
}
|
||||
|
||||
if response != nil {
|
||||
// Drain and close the body to reuse the connection
|
||||
io.Copy(io.Discard, response.Body)
|
||||
response.Body.Close()
|
||||
}
|
||||
|
||||
if err := retry.Sleep(ctx, pause); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("regionalaccessboundary: failed to fetch Regional Access Boundary: %w", err)
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("regionalaccessboundary: failed to read Regional Access Boundary response: %w", err)
|
||||
}
|
||||
|
||||
logger.DebugContext(ctx, "Regional Access Boundary response", "response", internallog.HTTPResponse(response, body))
|
||||
|
||||
if response.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("regionalaccessboundary: Regional Access Boundary request failed with status: %s, body: %s", response.Status, string(body))
|
||||
}
|
||||
|
||||
apiResponse := AllowedLocationsResponse{}
|
||||
if err := json.Unmarshal(body, &apiResponse); err != nil {
|
||||
return nil, fmt.Errorf("regionalaccessboundary: failed to unmarshal Regional Access Boundary response: %w", err)
|
||||
}
|
||||
|
||||
if apiResponse.EncodedLocations == "" {
|
||||
return nil, errors.New("regionalaccessboundary: invalid API response: encodedLocations is empty")
|
||||
}
|
||||
|
||||
return internal.NewRegionalAccessBoundaryData(apiResponse.Locations, apiResponse.EncodedLocations), nil
|
||||
}
|
||||
|
||||
// DataProvider fetches and caches Regional Access Boundary Data.
|
||||
// It implements the auth.TokenProvider interface and uses a ConfigProvider
|
||||
// to get type-specific details for the lookup.
|
||||
type DataProvider struct {
|
||||
client *http.Client
|
||||
configProvider ConfigProvider
|
||||
logger *slog.Logger
|
||||
base auth.TokenProvider
|
||||
|
||||
mu sync.RWMutex
|
||||
data *internal.RegionalAccessBoundaryData
|
||||
dataExpiry time.Time
|
||||
isFetching bool
|
||||
cooldownExpiry time.Time
|
||||
cooldownDuration time.Duration // tracks the current cooldown duration for exponential backoff
|
||||
}
|
||||
|
||||
// NewProvider wraps the provided base [auth.TokenProvider] and returns a new
|
||||
// provider that fetches and caches the Regional Access Boundary data. It uses
|
||||
// the provided HTTP client and configProvider.
|
||||
func NewProvider(client *http.Client, configProvider ConfigProvider, logger *slog.Logger, base auth.TokenProvider) (*DataProvider, error) {
|
||||
if client == nil {
|
||||
return nil, errors.New("regionalaccessboundary: HTTP client cannot be nil for DataProvider")
|
||||
}
|
||||
if configProvider == nil {
|
||||
return nil, errors.New("regionalaccessboundary: ConfigProvider cannot be nil for DataProvider")
|
||||
}
|
||||
p := &DataProvider{
|
||||
client: client,
|
||||
configProvider: configProvider,
|
||||
logger: internallog.New(logger),
|
||||
base: base,
|
||||
cooldownDuration: 15 * time.Minute,
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// Token retrieves a token from the base provider and injects the DataProvider
|
||||
// instance into its metadata.
|
||||
func (p *DataProvider) Token(ctx context.Context) (*auth.Token, error) {
|
||||
token, err := p.base.Token(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Clone the token and its metadata to avoid mutating shared/cached state.
|
||||
newToken := *token
|
||||
newToken.Metadata = maps.Clone(token.Metadata)
|
||||
if newToken.Metadata == nil {
|
||||
newToken.Metadata = make(map[string]interface{})
|
||||
}
|
||||
newToken.Metadata[ProviderKey] = p
|
||||
|
||||
return &newToken, nil
|
||||
}
|
||||
|
||||
// GetHeaderValue immediately returns a valid header if it's cached, or kicks off a background fetch
|
||||
// if it is unpopulated or expired.
|
||||
func (p *DataProvider) GetHeaderValue(ctx context.Context, reqURL string, accessToken *auth.Token) string {
|
||||
if !strings.Contains(reqURL, "://") {
|
||||
reqURL = "https://" + reqURL
|
||||
}
|
||||
if u, err := url.Parse(reqURL); err == nil {
|
||||
host := u.Host
|
||||
if host == "" && strings.HasPrefix(u.Path, "/") {
|
||||
host = strings.TrimPrefix(u.Path, "/")
|
||||
}
|
||||
if h, _, err := net.SplitHostPort(host); err == nil {
|
||||
host = h
|
||||
}
|
||||
// Skip lookup for regional endpoints.
|
||||
if host == "rep.googleapis.com" || strings.HasSuffix(host, ".rep.googleapis.com") ||
|
||||
host == "rep.sandbox.googleapis.com" || strings.HasSuffix(host, ".rep.sandbox.googleapis.com") {
|
||||
return ""
|
||||
}
|
||||
// Skip lookup for IAM and STS endpoints as they do not require RAB headers.
|
||||
if host == "iam.googleapis.com" || host == "iamcredentials.googleapis.com" ||
|
||||
host == "sts.googleapis.com" {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// Skip lookup for non-default universe domains.
|
||||
uniDomain, err := p.configProvider.GetUniverseDomain(ctx)
|
||||
if err != nil {
|
||||
p.logger.WarnContext(ctx, "regionalaccessboundary: error getting universe domain", "error", err)
|
||||
return ""
|
||||
}
|
||||
if uniDomain != "" && uniDomain != internal.DefaultUniverseDomain {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Return the cached data if present and not expired.
|
||||
p.mu.RLock()
|
||||
data := p.data
|
||||
dataExpiry := p.dataExpiry
|
||||
p.mu.RUnlock()
|
||||
|
||||
now := time.Now()
|
||||
if data != nil && now.Before(dataExpiry) {
|
||||
val, _ := data.RegionalAccessBoundaryHeader()
|
||||
|
||||
// Soft Expiry: if the cached data is within the soft expiration window,
|
||||
// initiate a non-blocking background refresh to proactively fetch new data
|
||||
// while continuing to serve the current valid cache block.
|
||||
if now.After(dataExpiry.Add(-cacheSoftExpiry)) {
|
||||
p.mu.Lock()
|
||||
if !p.isFetching && now.After(p.cooldownExpiry) {
|
||||
p.isFetching = true
|
||||
go p.fetchAsync(context.Background(), accessToken)
|
||||
}
|
||||
p.mu.Unlock()
|
||||
}
|
||||
|
||||
return val
|
||||
}
|
||||
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
// Skip lookup if in cooldown or another process is already fetching.
|
||||
if p.isFetching || time.Now().Before(p.cooldownExpiry) {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Start async RAB lookup and return empty header.
|
||||
p.isFetching = true
|
||||
go p.fetchAsync(context.Background(), accessToken)
|
||||
return ""
|
||||
}
|
||||
|
||||
// fetchAsync performs the background lookup for Regional Access Boundary data.
|
||||
// It updates the provider's state based on the result (success or failure).
|
||||
func (p *DataProvider) fetchAsync(ctx context.Context, accessToken *auth.Token) {
|
||||
defer func() {
|
||||
p.mu.Lock()
|
||||
p.isFetching = false
|
||||
p.mu.Unlock()
|
||||
}()
|
||||
|
||||
url, err := p.configProvider.GetRegionalAccessBoundaryEndpoint(ctx)
|
||||
if err != nil {
|
||||
p.logger.WarnContext(ctx, "regionalaccessboundary: error getting the lookup endpoint", "error", err)
|
||||
p.handleFetchFailure(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
newData, fetchErr := fetchRegionalAccessBoundaryData(ctx, p.client, url, accessToken, p.logger)
|
||||
|
||||
if fetchErr != nil {
|
||||
p.logger.WarnContext(ctx, "regionalaccessboundary: async fetch failed", "error", fetchErr)
|
||||
p.handleFetchFailure(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
p.handleFetchSuccess(newData)
|
||||
}
|
||||
|
||||
// handleFetchSuccess updates the cache with new data and clears any existing cooldown.
|
||||
func (p *DataProvider) handleFetchSuccess(newData *internal.RegionalAccessBoundaryData) {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
p.data = newData
|
||||
p.dataExpiry = time.Now().Add(cacheTTL)
|
||||
p.cooldownExpiry = time.Time{}
|
||||
p.cooldownDuration = baseCooldownDuration
|
||||
}
|
||||
|
||||
// handleFetchFailure triggers the cooldown period using exponential backoff.
|
||||
func (p *DataProvider) handleFetchFailure(ctx context.Context) {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
// Add random bounded jitter (between half of the base and the full base) to prevent thundering herds
|
||||
jitter := p.cooldownDuration/2 + time.Duration(rand.Int63n(int64(p.cooldownDuration/2)))
|
||||
p.cooldownExpiry = time.Now().Add(jitter)
|
||||
|
||||
// Exponential backoff for the NEXT attempt, up to cacheTTL max (6 hours)
|
||||
nextCooldown := p.cooldownDuration * 2
|
||||
if nextCooldown > cacheTTL {
|
||||
nextCooldown = cacheTTL
|
||||
}
|
||||
p.cooldownDuration = nextCooldown
|
||||
}
|
||||
|
||||
// serviceAccountConfig holds configuration for SA Regional Access Boundary lookups.
|
||||
// It implements the ConfigProvider interface.
|
||||
type serviceAccountConfig struct {
|
||||
ServiceAccountEmail string
|
||||
UniverseDomain string
|
||||
}
|
||||
|
||||
// NewServiceAccountConfigProvider creates a new config for service accounts.
|
||||
func NewServiceAccountConfigProvider(saEmail, universeDomain string) ConfigProvider {
|
||||
return &serviceAccountConfig{
|
||||
ServiceAccountEmail: saEmail,
|
||||
UniverseDomain: universeDomain,
|
||||
}
|
||||
}
|
||||
|
||||
// GetRegionalAccessBoundaryEndpoint returns the formatted URL for fetching allowed locations
|
||||
// for the configured service account.
|
||||
func (sac *serviceAccountConfig) GetRegionalAccessBoundaryEndpoint(ctx context.Context) (url string, err error) {
|
||||
if sac.ServiceAccountEmail == "" {
|
||||
return "", errors.New("regionalaccessboundary: service account email cannot be empty for config")
|
||||
}
|
||||
return fmt.Sprintf(serviceAccountAllowedLocationsEndpoint, sac.ServiceAccountEmail), nil
|
||||
}
|
||||
|
||||
// GetUniverseDomain returns the configured universe domain, defaulting to
|
||||
// [internal.DefaultUniverseDomain] if not explicitly set.
|
||||
func (sac *serviceAccountConfig) GetUniverseDomain(ctx context.Context) (string, error) {
|
||||
if sac.UniverseDomain == "" {
|
||||
return internal.DefaultUniverseDomain, nil
|
||||
}
|
||||
return sac.UniverseDomain, nil
|
||||
}
|
||||
|
||||
// GCEConfigProvider implements ConfigProvider for GCE environments.
|
||||
// It lazily fetches and caches the necessary metadata (service account email, universe domain)
|
||||
type GCEConfigProvider struct {
|
||||
// universeDomainProvider provides the universe domain and underlying metadata client.
|
||||
universeDomainProvider *internal.ComputeUniverseDomainProvider
|
||||
|
||||
// Caching for service account email
|
||||
saMu sync.Mutex
|
||||
saEmail string
|
||||
|
||||
// Caching for universe domain
|
||||
udOnce sync.Once
|
||||
ud string
|
||||
udErr error
|
||||
}
|
||||
|
||||
// NewGCEConfigProvider creates a new GCEConfigProvider
|
||||
// which uses the provided gceUDP to interact with the GCE metadata server.
|
||||
func NewGCEConfigProvider(gceUDP *internal.ComputeUniverseDomainProvider) *GCEConfigProvider {
|
||||
// The validity of gceUDP and its internal MetadataClient will be checked
|
||||
// within the GetRegionalAccessBoundaryEndpoint and GetUniverseDomain methods.
|
||||
return &GCEConfigProvider{
|
||||
universeDomainProvider: gceUDP,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GCEConfigProvider) fetchSA(ctx context.Context) (string, error) {
|
||||
if g.universeDomainProvider == nil || g.universeDomainProvider.MetadataClient == nil {
|
||||
return "", errors.New("regionalaccessboundary: GCEConfigProvider not properly initialized (missing ComputeUniverseDomainProvider or MetadataClient)")
|
||||
}
|
||||
mdClient := g.universeDomainProvider.MetadataClient
|
||||
saEmail, err := mdClient.EmailWithContext(ctx, "default")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("regionalaccessboundary: GCE config: failed to get service account email: %w", err)
|
||||
}
|
||||
return saEmail, nil
|
||||
}
|
||||
|
||||
func (g *GCEConfigProvider) fetchUD(ctx context.Context) {
|
||||
if g.universeDomainProvider == nil || g.universeDomainProvider.MetadataClient == nil {
|
||||
g.udErr = errors.New("regionalaccessboundary: GCEConfigProvider not properly initialized (missing ComputeUniverseDomainProvider or MetadataClient)")
|
||||
return
|
||||
}
|
||||
ud, err := g.universeDomainProvider.GetProperty(ctx)
|
||||
if err != nil {
|
||||
g.udErr = fmt.Errorf("regionalaccessboundary: GCE config: failed to get universe domain: %w", err)
|
||||
return
|
||||
}
|
||||
if ud == "" {
|
||||
ud = internal.DefaultUniverseDomain
|
||||
}
|
||||
g.ud = ud
|
||||
}
|
||||
|
||||
// GetRegionalAccessBoundaryEndpoint constructs the Regional Access Boundary lookup URL for a GCE environment.
|
||||
// It uses cached service account email after the first call.
|
||||
func (g *GCEConfigProvider) GetRegionalAccessBoundaryEndpoint(ctx context.Context) (string, error) {
|
||||
// Check if we already have a cached service account email.
|
||||
g.saMu.Lock()
|
||||
if g.saEmail != "" {
|
||||
email := g.saEmail
|
||||
g.saMu.Unlock()
|
||||
return fmt.Sprintf(serviceAccountAllowedLocationsEndpoint, email), nil
|
||||
}
|
||||
g.saMu.Unlock()
|
||||
|
||||
// Fetch the email from the metadata server. We do not hold the lock
|
||||
// during this I/O operation to avoid blocking other goroutines.
|
||||
email, err := g.fetchSA(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Cache the successful result.
|
||||
g.saMu.Lock()
|
||||
g.saEmail = email
|
||||
g.saMu.Unlock()
|
||||
|
||||
return fmt.Sprintf(serviceAccountAllowedLocationsEndpoint, email), nil
|
||||
}
|
||||
|
||||
// GetUniverseDomain retrieves the universe domain from the GCE metadata server.
|
||||
// It uses a cached value after the first call.
|
||||
func (g *GCEConfigProvider) GetUniverseDomain(ctx context.Context) (string, error) {
|
||||
g.udOnce.Do(func() { g.fetchUD(ctx) })
|
||||
if g.udErr != nil {
|
||||
return "", g.udErr
|
||||
}
|
||||
return g.ud, nil
|
||||
}
|
||||
70
vendor/cloud.google.com/go/auth/internal/retry/retry.go
generated
vendored
70
vendor/cloud.google.com/go/auth/internal/retry/retry.go
generated
vendored
@@ -22,10 +22,6 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
maxRetryAttempts = 5
|
||||
)
|
||||
|
||||
var (
|
||||
syscallRetryable = func(error) bool { return false }
|
||||
)
|
||||
@@ -61,21 +57,69 @@ func Sleep(ctx context.Context, d time.Duration) error {
|
||||
|
||||
// New returns a new Retryer with the default backoff strategy.
|
||||
func New() *Retryer {
|
||||
return &Retryer{bo: &defaultBackoff{
|
||||
cur: 100 * time.Millisecond,
|
||||
max: 30 * time.Second,
|
||||
mul: 2,
|
||||
}}
|
||||
return NewWithOptions(&Options{
|
||||
Initial: 100 * time.Millisecond,
|
||||
Max: 30 * time.Second,
|
||||
Multiplier: 2,
|
||||
MaxAttempts: 5,
|
||||
})
|
||||
}
|
||||
|
||||
// Options defines the configuration for the Retryer.
|
||||
type Options struct {
|
||||
// Initial is the initial backoff duration.
|
||||
Initial time.Duration
|
||||
// Max is the maximum backoff duration for a single retry attempt.
|
||||
// It does not limit the total time of all retries.
|
||||
Max time.Duration
|
||||
// Multiplier is the factor by which the backoff duration is multiplied after each attempt.
|
||||
Multiplier float64
|
||||
// MaxAttempts is the maximum number of attempts before giving up.
|
||||
MaxAttempts int
|
||||
}
|
||||
|
||||
// NewWithOptions returns a new Retryer with the specified backoff strategy.
|
||||
// If any option is not set (zero value), it defaults to the values used in New().
|
||||
func NewWithOptions(opts *Options) *Retryer {
|
||||
initial := opts.Initial
|
||||
if initial <= 0 {
|
||||
initial = 100 * time.Millisecond
|
||||
}
|
||||
|
||||
max := opts.Max
|
||||
if max <= 0 {
|
||||
max = 30 * time.Second
|
||||
}
|
||||
|
||||
multiplier := opts.Multiplier
|
||||
if multiplier < 1.0 {
|
||||
multiplier = 2.0
|
||||
}
|
||||
|
||||
maxAttempts := opts.MaxAttempts
|
||||
if maxAttempts <= 0 {
|
||||
maxAttempts = 5
|
||||
}
|
||||
|
||||
return &Retryer{
|
||||
bo: &defaultBackoff{
|
||||
cur: initial,
|
||||
max: max,
|
||||
mul: multiplier,
|
||||
},
|
||||
maxAttempts: maxAttempts,
|
||||
}
|
||||
}
|
||||
|
||||
type backoff interface {
|
||||
Pause() time.Duration
|
||||
}
|
||||
|
||||
// Retryer is a retryer for HTTP requests.
|
||||
// Retryer handles retry logic for HTTP requests using a configurable backoff strategy.
|
||||
type Retryer struct {
|
||||
bo backoff
|
||||
attempts int
|
||||
bo backoff
|
||||
attempts int
|
||||
maxAttempts int
|
||||
}
|
||||
|
||||
// Retry determines if a request should be retried.
|
||||
@@ -87,7 +131,7 @@ func (r *Retryer) Retry(status int, err error) (time.Duration, bool) {
|
||||
if !retryOk {
|
||||
return 0, false
|
||||
}
|
||||
if r.attempts == maxRetryAttempts {
|
||||
if r.attempts == r.maxAttempts {
|
||||
return 0, false
|
||||
}
|
||||
r.attempts++
|
||||
|
||||
31
vendor/cloud.google.com/go/auth/internal/retry/retry_linux.go
generated
vendored
Normal file
31
vendor/cloud.google.com/go/auth/internal/retry/retry_linux.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright 2026 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package retry
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Initialize syscallRetryable to return true on transient socket-level
|
||||
// errors. These errors are specific to Linux.
|
||||
syscallRetryable = func(err error) bool {
|
||||
return errors.Is(err, syscall.ECONNRESET) || errors.Is(err, syscall.ECONNREFUSED)
|
||||
}
|
||||
}
|
||||
35
vendor/cloud.google.com/go/auth/internal/transport/headers/headers.go
generated
vendored
35
vendor/cloud.google.com/go/auth/internal/transport/headers/headers.go
generated
vendored
@@ -15,14 +15,20 @@
|
||||
package headers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"cloud.google.com/go/auth"
|
||||
"cloud.google.com/go/auth/internal"
|
||||
"cloud.google.com/go/auth/internal/regionalaccessboundary"
|
||||
)
|
||||
|
||||
// SetAuthHeader uses the provided token to set the Authorization and trust
|
||||
// boundary headers on a request. If the token.Type is empty, the type is
|
||||
type regionalAccessBoundaryProvider interface {
|
||||
GetHeaderValue(ctx context.Context, reqURL string, token *auth.Token) string
|
||||
}
|
||||
|
||||
// SetAuthHeader uses the provided token to set the Authorization and regional
|
||||
// access boundary headers on a request. If the token.Type is empty, the type is
|
||||
// assumed to be Bearer.
|
||||
func SetAuthHeader(token *auth.Token, req *http.Request) {
|
||||
typ := token.Type
|
||||
@@ -31,31 +37,26 @@ func SetAuthHeader(token *auth.Token, req *http.Request) {
|
||||
}
|
||||
req.Header.Set("Authorization", typ+" "+token.Value)
|
||||
|
||||
if headerVal, setHeader := getTrustBoundaryHeader(token); setHeader {
|
||||
req.Header.Set("x-allowed-locations", headerVal)
|
||||
if provider, ok := token.Metadata[regionalaccessboundary.ProviderKey].(regionalAccessBoundaryProvider); ok {
|
||||
if headerVal := provider.GetHeaderValue(req.Context(), req.URL.String(), token); headerVal != "" {
|
||||
req.Header.Set("x-allowed-locations", headerVal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetAuthMetadata uses the provided token to set the Authorization and trust
|
||||
// boundary metadata. If the token.Type is empty, the type is assumed to be
|
||||
// SetAuthMetadata uses the provided token to set the Authorization and regional
|
||||
// access boundary metadata. If the token.Type is empty, the type is assumed to be
|
||||
// Bearer.
|
||||
func SetAuthMetadata(token *auth.Token, m map[string]string) {
|
||||
func SetAuthMetadata(ctx context.Context, token *auth.Token, reqURL string, m map[string]string) {
|
||||
typ := token.Type
|
||||
if typ == "" {
|
||||
typ = internal.TokenTypeBearer
|
||||
}
|
||||
m["authorization"] = typ + " " + token.Value
|
||||
|
||||
if headerVal, setHeader := getTrustBoundaryHeader(token); setHeader {
|
||||
m["x-allowed-locations"] = headerVal
|
||||
}
|
||||
}
|
||||
|
||||
func getTrustBoundaryHeader(token *auth.Token) (val string, present bool) {
|
||||
if data, ok := token.Metadata[internal.TrustBoundaryDataKey]; ok {
|
||||
if tbd, ok := data.(internal.TrustBoundaryData); ok {
|
||||
return tbd.TrustBoundaryHeader()
|
||||
if provider, ok := token.Metadata[regionalaccessboundary.ProviderKey].(regionalAccessBoundaryProvider); ok {
|
||||
if headerVal := provider.GetHeaderValue(ctx, reqURL, token); headerVal != "" {
|
||||
m["x-allowed-locations"] = headerVal
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
392
vendor/cloud.google.com/go/auth/internal/trustboundary/trust_boundary.go
generated
vendored
392
vendor/cloud.google.com/go/auth/internal/trustboundary/trust_boundary.go
generated
vendored
@@ -1,392 +0,0 @@
|
||||
// Copyright 2025 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package trustboundary
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"cloud.google.com/go/auth"
|
||||
"cloud.google.com/go/auth/internal"
|
||||
"cloud.google.com/go/auth/internal/retry"
|
||||
"cloud.google.com/go/auth/internal/transport/headers"
|
||||
"github.com/googleapis/gax-go/v2/internallog"
|
||||
)
|
||||
|
||||
const (
|
||||
// serviceAccountAllowedLocationsEndpoint is the URL for fetching allowed locations for a given service account email.
|
||||
serviceAccountAllowedLocationsEndpoint = "https://iamcredentials.%s/v1/projects/-/serviceAccounts/%s/allowedLocations"
|
||||
)
|
||||
|
||||
// isEnabled wraps isTrustBoundaryEnabled with sync.OnceValues to ensure it's
|
||||
// called only once.
|
||||
var isEnabled = sync.OnceValues(isTrustBoundaryEnabled)
|
||||
|
||||
// IsEnabled returns if the trust boundary feature is enabled and an error if
|
||||
// the configuration is invalid. The underlying check is performed only once.
|
||||
func IsEnabled() (bool, error) {
|
||||
return isEnabled()
|
||||
}
|
||||
|
||||
// isTrustBoundaryEnabled checks if the trust boundary feature is enabled via
|
||||
// GOOGLE_AUTH_TRUST_BOUNDARY_ENABLED environment variable.
|
||||
//
|
||||
// If the environment variable is not set, it is considered false.
|
||||
//
|
||||
// The environment variable is interpreted as a boolean with the following
|
||||
// (case-insensitive) rules:
|
||||
// - "true", "1" are considered true.
|
||||
// - "false", "0" are considered false.
|
||||
//
|
||||
// Any other values will return an error.
|
||||
func isTrustBoundaryEnabled() (bool, error) {
|
||||
const envVar = "GOOGLE_AUTH_TRUST_BOUNDARY_ENABLED"
|
||||
val, ok := os.LookupEnv(envVar)
|
||||
if !ok {
|
||||
return false, nil
|
||||
}
|
||||
val = strings.ToLower(val)
|
||||
switch val {
|
||||
case "true", "1":
|
||||
return true, nil
|
||||
case "false", "0":
|
||||
return false, nil
|
||||
default:
|
||||
return false, fmt.Errorf(`invalid value for %s: %q. Must be one of "true", "false", "1", or "0"`, envVar, val)
|
||||
}
|
||||
}
|
||||
|
||||
// ConfigProvider provides specific configuration for trust boundary lookups.
|
||||
type ConfigProvider interface {
|
||||
// GetTrustBoundaryEndpoint returns the endpoint URL for the trust boundary lookup.
|
||||
GetTrustBoundaryEndpoint(ctx context.Context) (url string, err error)
|
||||
// GetUniverseDomain returns the universe domain associated with the credential.
|
||||
// It may return an error if the universe domain cannot be determined.
|
||||
GetUniverseDomain(ctx context.Context) (string, error)
|
||||
}
|
||||
|
||||
// AllowedLocationsResponse is the structure of the response from the Trust Boundary API.
|
||||
type AllowedLocationsResponse struct {
|
||||
// Locations is the list of allowed locations.
|
||||
Locations []string `json:"locations"`
|
||||
// EncodedLocations is the encoded representation of the allowed locations.
|
||||
EncodedLocations string `json:"encodedLocations"`
|
||||
}
|
||||
|
||||
// fetchTrustBoundaryData fetches the trust boundary data from the API.
|
||||
func fetchTrustBoundaryData(ctx context.Context, client *http.Client, url string, token *auth.Token, logger *slog.Logger) (*internal.TrustBoundaryData, error) {
|
||||
if logger == nil {
|
||||
logger = slog.New(slog.NewTextHandler(io.Discard, nil))
|
||||
}
|
||||
if client == nil {
|
||||
return nil, errors.New("trustboundary: HTTP client is required")
|
||||
}
|
||||
|
||||
if url == "" {
|
||||
return nil, errors.New("trustboundary: URL cannot be empty")
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("trustboundary: failed to create trust boundary request: %w", err)
|
||||
}
|
||||
|
||||
if token == nil || token.Value == "" {
|
||||
return nil, errors.New("trustboundary: access token required for lookup API authentication")
|
||||
}
|
||||
headers.SetAuthHeader(token, req)
|
||||
logger.DebugContext(ctx, "trust boundary request", "request", internallog.HTTPRequest(req, nil))
|
||||
|
||||
retryer := retry.New()
|
||||
var response *http.Response
|
||||
for {
|
||||
response, err = client.Do(req)
|
||||
|
||||
var statusCode int
|
||||
if response != nil {
|
||||
statusCode = response.StatusCode
|
||||
}
|
||||
pause, shouldRetry := retryer.Retry(statusCode, err)
|
||||
|
||||
if !shouldRetry {
|
||||
break
|
||||
}
|
||||
|
||||
if response != nil {
|
||||
// Drain and close the body to reuse the connection
|
||||
io.Copy(io.Discard, response.Body)
|
||||
response.Body.Close()
|
||||
}
|
||||
|
||||
if err := retry.Sleep(ctx, pause); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("trustboundary: failed to fetch trust boundary: %w", err)
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("trustboundary: failed to read trust boundary response: %w", err)
|
||||
}
|
||||
|
||||
logger.DebugContext(ctx, "trust boundary response", "response", internallog.HTTPResponse(response, body))
|
||||
|
||||
if response.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("trustboundary: trust boundary request failed with status: %s, body: %s", response.Status, string(body))
|
||||
}
|
||||
|
||||
apiResponse := AllowedLocationsResponse{}
|
||||
if err := json.Unmarshal(body, &apiResponse); err != nil {
|
||||
return nil, fmt.Errorf("trustboundary: failed to unmarshal trust boundary response: %w", err)
|
||||
}
|
||||
|
||||
if apiResponse.EncodedLocations == "" {
|
||||
return nil, errors.New("trustboundary: invalid API response: encodedLocations is empty")
|
||||
}
|
||||
|
||||
return internal.NewTrustBoundaryData(apiResponse.Locations, apiResponse.EncodedLocations), nil
|
||||
}
|
||||
|
||||
// serviceAccountConfig holds configuration for SA trust boundary lookups.
|
||||
// It implements the ConfigProvider interface.
|
||||
type serviceAccountConfig struct {
|
||||
ServiceAccountEmail string
|
||||
UniverseDomain string
|
||||
}
|
||||
|
||||
// NewServiceAccountConfigProvider creates a new config for service accounts.
|
||||
func NewServiceAccountConfigProvider(saEmail, universeDomain string) ConfigProvider {
|
||||
return &serviceAccountConfig{
|
||||
ServiceAccountEmail: saEmail,
|
||||
UniverseDomain: universeDomain,
|
||||
}
|
||||
}
|
||||
|
||||
// GetTrustBoundaryEndpoint returns the formatted URL for fetching allowed locations
|
||||
// for the configured service account and universe domain.
|
||||
func (sac *serviceAccountConfig) GetTrustBoundaryEndpoint(ctx context.Context) (url string, err error) {
|
||||
if sac.ServiceAccountEmail == "" {
|
||||
return "", errors.New("trustboundary: service account email cannot be empty for config")
|
||||
}
|
||||
ud := sac.UniverseDomain
|
||||
if ud == "" {
|
||||
ud = internal.DefaultUniverseDomain
|
||||
}
|
||||
return fmt.Sprintf(serviceAccountAllowedLocationsEndpoint, ud, sac.ServiceAccountEmail), nil
|
||||
}
|
||||
|
||||
// GetUniverseDomain returns the configured universe domain, defaulting to
|
||||
// [internal.DefaultUniverseDomain] if not explicitly set.
|
||||
func (sac *serviceAccountConfig) GetUniverseDomain(ctx context.Context) (string, error) {
|
||||
if sac.UniverseDomain == "" {
|
||||
return internal.DefaultUniverseDomain, nil
|
||||
}
|
||||
return sac.UniverseDomain, nil
|
||||
}
|
||||
|
||||
// DataProvider fetches and caches trust boundary Data.
|
||||
// It implements the DataProvider interface and uses a ConfigProvider
|
||||
// to get type-specific details for the lookup.
|
||||
type DataProvider struct {
|
||||
client *http.Client
|
||||
configProvider ConfigProvider
|
||||
data *internal.TrustBoundaryData
|
||||
logger *slog.Logger
|
||||
base auth.TokenProvider
|
||||
}
|
||||
|
||||
// NewProvider wraps the provided base [auth.TokenProvider] to create a new
|
||||
// provider that injects tokens with trust boundary data. It uses the provided
|
||||
// HTTP client and configProvider to fetch the data and attach it to the token's
|
||||
// metadata.
|
||||
func NewProvider(client *http.Client, configProvider ConfigProvider, logger *slog.Logger, base auth.TokenProvider) (*DataProvider, error) {
|
||||
if client == nil {
|
||||
return nil, errors.New("trustboundary: HTTP client cannot be nil for DataProvider")
|
||||
}
|
||||
if configProvider == nil {
|
||||
return nil, errors.New("trustboundary: ConfigProvider cannot be nil for DataProvider")
|
||||
}
|
||||
p := &DataProvider{
|
||||
client: client,
|
||||
configProvider: configProvider,
|
||||
logger: internallog.New(logger),
|
||||
base: base,
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// Token retrieves a token from the base provider and injects it with trust
|
||||
// boundary data.
|
||||
func (p *DataProvider) Token(ctx context.Context) (*auth.Token, error) {
|
||||
// Get the original token.
|
||||
token, err := p.base.Token(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tbData, err := p.GetTrustBoundaryData(ctx, token)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("trustboundary: error fetching the trust boundary data: %w", err)
|
||||
}
|
||||
if tbData != nil {
|
||||
if token.Metadata == nil {
|
||||
token.Metadata = make(map[string]interface{})
|
||||
}
|
||||
token.Metadata[internal.TrustBoundaryDataKey] = *tbData
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
|
||||
// GetTrustBoundaryData retrieves the trust boundary data.
|
||||
// It first checks the universe domain: if it's non-default, a NoOp is returned.
|
||||
// Otherwise, it checks a local cache. If the data is not cached as NoOp,
|
||||
// it fetches new data from the endpoint provided by its ConfigProvider,
|
||||
// using the given accessToken for authentication. Results are cached.
|
||||
// If fetching fails, it returns previously cached data if available, otherwise the fetch error.
|
||||
func (p *DataProvider) GetTrustBoundaryData(ctx context.Context, token *auth.Token) (*internal.TrustBoundaryData, error) {
|
||||
// Check the universe domain.
|
||||
uniDomain, err := p.configProvider.GetUniverseDomain(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("trustboundary: error getting universe domain: %w", err)
|
||||
}
|
||||
if uniDomain != "" && uniDomain != internal.DefaultUniverseDomain {
|
||||
if p.data == nil || p.data.EncodedLocations != internal.TrustBoundaryNoOp {
|
||||
p.data = internal.NewNoOpTrustBoundaryData()
|
||||
}
|
||||
return p.data, nil
|
||||
}
|
||||
|
||||
// Check cache for a no-op result from a previous API call.
|
||||
cachedData := p.data
|
||||
if cachedData != nil && cachedData.EncodedLocations == internal.TrustBoundaryNoOp {
|
||||
return cachedData, nil
|
||||
}
|
||||
|
||||
// Get the endpoint
|
||||
url, err := p.configProvider.GetTrustBoundaryEndpoint(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("trustboundary: error getting the lookup endpoint: %w", err)
|
||||
}
|
||||
|
||||
// Proceed to fetch new data.
|
||||
newData, fetchErr := fetchTrustBoundaryData(ctx, p.client, url, token, p.logger)
|
||||
|
||||
if fetchErr != nil {
|
||||
// Fetch failed. Fallback to cachedData if available.
|
||||
if cachedData != nil {
|
||||
return cachedData, nil // Successful fallback
|
||||
}
|
||||
// No cache to fallback to.
|
||||
return nil, fmt.Errorf("trustboundary: failed to fetch trust boundary data for endpoint %s and no cache available: %w", url, fetchErr)
|
||||
}
|
||||
|
||||
// Fetch successful. Update cache.
|
||||
p.data = newData
|
||||
return newData, nil
|
||||
}
|
||||
|
||||
// GCEConfigProvider implements ConfigProvider for GCE environments.
|
||||
// It lazily fetches and caches the necessary metadata (service account email, universe domain)
|
||||
// from the GCE metadata server.
|
||||
type GCEConfigProvider struct {
|
||||
// universeDomainProvider provides the universe domain and underlying metadata client.
|
||||
universeDomainProvider *internal.ComputeUniverseDomainProvider
|
||||
|
||||
// Caching for service account email
|
||||
saOnce sync.Once
|
||||
saEmail string
|
||||
saEmailErr error
|
||||
|
||||
// Caching for universe domain
|
||||
udOnce sync.Once
|
||||
ud string
|
||||
udErr error
|
||||
}
|
||||
|
||||
// NewGCEConfigProvider creates a new GCEConfigProvider
|
||||
// which uses the provided gceUDP to interact with the GCE metadata server.
|
||||
func NewGCEConfigProvider(gceUDP *internal.ComputeUniverseDomainProvider) *GCEConfigProvider {
|
||||
// The validity of gceUDP and its internal MetadataClient will be checked
|
||||
// within the GetTrustBoundaryEndpoint and GetUniverseDomain methods.
|
||||
return &GCEConfigProvider{
|
||||
universeDomainProvider: gceUDP,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GCEConfigProvider) fetchSA(ctx context.Context) {
|
||||
if g.universeDomainProvider == nil || g.universeDomainProvider.MetadataClient == nil {
|
||||
g.saEmailErr = errors.New("trustboundary: GCEConfigProvider not properly initialized (missing ComputeUniverseDomainProvider or MetadataClient)")
|
||||
return
|
||||
}
|
||||
mdClient := g.universeDomainProvider.MetadataClient
|
||||
saEmail, err := mdClient.EmailWithContext(ctx, "default")
|
||||
if err != nil {
|
||||
g.saEmailErr = fmt.Errorf("trustboundary: GCE config: failed to get service account email: %w", err)
|
||||
return
|
||||
}
|
||||
g.saEmail = saEmail
|
||||
}
|
||||
|
||||
func (g *GCEConfigProvider) fetchUD(ctx context.Context) {
|
||||
if g.universeDomainProvider == nil || g.universeDomainProvider.MetadataClient == nil {
|
||||
g.udErr = errors.New("trustboundary: GCEConfigProvider not properly initialized (missing ComputeUniverseDomainProvider or MetadataClient)")
|
||||
return
|
||||
}
|
||||
ud, err := g.universeDomainProvider.GetProperty(ctx)
|
||||
if err != nil {
|
||||
g.udErr = fmt.Errorf("trustboundary: GCE config: failed to get universe domain: %w", err)
|
||||
return
|
||||
}
|
||||
if ud == "" {
|
||||
ud = internal.DefaultUniverseDomain
|
||||
}
|
||||
g.ud = ud
|
||||
}
|
||||
|
||||
// GetTrustBoundaryEndpoint constructs the trust boundary lookup URL for a GCE environment.
|
||||
// It uses cached metadata (service account email, universe domain) after the first call.
|
||||
func (g *GCEConfigProvider) GetTrustBoundaryEndpoint(ctx context.Context) (string, error) {
|
||||
g.saOnce.Do(func() { g.fetchSA(ctx) })
|
||||
if g.saEmailErr != nil {
|
||||
return "", g.saEmailErr
|
||||
}
|
||||
g.udOnce.Do(func() { g.fetchUD(ctx) })
|
||||
if g.udErr != nil {
|
||||
return "", g.udErr
|
||||
}
|
||||
return fmt.Sprintf(serviceAccountAllowedLocationsEndpoint, g.ud, g.saEmail), nil
|
||||
}
|
||||
|
||||
// GetUniverseDomain retrieves the universe domain from the GCE metadata server.
|
||||
// It uses a cached value after the first call.
|
||||
func (g *GCEConfigProvider) GetUniverseDomain(ctx context.Context) (string, error) {
|
||||
g.udOnce.Do(func() { g.fetchUD(ctx) })
|
||||
if g.udErr != nil {
|
||||
return "", g.udErr
|
||||
}
|
||||
return g.ud, nil
|
||||
}
|
||||
2
vendor/cloud.google.com/go/auth/internal/version.go
generated
vendored
2
vendor/cloud.google.com/go/auth/internal/version.go
generated
vendored
@@ -17,4 +17,4 @@
|
||||
package internal
|
||||
|
||||
// Version is the current tagged release of the library.
|
||||
const Version = "0.20.0"
|
||||
const Version = "0.22.0"
|
||||
|
||||
7
vendor/cloud.google.com/go/iam/CHANGES.md
generated
vendored
7
vendor/cloud.google.com/go/iam/CHANGES.md
generated
vendored
@@ -1,6 +1,13 @@
|
||||
# Changes
|
||||
|
||||
|
||||
## [1.12.0](https://github.com/googleapis/google-cloud-go/compare/iam/v1.11.0...iam/v1.12.0) (2026-07-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **o11y:** Regenerate clients for LRO tracing ([#20107](https://github.com/googleapis/google-cloud-go/issues/20107)) ([779074e](https://github.com/googleapis/google-cloud-go/commit/779074edd267a26520bae459307660953129eb07))
|
||||
|
||||
## [1.11.0](https://github.com/googleapis/google-cloud-go/releases/tag/iam%2Fv1.11.0) (2026-05-07)
|
||||
|
||||
## [1.10.0](https://github.com/googleapis/google-cloud-go/releases/tag/iam%2Fv1.10.0) (2026-04-30)
|
||||
|
||||
4
vendor/cloud.google.com/go/monitoring/apiv3/v2/alert_policy_client.go
generated
vendored
4
vendor/cloud.google.com/go/monitoring/apiv3/v2/alert_policy_client.go
generated
vendored
@@ -144,7 +144,7 @@ type AlertPolicyClient struct {
|
||||
|
||||
// Wrapper methods routed to the internal client.
|
||||
|
||||
// Close closes the connection to the API service. The user should invoke this when
|
||||
// Close closes the connection to the API service. **Always** call Close() when
|
||||
// the client is no longer required.
|
||||
func (c *AlertPolicyClient) Close() error {
|
||||
return c.internalClient.Close()
|
||||
@@ -312,7 +312,7 @@ func (c *alertPolicyGRPCClient) setGoogleClientInfo(keyval ...string) {
|
||||
}
|
||||
}
|
||||
|
||||
// Close closes the connection to the API service. The user should invoke this when
|
||||
// Close closes the connection to the API service. **Always** call Close() when
|
||||
// the client is no longer required.
|
||||
func (c *alertPolicyGRPCClient) Close() error {
|
||||
return c.connPool.Close()
|
||||
|
||||
4
vendor/cloud.google.com/go/monitoring/apiv3/v2/group_client.go
generated
vendored
4
vendor/cloud.google.com/go/monitoring/apiv3/v2/group_client.go
generated
vendored
@@ -171,7 +171,7 @@ type GroupClient struct {
|
||||
|
||||
// Wrapper methods routed to the internal client.
|
||||
|
||||
// Close closes the connection to the API service. The user should invoke this when
|
||||
// Close closes the connection to the API service. **Always** call Close() when
|
||||
// the client is no longer required.
|
||||
func (c *GroupClient) Close() error {
|
||||
return c.internalClient.Close()
|
||||
@@ -334,7 +334,7 @@ func (c *groupGRPCClient) setGoogleClientInfo(keyval ...string) {
|
||||
}
|
||||
}
|
||||
|
||||
// Close closes the connection to the API service. The user should invoke this when
|
||||
// Close closes the connection to the API service. **Always** call Close() when
|
||||
// the client is no longer required.
|
||||
func (c *groupGRPCClient) Close() error {
|
||||
return c.connPool.Close()
|
||||
|
||||
4
vendor/cloud.google.com/go/monitoring/apiv3/v2/metric_client.go
generated
vendored
4
vendor/cloud.google.com/go/monitoring/apiv3/v2/metric_client.go
generated
vendored
@@ -184,7 +184,7 @@ type MetricClient struct {
|
||||
|
||||
// Wrapper methods routed to the internal client.
|
||||
|
||||
// Close closes the connection to the API service. The user should invoke this when
|
||||
// Close closes the connection to the API service. **Always** call Close() when
|
||||
// the client is no longer required.
|
||||
func (c *MetricClient) Close() error {
|
||||
return c.internalClient.Close()
|
||||
@@ -375,7 +375,7 @@ func (c *metricGRPCClient) setGoogleClientInfo(keyval ...string) {
|
||||
}
|
||||
}
|
||||
|
||||
// Close closes the connection to the API service. The user should invoke this when
|
||||
// Close closes the connection to the API service. **Always** call Close() when
|
||||
// the client is no longer required.
|
||||
func (c *metricGRPCClient) Close() error {
|
||||
return c.connPool.Close()
|
||||
|
||||
4
vendor/cloud.google.com/go/monitoring/apiv3/v2/notification_channel_client.go
generated
vendored
4
vendor/cloud.google.com/go/monitoring/apiv3/v2/notification_channel_client.go
generated
vendored
@@ -198,7 +198,7 @@ type NotificationChannelClient struct {
|
||||
|
||||
// Wrapper methods routed to the internal client.
|
||||
|
||||
// Close closes the connection to the API service. The user should invoke this when
|
||||
// Close closes the connection to the API service. **Always** call Close() when
|
||||
// the client is no longer required.
|
||||
func (c *NotificationChannelClient) Close() error {
|
||||
return c.internalClient.Close()
|
||||
@@ -422,7 +422,7 @@ func (c *notificationChannelGRPCClient) setGoogleClientInfo(keyval ...string) {
|
||||
}
|
||||
}
|
||||
|
||||
// Close closes the connection to the API service. The user should invoke this when
|
||||
// Close closes the connection to the API service. **Always** call Close() when
|
||||
// the client is no longer required.
|
||||
func (c *notificationChannelGRPCClient) Close() error {
|
||||
return c.connPool.Close()
|
||||
|
||||
4
vendor/cloud.google.com/go/monitoring/apiv3/v2/query_client.go
generated
vendored
4
vendor/cloud.google.com/go/monitoring/apiv3/v2/query_client.go
generated
vendored
@@ -87,7 +87,7 @@ type QueryClient struct {
|
||||
|
||||
// Wrapper methods routed to the internal client.
|
||||
|
||||
// Close closes the connection to the API service. The user should invoke this when
|
||||
// Close closes the connection to the API service. **Always** call Close() when
|
||||
// the client is no longer required.
|
||||
func (c *QueryClient) Close() error {
|
||||
return c.internalClient.Close()
|
||||
@@ -215,7 +215,7 @@ func (c *queryGRPCClient) setGoogleClientInfo(keyval ...string) {
|
||||
}
|
||||
}
|
||||
|
||||
// Close closes the connection to the API service. The user should invoke this when
|
||||
// Close closes the connection to the API service. **Always** call Close() when
|
||||
// the client is no longer required.
|
||||
func (c *queryGRPCClient) Close() error {
|
||||
return c.connPool.Close()
|
||||
|
||||
4
vendor/cloud.google.com/go/monitoring/apiv3/v2/service_monitoring_client.go
generated
vendored
4
vendor/cloud.google.com/go/monitoring/apiv3/v2/service_monitoring_client.go
generated
vendored
@@ -191,7 +191,7 @@ type ServiceMonitoringClient struct {
|
||||
|
||||
// Wrapper methods routed to the internal client.
|
||||
|
||||
// Close closes the connection to the API service. The user should invoke this when
|
||||
// Close closes the connection to the API service. **Always** call Close() when
|
||||
// the client is no longer required.
|
||||
func (c *ServiceMonitoringClient) Close() error {
|
||||
return c.internalClient.Close()
|
||||
@@ -369,7 +369,7 @@ func (c *serviceMonitoringGRPCClient) setGoogleClientInfo(keyval ...string) {
|
||||
}
|
||||
}
|
||||
|
||||
// Close closes the connection to the API service. The user should invoke this when
|
||||
// Close closes the connection to the API service. **Always** call Close() when
|
||||
// the client is no longer required.
|
||||
func (c *serviceMonitoringGRPCClient) Close() error {
|
||||
return c.connPool.Close()
|
||||
|
||||
4
vendor/cloud.google.com/go/monitoring/apiv3/v2/snooze_client.go
generated
vendored
4
vendor/cloud.google.com/go/monitoring/apiv3/v2/snooze_client.go
generated
vendored
@@ -124,7 +124,7 @@ type SnoozeClient struct {
|
||||
|
||||
// Wrapper methods routed to the internal client.
|
||||
|
||||
// Close closes the connection to the API service. The user should invoke this when
|
||||
// Close closes the connection to the API service. **Always** call Close() when
|
||||
// the client is no longer required.
|
||||
func (c *SnoozeClient) Close() error {
|
||||
return c.internalClient.Close()
|
||||
@@ -269,7 +269,7 @@ func (c *snoozeGRPCClient) setGoogleClientInfo(keyval ...string) {
|
||||
}
|
||||
}
|
||||
|
||||
// Close closes the connection to the API service. The user should invoke this when
|
||||
// Close closes the connection to the API service. **Always** call Close() when
|
||||
// the client is no longer required.
|
||||
func (c *snoozeGRPCClient) Close() error {
|
||||
return c.connPool.Close()
|
||||
|
||||
4
vendor/cloud.google.com/go/monitoring/apiv3/v2/uptime_check_client.go
generated
vendored
4
vendor/cloud.google.com/go/monitoring/apiv3/v2/uptime_check_client.go
generated
vendored
@@ -157,7 +157,7 @@ type UptimeCheckClient struct {
|
||||
|
||||
// Wrapper methods routed to the internal client.
|
||||
|
||||
// Close closes the connection to the API service. The user should invoke this when
|
||||
// Close closes the connection to the API service. **Always** call Close() when
|
||||
// the client is no longer required.
|
||||
func (c *UptimeCheckClient) Close() error {
|
||||
return c.internalClient.Close()
|
||||
@@ -321,7 +321,7 @@ func (c *uptimeCheckGRPCClient) setGoogleClientInfo(keyval ...string) {
|
||||
}
|
||||
}
|
||||
|
||||
// Close closes the connection to the API service. The user should invoke this when
|
||||
// Close closes the connection to the API service. **Always** call Close() when
|
||||
// the client is no longer required.
|
||||
func (c *uptimeCheckGRPCClient) Close() error {
|
||||
return c.connPool.Close()
|
||||
|
||||
2
vendor/cloud.google.com/go/monitoring/internal/version.go
generated
vendored
2
vendor/cloud.google.com/go/monitoring/internal/version.go
generated
vendored
@@ -17,4 +17,4 @@
|
||||
package internal
|
||||
|
||||
// Version is the current tagged release of the library.
|
||||
const Version = "1.29.0"
|
||||
const Version = "1.30.0"
|
||||
|
||||
47
vendor/cloud.google.com/go/storage/CHANGES.md
generated
vendored
47
vendor/cloud.google.com/go/storage/CHANGES.md
generated
vendored
@@ -1,12 +1,43 @@
|
||||
# Changes
|
||||
|
||||
|
||||
## [1.64.0](https://github.com/googleapis/google-cloud-go/compare/storage/v1.63.1...storage/v1.64.0) (2026-07-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **storage:** Accept CRC32C for appendable objects ([#20104](https://github.com/googleapis/google-cloud-go/issues/20104)) ([1b2f5af](https://github.com/googleapis/google-cloud-go/commit/1b2f5afa0fe0f159edbc7184467928ebbd8720e2))
|
||||
|
||||
## [1.63.1](https://github.com/googleapis/google-cloud-go/compare/storage/v1.63.0...storage/v1.63.1) (2026-07-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **o11y:** Regenerate clients for LRO tracing ([#20107](https://github.com/googleapis/google-cloud-go/issues/20107)) ([779074e](https://github.com/googleapis/google-cloud-go/commit/779074edd267a26520bae459307660953129eb07))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **storage:** Minor documentation fix ([#20139](https://github.com/googleapis/google-cloud-go/issues/20139)) ([37f1745](https://github.com/googleapis/google-cloud-go/commit/37f17453d73ad7abbc424f51b51ff82f8004c5b2))
|
||||
|
||||
## [1.63.0](https://github.com/googleapis/google-cloud-go/compare/storage/v1.62.2...storage/v1.63.0) (2026-06-25)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **go:** Add full object checksum for negative offsets > size ([#20026](https://github.com/googleapis/google-cloud-go/issues/20026)) ([a04d980](https://github.com/googleapis/google-cloud-go/commit/a04d9809f8897195d796f4323d36e6880c0e02e8))
|
||||
* **storage:** Add client feature tracking in HTTP client ([#14691](https://github.com/googleapis/google-cloud-go/issues/14691)) ([319cc4c](https://github.com/googleapis/google-cloud-go/commit/319cc4c868f17196249d51faaecf91e58876ddba))
|
||||
* **storage:** App Centric Observability ([#14685](https://github.com/googleapis/google-cloud-go/issues/14685)) ([c3273bb](https://github.com/googleapis/google-cloud-go/commit/c3273bbf15b0d093dbb4e0bc62d22d26f273dbe5))
|
||||
* **storage:** Read checksums in gRPC partial reads ([#14586](https://github.com/googleapis/google-cloud-go/issues/14586)) ([d29f68a](https://github.com/googleapis/google-cloud-go/commit/d29f68afa17d1b874c374c97642afaaf0958a929))
|
||||
* **storage:** Support deleteSourceObjects option in object compose ([#14704](https://github.com/googleapis/google-cloud-go/issues/14704)) ([0d2d680](https://github.com/googleapis/google-cloud-go/commit/0d2d68046cae33909028c0c116c4743f72cc00f5))
|
||||
* Update API sources and regenerate ([#14701](https://github.com/googleapis/google-cloud-go/issues/14701)) ([a9b7921](https://github.com/googleapis/google-cloud-go/commit/a9b7921551e9c1535496731da53e880e9e364efa))
|
||||
|
||||
## [1.62.3](https://github.com/googleapis/google-cloud-go/releases/tag/storage%2Fv1.62.3) (2026-06-03)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add server closed idle connection to retriable errors (#14594) ([20b37d6](https://github.com/googleapis/google-cloud-go/commit/20b37d65d56d4b5e7b8d43b1f6b2ddefcd8944be))
|
||||
* fix race condition during retries in gRPC writer (#14649) ([04b6c63](https://github.com/googleapis/google-cloud-go/commit/04b6c635c09de1772fcefd8a7fd5e4ffdd370b79))
|
||||
* **storage:** Add server closed idle connection to retriable errors ([#14594](https://github.com/googleapis/google-cloud-go/issues/14594)) ([a6bd392](https://github.com/googleapis/google-cloud-go/commit/a6bd39257d261f74680c909c24102ca6f69989b9))
|
||||
* **storage:** Fix race condition during retries in gRPC writer ([#14649](https://github.com/googleapis/google-cloud-go/issues/14649)) ([c781a75](https://github.com/googleapis/google-cloud-go/commit/c781a7535f87377bb7d0b47fc82ad0bb330faf29))
|
||||
|
||||
## [1.62.2](https://github.com/googleapis/google-cloud-go/releases/tag/storage%2Fv1.62.2) (2026-05-18)
|
||||
|
||||
@@ -42,18 +73,6 @@
|
||||
|
||||
* Update `EnableParallelUpload` documentation in `writer.go` (#14328) ([22d0749](http://github.com/googleapis/google-cloud-go/commit/22d0749f8fdbeaa34f2a836b63510bd0c3def990))
|
||||
|
||||
## [1.61.5](https://github.com/googleapis/google-cloud-go/releases/tag/storage%2Fv1.61.5) (2026-06-01)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix race condition during retries in gRPC writer (#14649) ([e87213b](https://github.com/googleapis/google-cloud-go/commit/e87213b78affff3aafb6ee0ecd542d65719e5c5c))
|
||||
|
||||
## [1.61.4](https://github.com/googleapis/google-cloud-go/releases/tag/storage%2Fv1.61.4) (2026-05-21)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add server closed idle connection to retriable errors (#14594) ([37580e7](https://github.com/googleapis/google-cloud-go/commit/37580e7eb530bbcf54951425947060c51cb0b30a))
|
||||
|
||||
## [1.61.3](https://github.com/googleapis/google-cloud-go/releases/tag/storage%2Fv1.61.3) (2026-03-13)
|
||||
|
||||
### Documentation
|
||||
|
||||
6
vendor/cloud.google.com/go/storage/acl.go
generated
vendored
6
vendor/cloud.google.com/go/storage/acl.go
generated
vendored
@@ -76,7 +76,7 @@ type ACLHandle struct {
|
||||
|
||||
// Delete permanently deletes the ACL entry for the given entity.
|
||||
func (a *ACLHandle) Delete(ctx context.Context, entity ACLEntity) (err error) {
|
||||
ctx, _ = startSpan(ctx, "ACL.Delete")
|
||||
ctx, _ = startSpanWithBucket(ctx, a.c, a.bucket, "ACL.Delete")
|
||||
defer func() { endSpan(ctx, err) }()
|
||||
|
||||
if a.object != "" {
|
||||
@@ -90,7 +90,7 @@ func (a *ACLHandle) Delete(ctx context.Context, entity ACLEntity) (err error) {
|
||||
|
||||
// Set sets the role for the given entity.
|
||||
func (a *ACLHandle) Set(ctx context.Context, entity ACLEntity, role ACLRole) (err error) {
|
||||
ctx, _ = startSpan(ctx, "ACL.Set")
|
||||
ctx, _ = startSpanWithBucket(ctx, a.c, a.bucket, "ACL.Set")
|
||||
defer func() { endSpan(ctx, err) }()
|
||||
|
||||
if a.object != "" {
|
||||
@@ -104,7 +104,7 @@ func (a *ACLHandle) Set(ctx context.Context, entity ACLEntity, role ACLRole) (er
|
||||
|
||||
// List retrieves ACL entries.
|
||||
func (a *ACLHandle) List(ctx context.Context) (rules []ACLRule, err error) {
|
||||
ctx, _ = startSpan(ctx, "ACL.List")
|
||||
ctx, _ = startSpanWithBucket(ctx, a.c, a.bucket, "ACL.List")
|
||||
defer func() { endSpan(ctx, err) }()
|
||||
|
||||
if a.object != "" {
|
||||
|
||||
16
vendor/cloud.google.com/go/storage/bucket.go
generated
vendored
16
vendor/cloud.google.com/go/storage/bucket.go
generated
vendored
@@ -21,6 +21,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -81,7 +82,7 @@ func (c *Client) Bucket(name string) *BucketHandle {
|
||||
// Create creates the Bucket in the project.
|
||||
// If attrs is nil the API defaults will be used.
|
||||
func (b *BucketHandle) Create(ctx context.Context, projectID string, attrs *BucketAttrs) (err error) {
|
||||
ctx, _ = startSpan(ctx, "Bucket.Create")
|
||||
ctx, _ = startSpanWithBucket(ctx, b.c, b.name, "Bucket.Create")
|
||||
defer func() { endSpan(ctx, err) }()
|
||||
|
||||
o := makeStorageOpts(true, b.retry, b.userProject)
|
||||
@@ -94,7 +95,7 @@ func (b *BucketHandle) Create(ctx context.Context, projectID string, attrs *Buck
|
||||
|
||||
// Delete deletes the Bucket.
|
||||
func (b *BucketHandle) Delete(ctx context.Context) (err error) {
|
||||
ctx, _ = startSpan(ctx, "Bucket.Delete")
|
||||
ctx, _ = startSpanWithBucket(ctx, b.c, b.name, "Bucket.Delete")
|
||||
defer func() { endSpan(ctx, err) }()
|
||||
|
||||
o := makeStorageOpts(true, b.retry, b.userProject)
|
||||
@@ -149,16 +150,21 @@ func (b *BucketHandle) Object(name string) *ObjectHandle {
|
||||
|
||||
// Attrs returns the metadata for the bucket.
|
||||
func (b *BucketHandle) Attrs(ctx context.Context) (attrs *BucketAttrs, err error) {
|
||||
ctx, _ = startSpan(ctx, "Bucket.Attrs")
|
||||
ctx, _ = startSpanWithBucket(ctx, b.c, b.name, "Bucket.Attrs")
|
||||
defer func() { endSpan(ctx, err) }()
|
||||
|
||||
o := makeStorageOpts(true, b.retry, b.userProject)
|
||||
return b.c.tc.GetBucket(ctx, b.name, b.conds, o...)
|
||||
attrs, err = b.c.tc.GetBucket(ctx, b.name, b.conds, o...)
|
||||
if err == nil && b.c != nil && b.c.bucketMetadataCache != nil {
|
||||
resource, location := getMetadataFromAttrs(attrs.Location, attrs.LocationType, strconv.FormatUint(attrs.ProjectNumber, 10), b.name)
|
||||
b.c.bucketMetadataCache.put(b.name, bucketMetadata{resource: resource, location: location})
|
||||
}
|
||||
return attrs, err
|
||||
}
|
||||
|
||||
// Update updates a bucket's attributes.
|
||||
func (b *BucketHandle) Update(ctx context.Context, uattrs BucketAttrsToUpdate) (attrs *BucketAttrs, err error) {
|
||||
ctx, _ = startSpan(ctx, "Bucket.Update")
|
||||
ctx, _ = startSpanWithBucket(ctx, b.c, b.name, "Bucket.Update")
|
||||
defer func() { endSpan(ctx, err) }()
|
||||
|
||||
isIdempotent := b.conds != nil && b.conds.MetagenerationMatch != 0
|
||||
|
||||
161
vendor/cloud.google.com/go/storage/bucket_metadata_cache.go
generated
vendored
Normal file
161
vendor/cloud.google.com/go/storage/bucket_metadata_cache.go
generated
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
// Copyright 2026 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sync/singleflight"
|
||||
"google.golang.org/grpc/codes"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultBucketMetadataCacheLimit = 10000
|
||||
fetchBackgroundTimeout = 10 * time.Second
|
||||
)
|
||||
|
||||
type bucketMetadataFetcher interface {
|
||||
fetchBucketMetadata(ctx context.Context, bucket string) (resource string, location string, err error)
|
||||
}
|
||||
|
||||
type bucketMetadata struct {
|
||||
resource string
|
||||
location string
|
||||
placeholder bool
|
||||
}
|
||||
|
||||
type bucketMetadataCache struct {
|
||||
mu sync.Mutex
|
||||
muSF singleflight.Group
|
||||
lru *lruCache[string, bucketMetadata]
|
||||
fetcher bucketMetadataFetcher
|
||||
// fetchDone is a hook channel used to signal completion of fetchBackground in tests.
|
||||
fetchDone chan struct{}
|
||||
}
|
||||
|
||||
func newBucketMetadataCache(limit int, fetcher bucketMetadataFetcher) *bucketMetadataCache {
|
||||
return &bucketMetadataCache{
|
||||
lru: newLRUCache[string, bucketMetadata](limit),
|
||||
fetcher: fetcher,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *bucketMetadataCache) get(bucket string) (bucketMetadata, bool) {
|
||||
if c == nil {
|
||||
return bucketMetadata{}, false
|
||||
}
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
return c.lru.get(bucket)
|
||||
}
|
||||
|
||||
func (c *bucketMetadataCache) put(bucket string, entry bucketMetadata) {
|
||||
if c == nil {
|
||||
return
|
||||
}
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
// Don't let a placeholder overwrite valid metadata.
|
||||
if entry.placeholder {
|
||||
if curr, hit := c.lru.get(bucket); hit && !curr.placeholder {
|
||||
return
|
||||
}
|
||||
}
|
||||
c.lru.put(bucket, entry)
|
||||
}
|
||||
|
||||
func (c *bucketMetadataCache) evict(bucket string) {
|
||||
if c == nil {
|
||||
return
|
||||
}
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
c.lru.evict(bucket)
|
||||
}
|
||||
|
||||
func (c *bucketMetadataCache) fetchBackground(bucket string) {
|
||||
if c == nil || c.fetcher == nil {
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer func() {
|
||||
if c.fetchDone != nil {
|
||||
select {
|
||||
case c.fetchDone <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
c.muSF.Do(bucket, func() (interface{}, error) {
|
||||
// Perform the call with context.Background and a timeout so it runs outside request context lifetime but is bounded.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), fetchBackgroundTimeout)
|
||||
defer cancel()
|
||||
resource, location, err := c.fetcher.fetchBucketMetadata(ctx, bucket)
|
||||
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
curr, hit := c.lru.get(bucket)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrBucketNotExist) || isError(err, http.StatusNotFound, codes.NotFound) {
|
||||
c.lru.evict(bucket)
|
||||
} else if ShouldRetry(err) {
|
||||
if curr.placeholder {
|
||||
c.lru.evict(bucket)
|
||||
}
|
||||
} else {
|
||||
if !hit {
|
||||
c.lru.put(bucket, bucketMetadata{
|
||||
resource: fmt.Sprintf("projects/_/buckets/%s", bucket),
|
||||
location: "global",
|
||||
placeholder: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
entry := bucketMetadata{
|
||||
resource: resource,
|
||||
location: location,
|
||||
}
|
||||
c.lru.put(bucket, entry)
|
||||
return entry, nil
|
||||
})
|
||||
}()
|
||||
}
|
||||
|
||||
func getMetadataFromAttrs(location, locationType, project, bucket string) (string, string) {
|
||||
finalLocation := "global"
|
||||
if locationType == "zone" || locationType == "region" {
|
||||
finalLocation = strings.ToLower(location)
|
||||
}
|
||||
if strings.HasPrefix(project, "projects/") {
|
||||
return project + "/buckets/" + bucket, finalLocation
|
||||
}
|
||||
finalProject := "_"
|
||||
if project != "0" && project != "" {
|
||||
finalProject = project
|
||||
}
|
||||
return fmt.Sprintf("projects/%s/buckets/%s", finalProject, bucket), finalLocation
|
||||
}
|
||||
45
vendor/cloud.google.com/go/storage/client.go
generated
vendored
45
vendor/cloud.google.com/go/storage/client.go
generated
vendored
@@ -109,6 +109,8 @@ type storageClient interface {
|
||||
DeleteNotification(ctx context.Context, bucket string, id string, opts ...storageOption) error
|
||||
|
||||
NewMultiRangeDownloader(ctx context.Context, params *newMultiRangeDownloaderParams, opts ...storageOption) (*MultiRangeDownloader, error)
|
||||
|
||||
fetchBucketMetadata(ctx context.Context, bucket string) (resource string, location string, err error)
|
||||
}
|
||||
|
||||
// settings contains transport-agnostic configuration for API calls made via
|
||||
@@ -297,12 +299,13 @@ type openWriterParams struct {
|
||||
}
|
||||
|
||||
type newMultiRangeDownloaderParams struct {
|
||||
bucket string
|
||||
conds *Conditions
|
||||
encryptionKey []byte
|
||||
gen int64
|
||||
object string
|
||||
handle *ReadHandle
|
||||
bucket string
|
||||
conds *Conditions
|
||||
disableMRDReadChecksum bool
|
||||
encryptionKey []byte
|
||||
gen int64
|
||||
handle *ReadHandle
|
||||
object string
|
||||
|
||||
// Multistream settings.
|
||||
minConnections int
|
||||
@@ -312,15 +315,16 @@ type newMultiRangeDownloaderParams struct {
|
||||
}
|
||||
|
||||
type newRangeReaderParams struct {
|
||||
bucket string
|
||||
conds *Conditions
|
||||
encryptionKey []byte
|
||||
gen int64
|
||||
length int64
|
||||
object string
|
||||
offset int64
|
||||
readCompressed bool // Use accept-encoding: gzip. Only works for HTTP currently.
|
||||
handle *ReadHandle
|
||||
bucket string
|
||||
conds *Conditions
|
||||
encryptionKey []byte
|
||||
gen int64
|
||||
length int64
|
||||
object string
|
||||
offset int64
|
||||
readCompressed bool // Use accept-encoding: gzip. Only works for HTTP currently.
|
||||
handle *ReadHandle
|
||||
disableCRCCheck bool
|
||||
}
|
||||
|
||||
type getObjectParams struct {
|
||||
@@ -356,11 +360,12 @@ type moveObjectParams struct {
|
||||
}
|
||||
|
||||
type composeObjectRequest struct {
|
||||
dstBucket string
|
||||
dstObject destinationObject
|
||||
srcs []sourceObject
|
||||
predefinedACL string
|
||||
sendCRC32C bool
|
||||
dstBucket string
|
||||
dstObject destinationObject
|
||||
srcs []sourceObject
|
||||
predefinedACL string
|
||||
sendCRC32C bool
|
||||
deleteSourceObjects bool
|
||||
}
|
||||
|
||||
type sourceObject struct {
|
||||
|
||||
15
vendor/cloud.google.com/go/storage/copy.go
generated
vendored
15
vendor/cloud.google.com/go/storage/copy.go
generated
vendored
@@ -80,7 +80,7 @@ type Copier struct {
|
||||
|
||||
// Run performs the copy.
|
||||
func (c *Copier) Run(ctx context.Context) (attrs *ObjectAttrs, err error) {
|
||||
ctx, _ = startSpan(ctx, "Copier.Run")
|
||||
ctx, _ = startSpanWithBucket(ctx, c.dst.c, c.dst.bucket, "Copier.Run")
|
||||
defer func() { endSpan(ctx, err) }()
|
||||
|
||||
if err := c.src.validate(); err != nil {
|
||||
@@ -172,13 +172,17 @@ type Composer struct {
|
||||
// the checksum, the compose will be rejected.
|
||||
SendCRC32C bool
|
||||
|
||||
// DeleteSourceObjects specifies whether to delete the source objects after a
|
||||
// successful composition.
|
||||
DeleteSourceObjects bool
|
||||
|
||||
dst *ObjectHandle
|
||||
srcs []*ObjectHandle
|
||||
}
|
||||
|
||||
// Run performs the compose operation.
|
||||
func (c *Composer) Run(ctx context.Context) (attrs *ObjectAttrs, err error) {
|
||||
ctx, _ = startSpan(ctx, "Composer.Run")
|
||||
ctx, _ = startSpanWithBucket(ctx, c.dst.c, c.dst.bucket, "Composer.Run")
|
||||
defer func() { endSpan(ctx, err) }()
|
||||
|
||||
if err := c.dst.validate(); err != nil {
|
||||
@@ -204,9 +208,10 @@ func (c *Composer) Run(ctx context.Context) (attrs *ObjectAttrs, err error) {
|
||||
}
|
||||
|
||||
req := &composeObjectRequest{
|
||||
dstBucket: c.dst.bucket,
|
||||
predefinedACL: c.PredefinedACL,
|
||||
sendCRC32C: c.SendCRC32C,
|
||||
dstBucket: c.dst.bucket,
|
||||
predefinedACL: c.PredefinedACL,
|
||||
sendCRC32C: c.SendCRC32C,
|
||||
deleteSourceObjects: c.DeleteSourceObjects,
|
||||
}
|
||||
req.dstObject = destinationObject{
|
||||
name: c.dst.object,
|
||||
|
||||
16
vendor/cloud.google.com/go/storage/doc.go
generated
vendored
16
vendor/cloud.google.com/go/storage/doc.go
generated
vendored
@@ -407,6 +407,9 @@ roles which must be enabled in order to do the export successfully. To
|
||||
disable this export, you can use the [WithDisabledClientMetrics] client
|
||||
option.
|
||||
|
||||
To disable OpenTelemetry bucket metadata in traces, you can set the
|
||||
environment variable GO_OTEL_BUCKETMETADATA_DISABLED=true.
|
||||
|
||||
The client automatically computes and sends CRC32C checksums for uploads using [Writer],
|
||||
providing an additional layer of data integrity validation with a slight CPU overhead.
|
||||
|
||||
@@ -416,6 +419,19 @@ apply to single-shot uploads when user-provided checksum is provided.
|
||||
|
||||
Automatic checksumming can be disabled using [Writer.DisableAutoChecksum].
|
||||
|
||||
# Read checksumming
|
||||
|
||||
By default, the client automatically computes and validates CRC32C checksums for reads
|
||||
when downloading an entire object, providing an additional layer of data integrity
|
||||
validation with a slight CPU overhead.
|
||||
|
||||
For gRPC clients, read checksumming is also performed for partial reads (range requests)
|
||||
by validating the checksum of each individual data chunk returned by the server.
|
||||
|
||||
Automatic read checksumming can be disabled using the [WithDisableReaderChecksum] option
|
||||
for a normal reader (both gRPC and JSON), or the [WithDisableMRDReadChecksum] option
|
||||
for the multi-range downloader (gRPC only).
|
||||
|
||||
# Parallel Uploads
|
||||
|
||||
The parallel upload feature splits a large object into multiple parts and uploads them
|
||||
|
||||
7
vendor/cloud.google.com/go/storage/experimental/experimental.go
generated
vendored
7
vendor/cloud.google.com/go/storage/experimental/experimental.go
generated
vendored
@@ -115,3 +115,10 @@ func WithZonalBucketAPIs() option.ClientOption {
|
||||
func WithDirectConnectivityEnforced() option.ClientOption {
|
||||
return internal.WithDirectConnectivityEnforced.(func() option.ClientOption)()
|
||||
}
|
||||
|
||||
// WithOtelMetrics provides an [option.ClientOption] that may be passed to
|
||||
// [cloud.google.com/go/storage.NewClient] or [cloud.google.com/go/storage.NewGRPCClient].
|
||||
// It enables client-side OpenTelemetry metrics.
|
||||
func WithOtelMetrics() option.ClientOption {
|
||||
return internal.WithOtelMetrics.(func() option.ClientOption)()
|
||||
}
|
||||
|
||||
280
vendor/cloud.google.com/go/storage/grpc_client.go
generated
vendored
280
vendor/cloud.google.com/go/storage/grpc_client.go
generated
vendored
@@ -120,10 +120,12 @@ func defaultGRPCOptions() []option.ClientOption {
|
||||
// grpcStorageClient is the gRPC API implementation of the transport-agnostic
|
||||
// storageClient interface.
|
||||
type grpcStorageClient struct {
|
||||
raw *gapic.Client
|
||||
settings *settings
|
||||
config *storageConfig
|
||||
dpDiag string
|
||||
raw *gapic.Client
|
||||
settings *settings
|
||||
config *storageConfig
|
||||
dpDiag string
|
||||
metrics *clientMetrics
|
||||
metricsCleanup func()
|
||||
|
||||
// configFeatureAttributes tracks client-level features that are enabled for this
|
||||
// client instance.
|
||||
@@ -152,7 +154,7 @@ func enableClientMetrics(ctx context.Context, s *settings, config storageConfig)
|
||||
|
||||
// newGRPCStorageClient initializes a new storageClient that uses the gRPC
|
||||
// Storage API.
|
||||
func newGRPCStorageClient(ctx context.Context, opts ...storageOption) (*grpcStorageClient, error) {
|
||||
func newGRPCStorageClient(ctx context.Context, opts ...storageOption) (client *grpcStorageClient, err error) {
|
||||
s := initSettings(opts...)
|
||||
s.clientOption = append(defaultGRPCOptions(), s.clientOption...)
|
||||
// Disable all gax-level retries in favor of retry logic in the veneer client.
|
||||
@@ -172,9 +174,37 @@ func newGRPCStorageClient(ctx context.Context, opts ...storageOption) (*grpcStor
|
||||
log.Printf("Failed to enable client metrics: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
var clientMetrics *clientMetrics
|
||||
var metricsCleanup func()
|
||||
if isOtelMetricsEnabled(&config) {
|
||||
var project string
|
||||
if c, err := transport.Creds(ctx, s.clientOption...); err == nil {
|
||||
project = c.ProjectID
|
||||
}
|
||||
clientMetrics, metricsCleanup = initClientMetrics(ctx, project, &config)
|
||||
if clientMetrics != nil {
|
||||
unaryInt, streamInt := metricsInterceptors(clientMetrics)
|
||||
s.clientOption = append(s.clientOption,
|
||||
option.WithGRPCDialOption(grpc.WithChainUnaryInterceptor(unaryInt)),
|
||||
option.WithGRPCDialOption(grpc.WithChainStreamInterceptor(streamInt)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if metricsCleanup != nil {
|
||||
defer func() {
|
||||
if err != nil {
|
||||
metricsCleanup()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
c := &grpcStorageClient{
|
||||
settings: s,
|
||||
config: &config,
|
||||
settings: s,
|
||||
config: &config,
|
||||
metrics: clientMetrics,
|
||||
metricsCleanup: metricsCleanup,
|
||||
}
|
||||
// Add routing interceptors to inject headers.
|
||||
ui, si := c.routingInterceptors()
|
||||
@@ -275,6 +305,9 @@ func (c *grpcStorageClient) Close() error {
|
||||
if c.settings.metricsContext != nil {
|
||||
c.settings.metricsContext.close()
|
||||
}
|
||||
if c.metricsCleanup != nil {
|
||||
c.metricsCleanup()
|
||||
}
|
||||
return c.raw.Close()
|
||||
}
|
||||
|
||||
@@ -331,10 +364,12 @@ func (c *grpcStorageClient) ListBuckets(ctx context.Context, project string, opt
|
||||
|
||||
var gitr *gapic.BucketIterator
|
||||
fetch := func(pageSize int, pageToken string) (token string, err error) {
|
||||
ctx, record := startMetricsOp(it.ctx, "ListBuckets", false)
|
||||
defer func() { record(err) }()
|
||||
|
||||
var buckets []*storagepb.Bucket
|
||||
var next string
|
||||
err = run(it.ctx, func(ctx context.Context) error {
|
||||
err = run(ctx, func(ctx context.Context) error {
|
||||
// Initialize GAPIC-based iterator when pageToken is empty, which
|
||||
// indicates that this fetch call is attempting to get the first page.
|
||||
//
|
||||
@@ -573,16 +608,18 @@ func (c *grpcStorageClient) ListObjects(ctx context.Context, bucket string, q *Q
|
||||
Filter: it.query.Filter,
|
||||
}
|
||||
fetch := func(pageSize int, pageToken string) (token string, err error) {
|
||||
ctx, record := startMetricsOp(it.ctx, "ListObjects", false)
|
||||
defer func() { record(err) }()
|
||||
// Add trace span around List API call within the fetch.
|
||||
ctx, _ = startSpan(ctx, "grpcStorageClient.ObjectsListCall")
|
||||
defer func() { endSpan(ctx, err) }()
|
||||
var objects []*storagepb.Object
|
||||
var gitr *gapic.ObjectIterator
|
||||
err = run(it.ctx, func(ctx context.Context) error {
|
||||
err = run(ctx, func(ctx context.Context) error {
|
||||
gitr = c.raw.ListObjects(ctx, req, s.gax...)
|
||||
objects, token, err = gitr.InternalFetch(pageSize, pageToken)
|
||||
return err
|
||||
}, s.retry, s.idempotent)
|
||||
}, s.retry, s.idempotent, withOperation("ListObjects"), withBucket(bucket), withObject(it.query.Prefix))
|
||||
if err != nil {
|
||||
return "", formatBucketError(err)
|
||||
}
|
||||
@@ -1055,6 +1092,9 @@ func (c *grpcStorageClient) ComposeObject(ctx context.Context, req *composeObjec
|
||||
Destination: dstObjPb,
|
||||
SourceObjects: srcs,
|
||||
}
|
||||
if req.deleteSourceObjects {
|
||||
rawReq.DeleteSourceObjects = proto.Bool(true)
|
||||
}
|
||||
if err := applyCondsProto("ComposeObject destination", defaultGen, req.dstObject.conds, rawReq); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1328,7 +1368,7 @@ func (c *grpcStorageClient) NewRangeReader(ctx context.Context, params *newRange
|
||||
}
|
||||
err = decoder.readFullObjectResponse()
|
||||
return err
|
||||
}, s.retry, s.idempotent)
|
||||
}, s.retry, s.idempotent, withOperation("ReadObject"), withBucket(params.bucket), withObject(params.object))
|
||||
if err != nil {
|
||||
// Close the stream context we just created to ensure we don't leak
|
||||
// resources.
|
||||
@@ -1369,18 +1409,6 @@ func (c *grpcStorageClient) NewRangeReader(ctx context.Context, params *newRange
|
||||
params.length = obj.Size - params.offset
|
||||
}
|
||||
|
||||
// Only support checksums when reading an entire object, not a range.
|
||||
var (
|
||||
wantCRC uint32
|
||||
checkCRC bool
|
||||
)
|
||||
if checksums := obj.GetChecksums(); checksums != nil && checksums.Crc32C != nil {
|
||||
if params.offset == 0 && params.length < 0 {
|
||||
checkCRC = true
|
||||
}
|
||||
wantCRC = checksums.GetCrc32C()
|
||||
}
|
||||
|
||||
startOffset := params.offset
|
||||
if params.offset < 0 {
|
||||
startOffset = size + params.offset
|
||||
@@ -1390,6 +1418,20 @@ func (c *grpcStorageClient) NewRangeReader(ctx context.Context, params *newRange
|
||||
if startOffset < 0 {
|
||||
startOffset = 0
|
||||
}
|
||||
// Only support checksums when reading an entire object, not a range.
|
||||
var (
|
||||
wantCRC uint32
|
||||
checkCRC bool
|
||||
)
|
||||
if checksums := obj.GetChecksums(); checksums != nil && checksums.Crc32C != nil {
|
||||
if !params.disableCRCCheck &&
|
||||
startOffset == 0 &&
|
||||
(params.length < 0 ||
|
||||
finalized && params.length >= size) {
|
||||
checkCRC = true
|
||||
}
|
||||
wantCRC = checksums.GetCrc32C()
|
||||
}
|
||||
|
||||
// The remaining bytes are the lesser of the requested range and all bytes
|
||||
// after params.offset.
|
||||
@@ -1401,6 +1443,15 @@ func (c *grpcStorageClient) NewRangeReader(ctx context.Context, params *newRange
|
||||
}
|
||||
remain := length - startOffset
|
||||
|
||||
var chunkCRC uint32
|
||||
var chunkCRCPresent bool
|
||||
if ranges := msg.GetObjectDataRanges(); len(ranges) > 0 {
|
||||
if cs := ranges[0].GetChecksummedData(); cs != nil && cs.Crc32C != nil && !params.disableCRCCheck {
|
||||
chunkCRCPresent = true
|
||||
chunkCRC = *cs.Crc32C
|
||||
}
|
||||
}
|
||||
|
||||
metadata := obj.GetMetadata()
|
||||
r = &Reader{
|
||||
Attrs: ReaderObjectAttrs{
|
||||
@@ -1421,18 +1472,23 @@ func (c *grpcStorageClient) NewRangeReader(ctx context.Context, params *newRange
|
||||
cancel: cancel,
|
||||
size: size,
|
||||
// Preserve the decoder to read out object data when Read/WriteTo is called.
|
||||
currMsg: res.decoder,
|
||||
settings: s,
|
||||
zeroRange: params.length == 0,
|
||||
wantCRC: wantCRC,
|
||||
checkCRC: checkCRC,
|
||||
finalized: finalized,
|
||||
negativeOffset: negativeOffset,
|
||||
currMsg: res.decoder,
|
||||
wantChunkCRC: chunkCRC,
|
||||
chunkCRCPresent: chunkCRCPresent,
|
||||
settings: s,
|
||||
zeroRange: params.length == 0,
|
||||
wantCRC: wantCRC,
|
||||
checkCRC: checkCRC,
|
||||
disableCRCCheck: params.disableCRCCheck,
|
||||
finalized: finalized,
|
||||
negativeOffset: negativeOffset,
|
||||
},
|
||||
checkCRC: checkCRC,
|
||||
handle: &handle,
|
||||
remain: remain,
|
||||
unfinalized: !finalized,
|
||||
bucket: params.bucket,
|
||||
object: params.object,
|
||||
}
|
||||
|
||||
// For a zero-length request, explicitly close the stream and set remaining
|
||||
@@ -1570,19 +1626,23 @@ type bidiReadStreamResponse struct {
|
||||
|
||||
// gRPCReader is used by storage.Reader if the experimental option WithGRPCBidiReads is passed.
|
||||
type gRPCReader struct {
|
||||
seen, size int64
|
||||
zeroRange bool
|
||||
finalized bool // if we are reading from a finalized object; in this case, remain and size may be inaccurate
|
||||
negativeOffset bool
|
||||
stream storagepb.Storage_BidiReadObjectClient
|
||||
reopen func(seen int64) (*readStreamResponse, context.CancelFunc, error)
|
||||
leftovers []byte
|
||||
currMsg *readResponseDecoder // decoder for the current message
|
||||
cancel context.CancelFunc
|
||||
settings *settings
|
||||
checkCRC bool // should we check the CRC?
|
||||
wantCRC uint32 // the CRC32c value the server sent in the header
|
||||
gotCRC uint32 // running crc
|
||||
seen, size int64
|
||||
zeroRange bool
|
||||
finalized bool // if we are reading from a finalized object; in this case, remain and size may be inaccurate
|
||||
negativeOffset bool
|
||||
stream storagepb.Storage_BidiReadObjectClient
|
||||
reopen func(seen int64) (*readStreamResponse, context.CancelFunc, error)
|
||||
leftovers []byte
|
||||
currMsg *readResponseDecoder // decoder for the current message
|
||||
wantChunkCRC uint32
|
||||
chunkCRCPresent bool
|
||||
cancel context.CancelFunc
|
||||
settings *settings
|
||||
checkCRC bool // should we check the CRC?
|
||||
wantCRC uint32 // the CRC32c value the server sent in the header
|
||||
gotCRC uint32 // running crc
|
||||
gotChunkCRC uint32 // running crc32c of chunk
|
||||
disableCRCCheck bool
|
||||
}
|
||||
|
||||
// Update the running CRC with the data in the slice, if CRC checking was enabled.
|
||||
@@ -1590,6 +1650,9 @@ func (r *gRPCReader) updateCRC(b []byte) {
|
||||
if r.checkCRC {
|
||||
r.gotCRC = crc32.Update(r.gotCRC, crc32cTable, b)
|
||||
}
|
||||
if r.chunkCRCPresent {
|
||||
r.gotChunkCRC = crc32.Update(r.gotChunkCRC, crc32cTable, b)
|
||||
}
|
||||
}
|
||||
|
||||
// Checks whether the CRC matches at the conclusion of a read, if CRC checking was enabled.
|
||||
@@ -1600,6 +1663,17 @@ func (r *gRPCReader) runCRCCheck() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkAndResetChunkCRC verifies the chunk CRC if present, and resets the chunk CRC state.
|
||||
func (r *gRPCReader) checkAndResetChunkCRC() error {
|
||||
if r.chunkCRCPresent && r.gotChunkCRC != r.wantChunkCRC {
|
||||
return fmt.Errorf("storage: bad CRC on chunk read: got %d, want %d", r.gotChunkCRC, r.wantChunkCRC)
|
||||
}
|
||||
r.gotChunkCRC = 0
|
||||
r.chunkCRCPresent = false
|
||||
r.wantChunkCRC = 0
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read reads bytes into the user's buffer from an open gRPC stream.
|
||||
func (r *gRPCReader) Read(p []byte) (int, error) {
|
||||
// The entire object has been read by this reader, check the checksum if
|
||||
@@ -1622,29 +1696,53 @@ func (r *gRPCReader) Read(p []byte) (int, error) {
|
||||
for {
|
||||
// If there is data remaining in the current message, try to read from it.
|
||||
if r.currMsg != nil && !r.currMsg.done {
|
||||
n, found := r.currMsg.readAndUpdateCRC(p, 1, func(b []byte) {
|
||||
n, found := r.currMsg.readAndUpdateCRC(p, defaultReadID, func(b []byte) {
|
||||
r.updateCRC(b)
|
||||
})
|
||||
// If we are done reading the current msg, free buffers.
|
||||
if r.currMsg.done {
|
||||
r.currMsg.databufs.Free()
|
||||
}
|
||||
|
||||
// If data for our readID was found, we can update `seen` and return.
|
||||
if found {
|
||||
r.seen += int64(n)
|
||||
}
|
||||
// If we are done reading the current msg, validate chunk checksum and free buffers.
|
||||
if r.currMsg.done {
|
||||
r.currMsg.databufs.Free()
|
||||
if err := r.checkAndResetChunkCRC(); err != nil {
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
|
||||
// If data for our readID was found, we can return.
|
||||
if found {
|
||||
return n, nil
|
||||
}
|
||||
// If not found, this message is exhausted for our purposes.
|
||||
// Fall through to recv() to get a new one.
|
||||
} else if r.currMsg != nil {
|
||||
if err := r.checkAndResetChunkCRC(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
// Get the next message from the stream.
|
||||
err := r.recv()
|
||||
if err == io.EOF {
|
||||
if err := r.runCRCCheck(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return 0, io.EOF
|
||||
}
|
||||
if err != nil {
|
||||
// This correctly handles io.EOF, context canceled, and other terminal errors.
|
||||
return 0, err
|
||||
}
|
||||
msg := r.currMsg.msg
|
||||
if !r.disableCRCCheck &&
|
||||
len(msg.GetObjectDataRanges()) > 0 &&
|
||||
msg.GetObjectDataRanges()[0].GetChecksummedData() != nil &&
|
||||
msg.GetObjectDataRanges()[0].GetChecksummedData().Crc32C != nil {
|
||||
r.gotChunkCRC = 0
|
||||
r.wantChunkCRC = *msg.GetObjectDataRanges()[0].GetChecksummedData().Crc32C
|
||||
r.chunkCRCPresent = true
|
||||
}
|
||||
// The loop will now restart and try to read from the new r.currMsg.
|
||||
}
|
||||
}
|
||||
@@ -1686,8 +1784,19 @@ func (r *gRPCReader) WriteTo(w io.Writer) (int64, error) {
|
||||
if err != nil {
|
||||
return r.seen - alreadySeen, err
|
||||
}
|
||||
if r.currMsg.done {
|
||||
if err := r.checkAndResetChunkCRC(); err != nil {
|
||||
return r.seen - alreadySeen, err
|
||||
}
|
||||
}
|
||||
// If no data was found, we still need to fetch the next message.
|
||||
// If data was found, we also need the next message. So we always fall through.
|
||||
r.currMsg = nil
|
||||
|
||||
} else if r.currMsg != nil {
|
||||
if err := r.checkAndResetChunkCRC(); err != nil {
|
||||
return r.seen - alreadySeen, err
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to receive the next message on the stream.
|
||||
@@ -1699,6 +1808,15 @@ func (r *gRPCReader) WriteTo(w io.Writer) (int64, error) {
|
||||
}
|
||||
return r.seen - alreadySeen, err
|
||||
}
|
||||
msg := r.currMsg.msg
|
||||
if !r.disableCRCCheck &&
|
||||
len(msg.GetObjectDataRanges()) > 0 &&
|
||||
msg.GetObjectDataRanges()[0].GetChecksummedData() != nil &&
|
||||
msg.GetObjectDataRanges()[0].GetChecksummedData().Crc32C != nil {
|
||||
r.gotChunkCRC = 0
|
||||
r.wantChunkCRC = *msg.GetObjectDataRanges()[0].GetChecksummedData().Crc32C
|
||||
r.chunkCRCPresent = true
|
||||
}
|
||||
// Continue loop to process the new message.
|
||||
}
|
||||
// Propagate any checksum error.
|
||||
@@ -1781,6 +1899,7 @@ type readResponseDecoder struct {
|
||||
msg *storagepb.BidiReadObjectResponse // processed response message with all fields other than object data populated
|
||||
dataOffsets map[int64]bufferSliceOffsets // Map ReadId to the offsets of the object data for that ID in the message.
|
||||
done bool // true if the data has been completely read.
|
||||
crcErrs map[int64]error // Map ReadId to the CRC validation error if it failed.
|
||||
}
|
||||
|
||||
type bufferSliceOffsets struct {
|
||||
@@ -1908,6 +2027,51 @@ func (d *readResponseDecoder) readAndUpdateCRC(p []byte, readID int64, updateCRC
|
||||
return n, true
|
||||
}
|
||||
|
||||
func (d *readResponseDecoder) verifyChecksums() {
|
||||
if d.msg == nil {
|
||||
return
|
||||
}
|
||||
for _, dataRange := range d.msg.GetObjectDataRanges() {
|
||||
checksummedData := dataRange.GetChecksummedData()
|
||||
if checksummedData == nil || checksummedData.Crc32C == nil {
|
||||
continue
|
||||
}
|
||||
readID := dataRange.GetReadRange().GetReadId()
|
||||
offsets, ok := d.dataOffsets[readID]
|
||||
wantCRC := *checksummedData.Crc32C
|
||||
var gotCRC uint32
|
||||
|
||||
if ok {
|
||||
for i := offsets.startBuf; i <= offsets.endBuf; i++ {
|
||||
if i < 0 || i >= len(d.databufs) {
|
||||
continue
|
||||
}
|
||||
databuf := d.databufs[i]
|
||||
var start uint64
|
||||
if i == offsets.startBuf {
|
||||
start = min(offsets.startOff, uint64(databuf.Len()))
|
||||
}
|
||||
end := uint64(databuf.Len())
|
||||
if i == offsets.endBuf {
|
||||
end = min(offsets.endOff, end)
|
||||
}
|
||||
if start >= end {
|
||||
continue
|
||||
}
|
||||
dataSlice := databuf.ReadOnlyData()[start:end]
|
||||
gotCRC = crc32.Update(gotCRC, crc32cTable, dataSlice)
|
||||
}
|
||||
}
|
||||
|
||||
if gotCRC != wantCRC {
|
||||
if d.crcErrs == nil {
|
||||
d.crcErrs = make(map[int64]error)
|
||||
}
|
||||
d.crcErrs[readID] = fmt.Errorf("storage: bad CRC on chunk read: got %d, want %d", gotCRC, wantCRC)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *readResponseDecoder) writeToAndUpdateCRC(w io.Writer, readID int64, updateCRC func([]byte)) (totalWritten int64, found bool, err error) {
|
||||
// For a completely empty message, just return 0
|
||||
if len(d.databufs) == 0 {
|
||||
@@ -1923,6 +2087,9 @@ func (d *readResponseDecoder) writeToAndUpdateCRC(w io.Writer, readID int64, upd
|
||||
|
||||
// Loop from the current buffer to the ending buffer for this specific data range.
|
||||
for i := offsets.currBuf; i <= offsets.endBuf; i++ {
|
||||
if i < 0 || i >= len(d.databufs) {
|
||||
continue
|
||||
}
|
||||
databuf := d.databufs[i]
|
||||
|
||||
// Determine the start and end of the data slice for the current buffer.
|
||||
@@ -2240,3 +2407,16 @@ func (r *gRPCReader) reopenStream() error {
|
||||
r.cancel = cancel
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *grpcStorageClient) fetchBucketMetadata(ctx context.Context, bucket string) (string, string, error) {
|
||||
req := &storagepb.GetBucketRequest{
|
||||
Name: bucketResourceName(globalProjectAlias, bucket),
|
||||
ReadMask: &fieldmaskpb.FieldMask{Paths: []string{"name", "project", "location", "location_type"}},
|
||||
}
|
||||
resp, err := c.raw.GetBucket(ctx, req)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
resource, location := getMetadataFromAttrs(resp.GetLocation(), resp.GetLocationType(), resp.GetProject(), bucket)
|
||||
return resource, location, nil
|
||||
}
|
||||
|
||||
8
vendor/cloud.google.com/go/storage/grpc_metrics.go
generated
vendored
8
vendor/cloud.google.com/go/storage/grpc_metrics.go
generated
vendored
@@ -53,7 +53,9 @@ type storageMonitoredResource struct {
|
||||
func (smr *storageMonitoredResource) exporter() (metric.Exporter, error) {
|
||||
exporter, err := mexporter.New(
|
||||
mexporter.WithProjectID(smr.project),
|
||||
mexporter.WithMetricDescriptorTypeFormatter(metricFormatter),
|
||||
mexporter.WithMetricDescriptorTypeFormatter(func(m metricdata.Metrics) string {
|
||||
return formatMetricWithPrefix(m, metricPrefix)
|
||||
}),
|
||||
mexporter.WithCreateServiceTimeSeries(),
|
||||
mexporter.WithMonitoredResourceDescription(monitoredResourceName, []string{"project_id", "location", "cloud_platform", "host_id", "instance_id", "api"}),
|
||||
)
|
||||
@@ -281,7 +283,3 @@ func createHistogramView(name string, boundaries []float64) metric.View {
|
||||
Aggregation: metric.AggregationExplicitBucketHistogram{Boundaries: boundaries},
|
||||
})
|
||||
}
|
||||
|
||||
func metricFormatter(m metricdata.Metrics) string {
|
||||
return metricPrefix + strings.ReplaceAll(string(m.Name), ".", "/")
|
||||
}
|
||||
|
||||
133
vendor/cloud.google.com/go/storage/grpc_reader.go
generated
vendored
133
vendor/cloud.google.com/go/storage/grpc_reader.go
generated
vendored
@@ -183,14 +183,32 @@ func (c *grpcStorageClient) NewRangeReaderReadObject(ctx context.Context, params
|
||||
obj := msg.GetMetadata()
|
||||
// This is the size of the entire object, even if only a range was requested.
|
||||
size := obj.GetSize()
|
||||
var chunkCRC uint32
|
||||
chunkCRCPresent := false
|
||||
if !params.disableCRCCheck &&
|
||||
msg.GetChecksummedData() != nil &&
|
||||
msg.GetChecksummedData().Crc32C != nil {
|
||||
chunkCRCPresent = true
|
||||
chunkCRC = *msg.GetChecksummedData().Crc32C
|
||||
}
|
||||
startOffset := params.offset
|
||||
if params.offset < 0 {
|
||||
startOffset = size + params.offset
|
||||
}
|
||||
// If caller has specified a negative start offset that's larger than the
|
||||
// reported size, start at the beginning of the object.
|
||||
if startOffset < 0 {
|
||||
startOffset = 0
|
||||
}
|
||||
|
||||
// Only support checksums when reading an entire object, not a range.
|
||||
var (
|
||||
wantCRC uint32
|
||||
checkCRC bool
|
||||
)
|
||||
if checksums := msg.GetObjectChecksums(); checksums != nil && checksums.Crc32C != nil {
|
||||
if params.offset == 0 && params.length < 0 {
|
||||
if !params.disableCRCCheck &&
|
||||
startOffset == 0 &&
|
||||
(params.length < 0 || (obj != nil && params.length >= size)) {
|
||||
checkCRC = true
|
||||
}
|
||||
wantCRC = checksums.GetCrc32C()
|
||||
@@ -215,13 +233,18 @@ func (c *grpcStorageClient) NewRangeReaderReadObject(ctx context.Context, params
|
||||
cancel: cancel,
|
||||
size: size,
|
||||
// Preserve the decoder to read out object data when Read/WriteTo is called.
|
||||
currMsg: res.decoder,
|
||||
settings: s,
|
||||
zeroRange: params.length == 0,
|
||||
wantCRC: wantCRC,
|
||||
checkCRC: checkCRC,
|
||||
currMsg: res.decoder,
|
||||
wantChunkCRC: chunkCRC,
|
||||
chunkCRCPresent: chunkCRCPresent,
|
||||
settings: s,
|
||||
zeroRange: params.length == 0,
|
||||
wantCRC: wantCRC,
|
||||
checkCRC: checkCRC,
|
||||
disableCRCCheck: params.disableCRCCheck,
|
||||
},
|
||||
checkCRC: checkCRC,
|
||||
bucket: params.bucket,
|
||||
object: params.object,
|
||||
}
|
||||
|
||||
cr := msg.GetContentRange()
|
||||
@@ -248,17 +271,21 @@ type readStreamResponseReadObject struct {
|
||||
}
|
||||
|
||||
type gRPCReadObjectReader struct {
|
||||
seen, size int64
|
||||
zeroRange bool
|
||||
stream storagepb.Storage_ReadObjectClient
|
||||
reopen func(seen int64) (*readStreamResponseReadObject, context.CancelFunc, error)
|
||||
leftovers []byte
|
||||
currMsg *readObjectResponseDecoder // decoder for the current message
|
||||
cancel context.CancelFunc
|
||||
settings *settings
|
||||
checkCRC bool // should we check the CRC?
|
||||
wantCRC uint32 // the CRC32c value the server sent in the header
|
||||
gotCRC uint32 // running crc
|
||||
seen, size int64
|
||||
zeroRange bool
|
||||
stream storagepb.Storage_ReadObjectClient
|
||||
reopen func(seen int64) (*readStreamResponseReadObject, context.CancelFunc, error)
|
||||
leftovers []byte
|
||||
currMsg *readObjectResponseDecoder // decoder for the current message
|
||||
wantChunkCRC uint32
|
||||
chunkCRCPresent bool
|
||||
cancel context.CancelFunc
|
||||
settings *settings
|
||||
checkCRC bool // should we check the CRC?
|
||||
wantCRC uint32 // the CRC32c value the server sent in the header
|
||||
gotCRC uint32 // running crc
|
||||
gotChunkCRC uint32 // running crc32c of chunk
|
||||
disableCRCCheck bool
|
||||
}
|
||||
|
||||
// Update the running CRC with the data in the slice, if CRC checking was enabled.
|
||||
@@ -266,6 +293,9 @@ func (r *gRPCReadObjectReader) updateCRC(b []byte) {
|
||||
if r.checkCRC {
|
||||
r.gotCRC = crc32.Update(r.gotCRC, crc32cTable, b)
|
||||
}
|
||||
if r.chunkCRCPresent {
|
||||
r.gotChunkCRC = crc32.Update(r.gotChunkCRC, crc32cTable, b)
|
||||
}
|
||||
}
|
||||
|
||||
// Checks whether the CRC matches at the conclusion of a read, if CRC checking was enabled.
|
||||
@@ -276,6 +306,17 @@ func (r *gRPCReadObjectReader) runCRCCheck() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkAndResetChunkCRC verifies the chunk CRC if present, and resets the chunk CRC state.
|
||||
func (r *gRPCReadObjectReader) checkAndResetChunkCRC() error {
|
||||
if r.chunkCRCPresent && r.gotChunkCRC != r.wantChunkCRC {
|
||||
return fmt.Errorf("storage: bad CRC on chunk read: got %d, want %d", r.gotChunkCRC, r.wantChunkCRC)
|
||||
}
|
||||
r.gotChunkCRC = 0
|
||||
r.chunkCRCPresent = false
|
||||
r.wantChunkCRC = 0
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read reads bytes into the user's buffer from an open gRPC stream.
|
||||
func (r *gRPCReadObjectReader) Read(p []byte) (int, error) {
|
||||
// The entire object has been read by this reader, check the checksum if
|
||||
@@ -305,16 +346,38 @@ func (r *gRPCReadObjectReader) Read(p []byte) (int, error) {
|
||||
r.updateCRC(b)
|
||||
})
|
||||
r.seen += int64(n)
|
||||
if r.currMsg.done {
|
||||
if err := r.checkAndResetChunkCRC(); err != nil {
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
return n, nil
|
||||
} else if err := r.checkAndResetChunkCRC(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Attempt to Recv the next message on the stream.
|
||||
// This will update r.currMsg with the decoder for the new message.
|
||||
err := r.recv()
|
||||
if err == io.EOF {
|
||||
if err := r.runCRCCheck(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return 0, io.EOF
|
||||
}
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
msg := r.currMsg.msg
|
||||
if !r.disableCRCCheck &&
|
||||
msg.GetChecksummedData() != nil &&
|
||||
msg.GetChecksummedData().Crc32C != nil {
|
||||
r.wantChunkCRC = *msg.GetChecksummedData().Crc32C
|
||||
r.chunkCRCPresent = true
|
||||
r.gotChunkCRC = 0
|
||||
}
|
||||
|
||||
// TODO: Determine if we need to capture incremental CRC32C for this
|
||||
// chunk. The Object CRC32C checksum is captured when directed to read
|
||||
// the entire Object. If directed to read a range, we may need to
|
||||
@@ -327,6 +390,11 @@ func (r *gRPCReadObjectReader) Read(p []byte) (int, error) {
|
||||
r.updateCRC(b)
|
||||
})
|
||||
r.seen += int64(n)
|
||||
if r.currMsg.done {
|
||||
if err := r.checkAndResetChunkCRC(); err != nil {
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
@@ -360,8 +428,19 @@ func (r *gRPCReadObjectReader) WriteTo(w io.Writer) (int64, error) {
|
||||
r.updateCRC(b)
|
||||
})
|
||||
r.seen += int64(written)
|
||||
r.currMsg = nil
|
||||
if err != nil {
|
||||
r.currMsg = nil
|
||||
return r.seen - alreadySeen, err
|
||||
}
|
||||
if r.currMsg.done {
|
||||
if err := r.checkAndResetChunkCRC(); err != nil {
|
||||
r.currMsg = nil
|
||||
return r.seen - alreadySeen, err
|
||||
}
|
||||
}
|
||||
r.currMsg = nil
|
||||
} else if r.currMsg != nil {
|
||||
if err := r.checkAndResetChunkCRC(); err != nil {
|
||||
return r.seen - alreadySeen, err
|
||||
}
|
||||
}
|
||||
@@ -379,7 +458,14 @@ func (r *gRPCReadObjectReader) WriteTo(w io.Writer) (int64, error) {
|
||||
}
|
||||
return r.seen - alreadySeen, err
|
||||
}
|
||||
|
||||
msg := r.currMsg.msg
|
||||
if !r.disableCRCCheck &&
|
||||
msg.ChecksummedData != nil &&
|
||||
msg.ChecksummedData.Crc32C != nil {
|
||||
r.gotChunkCRC = 0
|
||||
r.wantChunkCRC = *msg.ChecksummedData.Crc32C
|
||||
r.chunkCRCPresent = true
|
||||
}
|
||||
// TODO: Determine if we need to capture incremental CRC32C for this
|
||||
// chunk. The Object CRC32C checksum is captured when directed to read
|
||||
// the entire Object. If directed to read a range, we may need to
|
||||
@@ -394,6 +480,11 @@ func (r *gRPCReadObjectReader) WriteTo(w io.Writer) (int64, error) {
|
||||
if err != nil {
|
||||
return r.seen - alreadySeen, err
|
||||
}
|
||||
if r.currMsg != nil && r.currMsg.done {
|
||||
if err := r.checkAndResetChunkCRC(); err != nil {
|
||||
return r.seen - alreadySeen, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -596,7 +687,7 @@ func (d *readObjectResponseDecoder) writeToAndUpdateCRC(w io.Writer, updateCRC f
|
||||
// Write all remaining data from the current buffer
|
||||
n, err := w.Write(b)
|
||||
written += int64(n)
|
||||
updateCRC(b)
|
||||
updateCRC(b[:n])
|
||||
if err != nil {
|
||||
return written, err
|
||||
}
|
||||
|
||||
24
vendor/cloud.google.com/go/storage/grpc_reader_multi_range.go
generated
vendored
24
vendor/cloud.google.com/go/storage/grpc_reader_multi_range.go
generated
vendored
@@ -20,6 +20,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"cloud.google.com/go/storage/internal/apiv2/storagepb"
|
||||
@@ -769,7 +770,7 @@ func (m *multiRangeDownloaderManager) createNewSession(id int, readSpec *storage
|
||||
newSession = session
|
||||
firstResult = result
|
||||
return nil
|
||||
}, retry, true)
|
||||
}, retry, true, withOperation("ReadObject"), withBucket(m.params.bucket), withObject(m.params.object))
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@@ -1010,6 +1011,10 @@ func (m *multiRangeDownloaderManager) processSessionResult(result mrdSessionResu
|
||||
m.handleStreamEnd(result, m.streams[result.id])
|
||||
return
|
||||
}
|
||||
// Safety check but this should not happen.
|
||||
if result.decoder == nil {
|
||||
return
|
||||
}
|
||||
|
||||
resp := result.decoder.msg
|
||||
if handle := resp.GetReadHandle().GetHandle(); len(handle) > 0 {
|
||||
@@ -1057,6 +1062,7 @@ func (m *multiRangeDownloaderManager) processDataRanges(result mrdSessionResult,
|
||||
if !exists || req.completed {
|
||||
continue
|
||||
}
|
||||
|
||||
written, _, err := result.decoder.writeToAndUpdateCRC(req.output, readID, nil)
|
||||
req.bytesWritten += written
|
||||
mrdStream.updateCapacity(m, 0, -written)
|
||||
@@ -1065,10 +1071,18 @@ func (m *multiRangeDownloaderManager) processDataRanges(result mrdSessionResult,
|
||||
continue
|
||||
}
|
||||
|
||||
if result.decoder.crcErrs != nil && result.decoder.crcErrs[readID] != nil {
|
||||
m.failRange(mrdStream, req, result.decoder.crcErrs[readID])
|
||||
continue
|
||||
}
|
||||
|
||||
if dataRange.GetRangeEnd() {
|
||||
req.completed = true
|
||||
delete(mrdStream.pendingRanges, req.readID)
|
||||
delete(mrdStream.pendingRanges, readID)
|
||||
mrdStream.updateCapacity(m, -1, 0)
|
||||
if req.length >= 0 && req.bytesWritten > req.length {
|
||||
log.Printf("storage: received %d more bytes than requested from GCS for bucket %q, object %q", req.bytesWritten-req.length, m.params.bucket, m.params.object)
|
||||
}
|
||||
m.runCallback(req.origOffset, req.bytesWritten, nil, req.callback)
|
||||
}
|
||||
}
|
||||
@@ -1140,6 +1154,9 @@ func (m *multiRangeDownloaderManager) failRange(mrdStream *mrdStream, req *range
|
||||
mrdStream.updateCapacity(m, -1, -(req.length - req.bytesWritten))
|
||||
}
|
||||
}
|
||||
if req.length >= 0 && req.bytesWritten > req.length {
|
||||
log.Printf("storage: received %d more bytes than requested from GCS for bucket %q, object %q", req.bytesWritten-req.length, m.params.bucket, m.params.object)
|
||||
}
|
||||
m.runCallback(req.origOffset, req.bytesWritten, err, req.callback)
|
||||
}
|
||||
|
||||
@@ -1331,6 +1348,9 @@ func (s *bidiReadStreamSession) receiveLoop() {
|
||||
databufs: databufs,
|
||||
}
|
||||
err = decoder.readFullObjectResponse()
|
||||
if err == nil && !s.params.disableMRDReadChecksum {
|
||||
decoder.verifyChecksums()
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
||||
74
vendor/cloud.google.com/go/storage/grpc_writer.go
generated
vendored
74
vendor/cloud.google.com/go/storage/grpc_writer.go
generated
vendored
@@ -58,7 +58,8 @@ func (w *gRPCWriter) Write(p []byte) (n int, err error) {
|
||||
// Skip checksum calculation if user configures MD5 or CRC32C themselves.
|
||||
if !w.disableAutoChecksum &&
|
||||
!w.sendCRC32C &&
|
||||
!md5Provided {
|
||||
!md5Provided &&
|
||||
!w.append {
|
||||
w.fullObjectChecksum = crc32.Update(w.fullObjectChecksum, crc32cTable, p)
|
||||
}
|
||||
// write command successfully delivered to sender. We no longer own cmd.
|
||||
@@ -109,6 +110,11 @@ func (w *gRPCWriter) CloseWithError(err error) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *gRPCWriter) setAppendFinalCRC32C(sendAppendFinalCRC32C bool, c uint32) {
|
||||
w.sendAppendFinalCRC32C = sendAppendFinalCRC32C
|
||||
w.appendFinalCRC32C = c
|
||||
}
|
||||
|
||||
func (c *grpcStorageClient) OpenWriter(params *openWriterParams, opts ...storageOption) (internalWriter, error) {
|
||||
if params.attrs.Retention != nil {
|
||||
// TO-DO: remove once ObjectRetention is available - see b/308194853
|
||||
@@ -259,7 +265,9 @@ type gRPCWriter struct {
|
||||
setSize func(int64)
|
||||
setTakeoverOffset func(int64)
|
||||
|
||||
fullObjectChecksum uint32
|
||||
fullObjectChecksum uint32
|
||||
appendFinalCRC32C uint32
|
||||
sendAppendFinalCRC32C bool
|
||||
|
||||
flushSupported bool
|
||||
sendCRC32C bool
|
||||
@@ -948,9 +956,9 @@ type getObjectChecksumsParams struct {
|
||||
sendCRC32C bool
|
||||
disableAutoChecksum bool
|
||||
objectAttrs *ObjectAttrs
|
||||
fullObjectChecksum func() uint32
|
||||
fullObjectChecksum func() *uint32
|
||||
finishWrite bool
|
||||
takeoverWriter bool
|
||||
append bool
|
||||
}
|
||||
|
||||
// getObjectChecksums determines what checksum information to include in the final
|
||||
@@ -965,20 +973,30 @@ func getObjectChecksums(params *getObjectChecksumsParams) *storagepb.ObjectCheck
|
||||
return nil
|
||||
}
|
||||
|
||||
// For append operations, send user's final append checksum on last write op if available.
|
||||
// Auto checksum is not supported for appendable writes.
|
||||
var crc32c *uint32
|
||||
if params.fullObjectChecksum != nil {
|
||||
crc32c = params.fullObjectChecksum()
|
||||
}
|
||||
|
||||
if params.append && crc32c != nil {
|
||||
return &storagepb.ObjectChecksums{Crc32C: crc32c}
|
||||
}
|
||||
|
||||
// send user's checksum on last write op if available
|
||||
if params.sendCRC32C || (params.objectAttrs != nil && params.objectAttrs.MD5 != nil) {
|
||||
return toProtoChecksums(params.sendCRC32C, params.objectAttrs)
|
||||
}
|
||||
// TODO(b/461982277): Enable checksum validation for appendable takeover writer gRPC
|
||||
if params.disableAutoChecksum || params.takeoverWriter {
|
||||
|
||||
if params.append || params.disableAutoChecksum || params.fullObjectChecksum == nil {
|
||||
return nil
|
||||
}
|
||||
if params.fullObjectChecksum == nil {
|
||||
return nil
|
||||
}
|
||||
return &storagepb.ObjectChecksums{
|
||||
Crc32C: proto.Uint32(params.fullObjectChecksum()),
|
||||
|
||||
if crc32c != nil {
|
||||
return &storagepb.ObjectChecksums{Crc32C: crc32c}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type gRPCBidiWriteBufferSender interface {
|
||||
@@ -1014,7 +1032,7 @@ type gRPCOneshotBidiWriteBufferSender struct {
|
||||
sendCRC32C bool
|
||||
disableAutoChecksum bool
|
||||
objectAttrs *ObjectAttrs
|
||||
fullObjectChecksum func() uint32
|
||||
fullObjectChecksum func() *uint32
|
||||
}
|
||||
|
||||
func (w *gRPCWriter) newGRPCOneshotBidiWriteBufferSender() *gRPCOneshotBidiWriteBufferSender {
|
||||
@@ -1031,8 +1049,9 @@ func (w *gRPCWriter) newGRPCOneshotBidiWriteBufferSender() *gRPCOneshotBidiWrite
|
||||
sendCRC32C: w.sendCRC32C,
|
||||
disableAutoChecksum: w.disableAutoChecksum,
|
||||
objectAttrs: w.attrs,
|
||||
fullObjectChecksum: func() uint32 {
|
||||
return w.fullObjectChecksum
|
||||
fullObjectChecksum: func() *uint32 {
|
||||
checksum := w.fullObjectChecksum
|
||||
return &checksum
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1151,7 +1170,7 @@ type gRPCResumableBidiWriteBufferSender struct {
|
||||
sendCRC32C bool
|
||||
disableAutoChecksum bool
|
||||
objectAttrs *ObjectAttrs
|
||||
fullObjectChecksum func() uint32
|
||||
fullObjectChecksum func() *uint32
|
||||
|
||||
streamErr error
|
||||
}
|
||||
@@ -1168,8 +1187,9 @@ func (w *gRPCWriter) newGRPCResumableBidiWriteBufferSender() *gRPCResumableBidiW
|
||||
sendCRC32C: w.sendCRC32C,
|
||||
disableAutoChecksum: w.disableAutoChecksum,
|
||||
objectAttrs: w.attrs,
|
||||
fullObjectChecksum: func() uint32 {
|
||||
return w.fullObjectChecksum
|
||||
fullObjectChecksum: func() *uint32 {
|
||||
checksum := w.fullObjectChecksum
|
||||
return &checksum
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1299,7 +1319,7 @@ type gRPCAppendBidiWriteBufferSender struct {
|
||||
sendCRC32C bool
|
||||
disableAutoChecksum bool
|
||||
objectAttrs *ObjectAttrs
|
||||
fullObjectChecksum func() uint32
|
||||
fullObjectChecksum func() *uint32
|
||||
|
||||
takeoverWriter bool
|
||||
|
||||
@@ -1323,8 +1343,12 @@ func (w *gRPCWriter) newGRPCAppendableObjectBufferSender() *gRPCAppendBidiWriteB
|
||||
sendCRC32C: w.sendCRC32C,
|
||||
disableAutoChecksum: w.disableAutoChecksum,
|
||||
objectAttrs: w.attrs,
|
||||
fullObjectChecksum: func() uint32 {
|
||||
return w.fullObjectChecksum
|
||||
fullObjectChecksum: func() *uint32 {
|
||||
if !w.sendAppendFinalCRC32C {
|
||||
return nil
|
||||
}
|
||||
checksum := w.appendFinalCRC32C
|
||||
return &checksum
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1439,8 +1463,12 @@ func (w *gRPCWriter) newGRPCAppendTakeoverWriteBufferSender() *gRPCAppendTakeove
|
||||
sendCRC32C: w.sendCRC32C,
|
||||
disableAutoChecksum: w.disableAutoChecksum,
|
||||
objectAttrs: w.attrs,
|
||||
fullObjectChecksum: func() uint32 {
|
||||
return w.fullObjectChecksum
|
||||
fullObjectChecksum: func() *uint32 {
|
||||
if !w.sendAppendFinalCRC32C {
|
||||
return nil
|
||||
}
|
||||
checksum := w.appendFinalCRC32C
|
||||
return &checksum
|
||||
},
|
||||
},
|
||||
takeoverReported: false,
|
||||
@@ -1582,7 +1610,7 @@ func (s *gRPCAppendBidiWriteBufferSender) send(stream storagepb.Storage_BidiWrit
|
||||
fullObjectChecksum: s.fullObjectChecksum,
|
||||
disableAutoChecksum: s.disableAutoChecksum,
|
||||
finishWrite: finalizeObject,
|
||||
takeoverWriter: s.takeoverWriter,
|
||||
append: true,
|
||||
})
|
||||
req := bidiWriteObjectRequest(r, bufChecksum, objectChecksums)
|
||||
if sendFirstMessage {
|
||||
|
||||
153
vendor/cloud.google.com/go/storage/http_client.go
generated
vendored
153
vendor/cloud.google.com/go/storage/http_client.go
generated
vendored
@@ -45,8 +45,6 @@ import (
|
||||
|
||||
// httpStorageClient is the HTTP-JSON API implementation of the transport-agnostic
|
||||
// storageClient interface.
|
||||
//
|
||||
// TODO(b/498422946): Add client feature tracker in HTTP client.
|
||||
type httpStorageClient struct {
|
||||
creds *auth.Credentials
|
||||
hc *http.Client
|
||||
@@ -56,11 +54,17 @@ type httpStorageClient struct {
|
||||
settings *settings
|
||||
config *storageConfig
|
||||
dynamicReadReqStallTimeout *bucketDelayManager
|
||||
metrics *clientMetrics
|
||||
metricsCleanup func()
|
||||
|
||||
// configFeatureAttributes tracks client-level features that are enabled for this
|
||||
// client instance.
|
||||
configFeatureAttributes uint32
|
||||
}
|
||||
|
||||
// newHTTPStorageClient initializes a new storageClient that uses the HTTP-JSON
|
||||
// Storage API.
|
||||
func newHTTPStorageClient(ctx context.Context, opts ...storageOption) (storageClient, error) {
|
||||
func newHTTPStorageClient(ctx context.Context, opts ...storageOption) (client storageClient, err error) {
|
||||
s := initSettings(opts...)
|
||||
o := s.clientOption
|
||||
config := newStorageConfig(o...)
|
||||
@@ -119,8 +123,50 @@ func newHTTPStorageClient(ctx context.Context, opts ...storageOption) (storageCl
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("dialing: %w", err)
|
||||
}
|
||||
|
||||
var clientMetrics *clientMetrics
|
||||
var metricsCleanup func()
|
||||
if isOtelMetricsEnabled(&config) {
|
||||
var project string
|
||||
if creds != nil {
|
||||
project, _ = creds.ProjectID(ctx)
|
||||
}
|
||||
clientMetrics, metricsCleanup = initClientMetrics(ctx, project, &config)
|
||||
}
|
||||
if metricsCleanup != nil {
|
||||
defer func() {
|
||||
if err != nil {
|
||||
metricsCleanup()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Clone the http.Client to avoid modifying the original one if it was provided by the user.
|
||||
hcClone := *hc
|
||||
c := &httpStorageClient{
|
||||
creds: creds,
|
||||
hc: &hcClone,
|
||||
settings: s,
|
||||
config: &config,
|
||||
metrics: clientMetrics,
|
||||
metricsCleanup: metricsCleanup,
|
||||
}
|
||||
|
||||
// Wrap transport to inject tracking headers and metrics.
|
||||
transport := hc.Transport
|
||||
if clientMetrics != nil {
|
||||
transport = &metricsRoundTripper{
|
||||
base: transport,
|
||||
metrics: clientMetrics,
|
||||
}
|
||||
}
|
||||
hcClone.Transport = &trackingTransport{
|
||||
base: transport,
|
||||
features: c.configFeatureAttributes,
|
||||
}
|
||||
|
||||
// RawService should be created with the chosen endpoint to take account of user override.
|
||||
rawService, err := raw.NewService(ctx, option.WithEndpoint(ep), option.WithHTTPClient(hc))
|
||||
rawService, err := raw.NewService(ctx, option.WithEndpoint(ep), option.WithHTTPClient(c.hc))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("storage client: %w", err)
|
||||
}
|
||||
@@ -144,23 +190,59 @@ func newHTTPStorageClient(ctx context.Context, opts ...storageOption) (storageCl
|
||||
}
|
||||
}
|
||||
|
||||
return &httpStorageClient{
|
||||
creds: creds,
|
||||
hc: hc,
|
||||
xmlHost: u.Host,
|
||||
raw: rawService,
|
||||
scheme: u.Scheme,
|
||||
settings: s,
|
||||
config: &config,
|
||||
dynamicReadReqStallTimeout: bd,
|
||||
}, nil
|
||||
c.xmlHost = u.Host
|
||||
c.raw = rawService
|
||||
c.scheme = u.Scheme
|
||||
c.dynamicReadReqStallTimeout = bd
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (c *httpStorageClient) Close() error {
|
||||
c.hc.CloseIdleConnections()
|
||||
if c.metricsCleanup != nil {
|
||||
c.metricsCleanup()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// trackingTransport wraps an http.RoundTripper to inject feature tracking headers.
|
||||
type trackingTransport struct {
|
||||
base http.RoundTripper
|
||||
features uint32
|
||||
}
|
||||
|
||||
func (t *trackingTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
baseRT := t.base
|
||||
if baseRT == nil {
|
||||
baseRT = http.DefaultTransport
|
||||
}
|
||||
features := t.features | featureAttributes(req.Context())
|
||||
// Merge all existing headers for this key.
|
||||
features |= mergeFeatureAttributes(req.Header.Values(featureTrackerHeaderName))
|
||||
if features > 0 {
|
||||
// Clone the request to avoid modifying the original one.
|
||||
clonedReq := req.Clone(req.Context())
|
||||
clonedReq.Header.Set(featureTrackerHeaderName, encodeUint32(features))
|
||||
return baseRT.RoundTrip(clonedReq)
|
||||
}
|
||||
|
||||
return baseRT.RoundTrip(req)
|
||||
}
|
||||
|
||||
func (t *trackingTransport) CloseIdleConnections() {
|
||||
type closeIdler interface {
|
||||
CloseIdleConnections()
|
||||
}
|
||||
base := t.base
|
||||
if base == nil {
|
||||
base = http.DefaultTransport
|
||||
}
|
||||
if tr, ok := base.(closeIdler); ok {
|
||||
tr.CloseIdleConnections()
|
||||
}
|
||||
}
|
||||
|
||||
// Top-level methods.
|
||||
|
||||
func (c *httpStorageClient) GetServiceAccount(ctx context.Context, project string, opts ...storageOption) (string, error) {
|
||||
@@ -222,6 +304,8 @@ func (c *httpStorageClient) ListBuckets(ctx context.Context, project string, opt
|
||||
}
|
||||
|
||||
fetch := func(pageSize int, pageToken string) (token string, err error) {
|
||||
ctx, record := startMetricsOp(it.ctx, "ListBuckets", true)
|
||||
defer func() { record(err) }()
|
||||
req := c.raw.Buckets.List(it.projectID)
|
||||
req.Projection("full")
|
||||
req.Prefix(it.Prefix)
|
||||
@@ -231,15 +315,16 @@ func (c *httpStorageClient) ListBuckets(ctx context.Context, project string, opt
|
||||
req.MaxResults(int64(pageSize))
|
||||
}
|
||||
var resp *raw.Buckets
|
||||
err = run(it.ctx, func(ctx context.Context) error {
|
||||
err = run(ctx, func(ctx context.Context) error {
|
||||
resp, err = req.Context(ctx).Do()
|
||||
return err
|
||||
}, s.retry, s.idempotent)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var b *BucketAttrs
|
||||
for _, item := range resp.Items {
|
||||
b, err := newBucket(item)
|
||||
b, err = newBucket(item)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -348,6 +433,8 @@ func (c *httpStorageClient) ListObjects(ctx context.Context, bucket string, q *Q
|
||||
}
|
||||
fetch := func(pageSize int, pageToken string) (string, error) {
|
||||
var err error
|
||||
ctx, record := startMetricsOp(it.ctx, "ListObjects", true)
|
||||
defer func() { record(err) }()
|
||||
// Add trace span around List API call within the fetch.
|
||||
ctx, _ = startSpan(ctx, "httpStorageClient.ObjectsListCall")
|
||||
defer func() { endSpan(ctx, err) }()
|
||||
@@ -385,7 +472,7 @@ func (c *httpStorageClient) ListObjects(ctx context.Context, bucket string, q *Q
|
||||
req.MaxResults(int64(pageSize))
|
||||
}
|
||||
var resp *raw.Objects
|
||||
err = run(it.ctx, func(ctx context.Context) error {
|
||||
err = run(ctx, func(ctx context.Context) error {
|
||||
resp, err = req.Context(ctx).Do()
|
||||
return err
|
||||
}, s.retry, s.idempotent, withOperation("ListObjects"), withObject(it.query.Prefix), withBucket(bucket))
|
||||
@@ -767,7 +854,9 @@ func (c *httpStorageClient) UpdateObjectACL(ctx context.Context, bucket, object
|
||||
|
||||
func (c *httpStorageClient) ComposeObject(ctx context.Context, req *composeObjectRequest, opts ...storageOption) (*ObjectAttrs, error) {
|
||||
s := callSettings(c.settings, opts...)
|
||||
rawReq := &raw.ComposeRequest{}
|
||||
rawReq := &raw.ComposeRequest{
|
||||
DeleteSourceObjects: req.deleteSourceObjects,
|
||||
}
|
||||
// Compose requires a non-empty Destination, so we always set it,
|
||||
// even if the caller-provided ObjectAttrs is the zero value.
|
||||
rawReq.Destination = req.dstObject.attrs.toRawObject(req.dstBucket)
|
||||
@@ -1031,6 +1120,9 @@ func (hiw *httpInternalWriter) Flush() (int64, error) {
|
||||
return 0, errors.New("Writer.Flush is only supported for gRPC-based clients")
|
||||
}
|
||||
|
||||
// Not supported on HTTP Client as this is for setting CRC on appendable objects.
|
||||
func (hiw *httpInternalWriter) setAppendFinalCRC32C(sendAppendFinalCRC32C bool, c uint32) {}
|
||||
|
||||
func (c *httpStorageClient) OpenWriter(params *openWriterParams, opts ...storageOption) (internalWriter, error) {
|
||||
if params.append {
|
||||
return nil, errors.New("storage: append not supported on HTTP Client; use gRPC")
|
||||
@@ -1235,6 +1327,8 @@ func (c *httpStorageClient) ListHMACKeys(ctx context.Context, project, serviceAc
|
||||
retry: s.retry,
|
||||
}
|
||||
fetch := func(pageSize int, pageToken string) (token string, err error) {
|
||||
ctx, record := startMetricsOp(it.ctx, "ListHMACKeys", true)
|
||||
defer func() { record(err) }()
|
||||
call := c.raw.Projects.HmacKeys.List(project)
|
||||
if pageToken != "" {
|
||||
call = call.PageToken(pageToken)
|
||||
@@ -1253,7 +1347,7 @@ func (c *httpStorageClient) ListHMACKeys(ctx context.Context, project, serviceAc
|
||||
}
|
||||
|
||||
var resp *raw.HmacKeysMetadata
|
||||
err = run(it.ctx, func(ctx context.Context) error {
|
||||
err = run(ctx, func(ctx context.Context) error {
|
||||
resp, err = call.Context(ctx).Do()
|
||||
return err
|
||||
}, s.retry, s.idempotent)
|
||||
@@ -1261,11 +1355,12 @@ func (c *httpStorageClient) ListHMACKeys(ctx context.Context, project, serviceAc
|
||||
return "", err
|
||||
}
|
||||
|
||||
var hkey *HMACKey
|
||||
for _, metadata := range resp.Items {
|
||||
hk := &raw.HmacKey{
|
||||
Metadata: metadata,
|
||||
}
|
||||
hkey, err := toHMACKeyFromRaw(hk, true)
|
||||
hkey, err = toHMACKeyFromRaw(hk, true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -1406,7 +1501,7 @@ func (r *httpReader) Read(p []byte) (int, error) {
|
||||
n += m
|
||||
r.seen += int64(m)
|
||||
if r.checkCRC {
|
||||
r.gotCRC = crc32.Update(r.gotCRC, crc32cTable, p[:n])
|
||||
r.gotCRC = crc32.Update(r.gotCRC, crc32cTable, p[n-m:n])
|
||||
}
|
||||
if err == nil {
|
||||
return n, nil
|
||||
@@ -1535,7 +1630,7 @@ func readerReopen(ctx context.Context, header http.Header, params *newRangeReade
|
||||
params.gen = gen64
|
||||
}
|
||||
return nil
|
||||
}, s.retry, s.idempotent)
|
||||
}, s.retry, s.idempotent, withOperation("ReadObject"), withBucket(params.bucket), withObject(params.object))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1582,6 +1677,7 @@ func parseReadResponse(res *http.Response, params *newRangeReaderParams, reopen
|
||||
}
|
||||
|
||||
// Check the CRC iff all of the following hold:
|
||||
// - The user did not disable CRC check.
|
||||
// - We asked for content (length != 0).
|
||||
// - We got all the content (status != PartialContent).
|
||||
// - The server sent a CRC header.
|
||||
@@ -1591,7 +1687,7 @@ func parseReadResponse(res *http.Response, params *newRangeReaderParams, reopen
|
||||
// computes it on the compressed contents, but we compute it on the
|
||||
// uncompressed contents.
|
||||
crc, checkCRC = parseCRC32c(res)
|
||||
if params.length == 0 || res.StatusCode == http.StatusPartialContent || res.Uncompressed || uncompressedByServer(res) {
|
||||
if params.disableCRCCheck || params.length == 0 || res.StatusCode == http.StatusPartialContent || res.Uncompressed || uncompressedByServer(res) {
|
||||
checkCRC = false
|
||||
}
|
||||
|
||||
@@ -1652,6 +1748,8 @@ func parseReadResponse(res *http.Response, params *newRangeReaderParams, reopen
|
||||
wantCRC: crc,
|
||||
checkCRC: checkCRC,
|
||||
},
|
||||
bucket: params.bucket,
|
||||
object: params.object,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -1681,3 +1779,12 @@ func setHeadersFromCtx(ctx context.Context, header http.Header) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *httpStorageClient) fetchBucketMetadata(ctx context.Context, bucket string) (string, string, error) {
|
||||
resp, err := c.raw.Buckets.Get(bucket).Projection("noAcl").Context(ctx).Do()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
resource, location := getMetadataFromAttrs(resp.Location, resp.LocationType, strconv.FormatUint(resp.ProjectNumber, 10), bucket)
|
||||
return resource, location, nil
|
||||
}
|
||||
|
||||
8
vendor/cloud.google.com/go/storage/iam.go
generated
vendored
8
vendor/cloud.google.com/go/storage/iam.go
generated
vendored
@@ -29,6 +29,7 @@ func (b *BucketHandle) IAM() *iam.Handle {
|
||||
userProject: b.userProject,
|
||||
retry: b.retry,
|
||||
client: b.c,
|
||||
bucket: b.name,
|
||||
}, b.name)
|
||||
}
|
||||
|
||||
@@ -37,6 +38,7 @@ type iamClient struct {
|
||||
userProject string
|
||||
retry *retryConfig
|
||||
client *Client
|
||||
bucket string
|
||||
}
|
||||
|
||||
func (c *iamClient) Get(ctx context.Context, resource string) (p *iampb.Policy, err error) {
|
||||
@@ -44,7 +46,7 @@ func (c *iamClient) Get(ctx context.Context, resource string) (p *iampb.Policy,
|
||||
}
|
||||
|
||||
func (c *iamClient) GetWithVersion(ctx context.Context, resource string, requestedPolicyVersion int32) (p *iampb.Policy, err error) {
|
||||
ctx, _ = startSpan(ctx, "storage.IAM.Get")
|
||||
ctx, _ = startSpanWithBucket(ctx, c.client, c.bucket, "storage.IAM.Get")
|
||||
defer func() { endSpan(ctx, err) }()
|
||||
|
||||
o := makeStorageOpts(true, c.retry, c.userProject)
|
||||
@@ -52,7 +54,7 @@ func (c *iamClient) GetWithVersion(ctx context.Context, resource string, request
|
||||
}
|
||||
|
||||
func (c *iamClient) Set(ctx context.Context, resource string, p *iampb.Policy) (err error) {
|
||||
ctx, _ = startSpan(ctx, "storage.IAM.Set")
|
||||
ctx, _ = startSpanWithBucket(ctx, c.client, c.bucket, "storage.IAM.Set")
|
||||
defer func() { endSpan(ctx, err) }()
|
||||
|
||||
isIdempotent := len(p.Etag) > 0
|
||||
@@ -61,7 +63,7 @@ func (c *iamClient) Set(ctx context.Context, resource string, p *iampb.Policy) (
|
||||
}
|
||||
|
||||
func (c *iamClient) Test(ctx context.Context, resource string, perms []string) (permissions []string, err error) {
|
||||
ctx, _ = startSpan(ctx, "storage.IAM.Test")
|
||||
ctx, _ = startSpanWithBucket(ctx, c.client, c.bucket, "storage.IAM.Test")
|
||||
defer func() { endSpan(ctx, err) }()
|
||||
|
||||
o := makeStorageOpts(true, c.retry, c.userProject)
|
||||
|
||||
4
vendor/cloud.google.com/go/storage/internal/apiv2/storage_client.go
generated
vendored
4
vendor/cloud.google.com/go/storage/internal/apiv2/storage_client.go
generated
vendored
@@ -460,7 +460,7 @@ type Client struct {
|
||||
|
||||
// Wrapper methods routed to the internal client.
|
||||
|
||||
// Close closes the connection to the API service. The user should invoke this when
|
||||
// Close closes the connection to the API service. **Always** call Close() when
|
||||
// the client is no longer required.
|
||||
func (c *Client) Close() error {
|
||||
return c.internalClient.Close()
|
||||
@@ -1079,7 +1079,7 @@ func (c *gRPCClient) setGoogleClientInfo(keyval ...string) {
|
||||
}
|
||||
}
|
||||
|
||||
// Close closes the connection to the API service. The user should invoke this when
|
||||
// Close closes the connection to the API service. **Always** call Close() when
|
||||
// the client is no longer required.
|
||||
func (c *gRPCClient) Close() error {
|
||||
return c.connPool.Close()
|
||||
|
||||
4
vendor/cloud.google.com/go/storage/internal/experimental.go
generated
vendored
4
vendor/cloud.google.com/go/storage/internal/experimental.go
generated
vendored
@@ -47,4 +47,8 @@ var (
|
||||
// It sets the gRPC client to use direct path connectivity for all requests and may fail
|
||||
// if direct path connectivity cannot be established for a request.
|
||||
WithDirectConnectivityEnforced any // func() option.ClientOption
|
||||
|
||||
// WithOtelMetrics is a function which is implemented by the storage package.
|
||||
// It enables client-side OpenTelemetry metrics.
|
||||
WithOtelMetrics any // func() option.ClientOption
|
||||
)
|
||||
|
||||
2
vendor/cloud.google.com/go/storage/internal/version.go
generated
vendored
2
vendor/cloud.google.com/go/storage/internal/version.go
generated
vendored
@@ -17,4 +17,4 @@
|
||||
package internal
|
||||
|
||||
// Version is the current tagged release of the library.
|
||||
const Version = "1.62.3"
|
||||
const Version = "1.64.0"
|
||||
|
||||
15
vendor/cloud.google.com/go/storage/invoke.go
generated
vendored
15
vendor/cloud.google.com/go/storage/invoke.go
generated
vendored
@@ -246,3 +246,18 @@ func ShouldRetry(err error) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isError(err error, httpErrorCode int, grpcErrorCode codes.Code) bool {
|
||||
var e *googleapi.Error
|
||||
if errors.As(err, &e) {
|
||||
if e.Code == httpErrorCode {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if s, ok := status.FromError(err); ok {
|
||||
if s.Code() == grpcErrorCode {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
98
vendor/cloud.google.com/go/storage/lru.go
generated
vendored
Normal file
98
vendor/cloud.google.com/go/storage/lru.go
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
// Copyright 2026 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package storage
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
)
|
||||
|
||||
// lruCache is a generic Least Recently Used cache. It is not thread-safe.
|
||||
type lruCache[K comparable, V any] struct {
|
||||
entries map[K]*list.Element
|
||||
evictList *list.List
|
||||
limit int
|
||||
}
|
||||
|
||||
type cacheEntry[K comparable, V any] struct {
|
||||
key K
|
||||
value V
|
||||
}
|
||||
|
||||
func newLRUCache[K comparable, V any](limit int) *lruCache[K, V] {
|
||||
return &lruCache[K, V]{
|
||||
entries: make(map[K]*list.Element),
|
||||
evictList: list.New(),
|
||||
limit: limit,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *lruCache[K, V]) get(key K) (V, bool) {
|
||||
if c == nil {
|
||||
var zero V
|
||||
return zero, false
|
||||
}
|
||||
|
||||
if elem, ok := c.entries[key]; ok {
|
||||
c.evictList.MoveToFront(elem)
|
||||
return elem.Value.(*cacheEntry[K, V]).value, true
|
||||
}
|
||||
var zero V
|
||||
return zero, false
|
||||
}
|
||||
|
||||
func (c *lruCache[K, V]) put(key K, val V) {
|
||||
if c == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// If element already exists, update the value and promote it.
|
||||
if elem, ok := c.entries[key]; ok {
|
||||
c.evictList.MoveToFront(elem)
|
||||
elem.Value.(*cacheEntry[K, V]).value = val
|
||||
return
|
||||
}
|
||||
|
||||
// Add new element to front
|
||||
elem := c.evictList.PushFront(&cacheEntry[K, V]{key: key, value: val})
|
||||
c.entries[key] = elem
|
||||
|
||||
// Evict oldest element if limit exceeded.
|
||||
if c.evictList.Len() > c.limit {
|
||||
c.removeOldest()
|
||||
}
|
||||
}
|
||||
|
||||
func (c *lruCache[K, V]) evict(key K) {
|
||||
if c == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if elem, ok := c.entries[key]; ok {
|
||||
c.removeElement(elem)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *lruCache[K, V]) removeOldest() {
|
||||
elem := c.evictList.Back()
|
||||
if elem != nil {
|
||||
c.removeElement(elem)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *lruCache[K, V]) removeElement(elem *list.Element) {
|
||||
c.evictList.Remove(elem)
|
||||
kv := elem.Value.(*cacheEntry[K, V])
|
||||
delete(c.entries, kv.key)
|
||||
}
|
||||
1141
vendor/cloud.google.com/go/storage/metrics.go
generated
vendored
Normal file
1141
vendor/cloud.google.com/go/storage/metrics.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6
vendor/cloud.google.com/go/storage/notifications.go
generated
vendored
6
vendor/cloud.google.com/go/storage/notifications.go
generated
vendored
@@ -120,7 +120,7 @@ func toRawNotification(n *Notification) *raw.Notification {
|
||||
// returned Notification's ID can be used to refer to it.
|
||||
// Note: gRPC is not supported.
|
||||
func (b *BucketHandle) AddNotification(ctx context.Context, n *Notification) (ret *Notification, err error) {
|
||||
ctx, _ = startSpan(ctx, "Bucket.AddNotification")
|
||||
ctx, _ = startSpanWithBucket(ctx, b.c, b.name, "Bucket.AddNotification")
|
||||
defer func() { endSpan(ctx, err) }()
|
||||
|
||||
if n.ID != "" {
|
||||
@@ -142,7 +142,7 @@ func (b *BucketHandle) AddNotification(ctx context.Context, n *Notification) (re
|
||||
// indexed by notification ID.
|
||||
// Note: gRPC is not supported.
|
||||
func (b *BucketHandle) Notifications(ctx context.Context) (n map[string]*Notification, err error) {
|
||||
ctx, _ = startSpan(ctx, "Bucket.Notifications")
|
||||
ctx, _ = startSpanWithBucket(ctx, b.c, b.name, "Bucket.Notifications")
|
||||
defer func() { endSpan(ctx, err) }()
|
||||
|
||||
opts := makeStorageOpts(true, b.retry, b.userProject)
|
||||
@@ -161,7 +161,7 @@ func notificationsToMap(rns []*raw.Notification) map[string]*Notification {
|
||||
// DeleteNotification deletes the notification with the given ID.
|
||||
// Note: gRPC is not supported.
|
||||
func (b *BucketHandle) DeleteNotification(ctx context.Context, id string) (err error) {
|
||||
ctx, _ = startSpan(ctx, "Bucket.DeleteNotification")
|
||||
ctx, _ = startSpanWithBucket(ctx, b.c, b.name, "Bucket.DeleteNotification")
|
||||
defer func() { endSpan(ctx, err) }()
|
||||
|
||||
opts := makeStorageOpts(true, b.retry, b.userProject)
|
||||
|
||||
14
vendor/cloud.google.com/go/storage/option.go
generated
vendored
14
vendor/cloud.google.com/go/storage/option.go
generated
vendored
@@ -44,6 +44,7 @@ func init() {
|
||||
storageinternal.WithGRPCBidiReads = withGRPCBidiReads
|
||||
storageinternal.WithZonalBucketAPIs = withZonalBucketAPIs
|
||||
storageinternal.WithDirectConnectivityEnforced = withDirectConnectivityEnforced
|
||||
storageinternal.WithOtelMetrics = withOtelMetrics
|
||||
}
|
||||
|
||||
// getDynamicReadReqIncreaseRateFromEnv returns the value set in the env variable.
|
||||
@@ -81,6 +82,7 @@ type storageConfig struct {
|
||||
useJSONforReads bool
|
||||
readAPIWasSet bool
|
||||
disableClientMetrics bool
|
||||
enableOtelMetrics bool
|
||||
metricExporter *metric.Exporter
|
||||
metricInterval time.Duration
|
||||
meterProvider *metric.MeterProvider
|
||||
@@ -300,3 +302,15 @@ func (w *withZonalBucketAPIsConfig) ApplyStorageOpt(config *storageConfig) {
|
||||
config.grpcAppendableUploads = true
|
||||
config.grpcBidiReads = true
|
||||
}
|
||||
|
||||
func withOtelMetrics() option.ClientOption {
|
||||
return &withOtelMetricsConfig{}
|
||||
}
|
||||
|
||||
type withOtelMetricsConfig struct {
|
||||
internaloption.EmbeddableAdapter
|
||||
}
|
||||
|
||||
func (w *withOtelMetricsConfig) ApplyStorageOpt(c *storageConfig) {
|
||||
c.enableOtelMetrics = true
|
||||
}
|
||||
|
||||
5
vendor/cloud.google.com/go/storage/pcu.go
generated
vendored
5
vendor/cloud.google.com/go/storage/pcu.go
generated
vendored
@@ -47,6 +47,8 @@ const (
|
||||
//
|
||||
// **Note:** This feature is currently experimental and its API surface may change
|
||||
// in future releases. It is not yet recommended for production use.
|
||||
//
|
||||
// TODO(b/521239530): Add option to delete source parts after compose operation and remove cleanup logic.
|
||||
type ParallelUploadConfig struct {
|
||||
|
||||
// PartSize is the size of each part to be uploaded in parallel.
|
||||
@@ -182,7 +184,8 @@ func (w *Writer) initPCU(ctx context.Context) error {
|
||||
// Track PCU operations using client feature tracking header.
|
||||
ctx = addFeatureAttributes(ctx, featurePCU)
|
||||
|
||||
pCtx, cancel := context.WithCancel(ctx)
|
||||
bgCtx := contextWithoutMetrics(ctx)
|
||||
pCtx, cancel := context.WithCancel(bgCtx)
|
||||
|
||||
state := &pcuState{
|
||||
ctx: pCtx,
|
||||
|
||||
120
vendor/cloud.google.com/go/storage/reader.go
generated
vendored
120
vendor/cloud.google.com/go/storage/reader.go
generated
vendored
@@ -19,10 +19,15 @@ import (
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
)
|
||||
|
||||
var crc32cTable = crc32.MakeTable(crc32.Castagnoli)
|
||||
@@ -90,8 +95,8 @@ type ReaderObjectAttrs struct {
|
||||
// when calling [NewClient]. This ensures consistency with other client
|
||||
// operations, which all use JSON. JSON will become the default in a future
|
||||
// release.
|
||||
func (o *ObjectHandle) NewReader(ctx context.Context) (*Reader, error) {
|
||||
return o.NewRangeReader(ctx, 0, -1)
|
||||
func (o *ObjectHandle) NewReader(ctx context.Context, opts ...ReaderOption) (*Reader, error) {
|
||||
return o.NewRangeReader(ctx, 0, -1, opts...)
|
||||
}
|
||||
|
||||
// NewRangeReader reads part of an object, reading at most length bytes
|
||||
@@ -111,10 +116,10 @@ func (o *ObjectHandle) NewReader(ctx context.Context) (*Reader, error) {
|
||||
// when calling [NewClient]. This ensures consistency with other client
|
||||
// operations, which all use JSON. JSON will become the default in a future
|
||||
// release.
|
||||
func (o *ObjectHandle) NewRangeReader(ctx context.Context, offset, length int64) (r *Reader, err error) {
|
||||
func (o *ObjectHandle) NewRangeReader(ctx context.Context, offset, length int64, opts ...ReaderOption) (r *Reader, err error) {
|
||||
// This span covers the life of the reader. It is closed via the context
|
||||
// in Reader.Close.
|
||||
ctx, _ = startSpan(ctx, "Object.Reader")
|
||||
ctx, _ = startSpanWithBucket(ctx, o.c, o.bucket, "Object.Reader")
|
||||
defer func() { endSpan(ctx, err) }()
|
||||
|
||||
if err := o.validate(); err != nil {
|
||||
@@ -129,7 +134,7 @@ func (o *ObjectHandle) NewRangeReader(ctx context.Context, offset, length int64)
|
||||
}
|
||||
}
|
||||
|
||||
opts := makeStorageOpts(true, o.retry, o.userProject)
|
||||
storageOpts := makeStorageOpts(true, o.retry, o.userProject)
|
||||
|
||||
params := &newRangeReaderParams{
|
||||
bucket: o.bucket,
|
||||
@@ -142,8 +147,11 @@ func (o *ObjectHandle) NewRangeReader(ctx context.Context, offset, length int64)
|
||||
readCompressed: o.readCompressed,
|
||||
handle: &o.readHandle,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt.apply(params)
|
||||
}
|
||||
|
||||
r, err = o.c.tc.NewRangeReader(ctx, params, opts...)
|
||||
r, err = o.c.tc.NewRangeReader(ctx, params, storageOpts...)
|
||||
|
||||
// Pass the context so that the span can be closed in Reader.Close, or close the
|
||||
// span now if there is an error.
|
||||
@@ -154,6 +162,11 @@ func (o *ObjectHandle) NewRangeReader(ctx context.Context, offset, length int64)
|
||||
return r, err
|
||||
}
|
||||
|
||||
// ReaderOption is an option for NewReader or NewRangeReader.
|
||||
type ReaderOption interface {
|
||||
apply(*newRangeReaderParams)
|
||||
}
|
||||
|
||||
// MRDOption is an option for MultiRangeDownloader.
|
||||
type MRDOption interface {
|
||||
apply(*newMultiRangeDownloaderParams)
|
||||
@@ -221,6 +234,28 @@ func WithTargetPendingBytes(c int) MRDOption {
|
||||
return targetPendingBytes(c)
|
||||
}
|
||||
|
||||
type disableMRDReadChecksum struct{}
|
||||
|
||||
func (c disableMRDReadChecksum) apply(params *newMultiRangeDownloaderParams) {
|
||||
params.disableMRDReadChecksum = true
|
||||
}
|
||||
|
||||
// WithDisableMRDReadChecksum returns an MRDOption that disables read checksum validation for the MRD range downloads.
|
||||
func WithDisableMRDReadChecksum() MRDOption {
|
||||
return disableMRDReadChecksum{}
|
||||
}
|
||||
|
||||
type disableReaderChecksum struct{}
|
||||
|
||||
func (c disableReaderChecksum) apply(params *newRangeReaderParams) {
|
||||
params.disableCRCCheck = true
|
||||
}
|
||||
|
||||
// WithDisableReaderChecksum returns a ReaderOption that disables read checksum validation.
|
||||
func WithDisableReaderChecksum() ReaderOption {
|
||||
return disableReaderChecksum{}
|
||||
}
|
||||
|
||||
// NewMultiRangeDownloader creates a multi-range reader for an object.
|
||||
// Must be called on a gRPC client created using [NewGRPCClient].
|
||||
//
|
||||
@@ -235,7 +270,7 @@ func (o *ObjectHandle) NewMultiRangeDownloader(ctx context.Context, opts ...MRDO
|
||||
// This span covers the life of the MRD. It is closed via the context
|
||||
// in MultiRangeDownloader.Close.
|
||||
var spanCtx context.Context
|
||||
spanCtx, _ = startSpan(ctx, "Object.MultiRangeDownloader")
|
||||
spanCtx, _ = startSpanWithBucket(ctx, o.c, o.bucket, "Object.MultiRangeDownloader")
|
||||
defer func() {
|
||||
if err != nil {
|
||||
endSpan(spanCtx, err)
|
||||
@@ -339,31 +374,61 @@ var emptyBody = io.NopCloser(strings.NewReader(""))
|
||||
// the stored CRC, returning an error from Read if there is a mismatch. This integrity check
|
||||
// is skipped if transcoding occurs. See https://cloud.google.com/storage/docs/transcoding.
|
||||
type Reader struct {
|
||||
// remain must be the first field in the struct to guarantee 64-bit
|
||||
// alignment on 32-bit architectures for atomic operations.
|
||||
remain int64
|
||||
bytesRead int64 // Cumulative bytes read for response size metric.
|
||||
|
||||
Attrs ReaderObjectAttrs
|
||||
objectMetadata *map[string]string
|
||||
|
||||
seen, remain, size int64
|
||||
checkCRC bool // Did we check the CRC? This is now only used by tests.
|
||||
seen, size int64
|
||||
checkCRC bool // Did we check the CRC? This is now only used by tests.
|
||||
|
||||
reader io.ReadCloser
|
||||
ctx context.Context
|
||||
mu sync.Mutex
|
||||
err error // Persistent error encountered during Read or WriteTo.
|
||||
handle *ReadHandle
|
||||
unfinalized bool
|
||||
|
||||
bucket string
|
||||
object string
|
||||
|
||||
metricsState *metricsState
|
||||
}
|
||||
|
||||
// Close closes the Reader. It must be called when done reading.
|
||||
func (r *Reader) Close() error {
|
||||
if !r.unfinalized && !r.Attrs.Decompressed {
|
||||
if rem := atomic.LoadInt64(&r.remain); rem < 0 {
|
||||
log.Printf("storage: received %d more bytes than requested from GCS for bucket %q, object %q", -rem, r.bucket, r.object)
|
||||
}
|
||||
}
|
||||
err := r.reader.Close()
|
||||
r.mu.Lock()
|
||||
if r.err != nil {
|
||||
err = r.err
|
||||
}
|
||||
r.mu.Unlock()
|
||||
|
||||
if r.metricsState != nil {
|
||||
if r.metricsState.metrics != nil {
|
||||
if total := atomic.SwapInt64(&r.bytesRead, 0); total > 0 {
|
||||
r.metricsState.metrics.responseBodySize.Record(r.ctx, total, metric.WithAttributes(attribute.String("rpc.method", "ReadObject")))
|
||||
}
|
||||
}
|
||||
if r.metricsState.record != nil {
|
||||
r.metricsState.record(err)
|
||||
}
|
||||
}
|
||||
endSpan(r.ctx, err)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *Reader) Read(p []byte) (int, error) {
|
||||
n, err := r.reader.Read(p)
|
||||
if r.remain != -1 {
|
||||
r.remain -= int64(n)
|
||||
}
|
||||
r.recordRead(int64(n), err)
|
||||
return n, err
|
||||
}
|
||||
|
||||
@@ -373,12 +438,26 @@ func (r *Reader) WriteTo(w io.Writer) (int64, error) {
|
||||
// This implicitly calls r.reader.WriteTo for gRPC only. JSON and XML don't have an
|
||||
// implementation of WriteTo.
|
||||
n, err := io.Copy(w, r.reader)
|
||||
if r.remain != -1 {
|
||||
r.remain -= int64(n)
|
||||
}
|
||||
r.recordRead(n, err)
|
||||
return n, err
|
||||
}
|
||||
|
||||
// recordRead updates remaining byte counts and metrics after a read operation,
|
||||
// and saves any persistent error encountered during Read or WriteTo.
|
||||
func (r *Reader) recordRead(n int64, err error) {
|
||||
if !r.unfinalized && !r.Attrs.Decompressed {
|
||||
atomic.AddInt64(&r.remain, -n)
|
||||
}
|
||||
if n > 0 {
|
||||
atomic.AddInt64(&r.bytesRead, n)
|
||||
}
|
||||
if err != nil && err != io.EOF {
|
||||
r.mu.Lock()
|
||||
r.err = err
|
||||
r.mu.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
// Size returns the size of the object in bytes.
|
||||
// The returned value is always the same and is not affected by
|
||||
// calls to Read or Close.
|
||||
@@ -392,10 +471,14 @@ func (r *Reader) Size() int64 {
|
||||
// Remain returns the number of bytes left to read, or -1 if unknown.
|
||||
// Unfinalized objects will return -1.
|
||||
func (r *Reader) Remain() int64 {
|
||||
if r.unfinalized {
|
||||
if r.unfinalized || r.Attrs.Decompressed {
|
||||
return -1
|
||||
}
|
||||
return r.remain
|
||||
rem := atomic.LoadInt64(&r.remain)
|
||||
if rem < 0 {
|
||||
return 0
|
||||
}
|
||||
return rem
|
||||
}
|
||||
|
||||
// ContentType returns the content type of the object.
|
||||
@@ -506,6 +589,9 @@ func (mrd *MultiRangeDownloader) Add(output io.Writer, offset, length int64, cal
|
||||
// it could lead to a deadlock.
|
||||
func (mrd *MultiRangeDownloader) Close() error {
|
||||
err := mrd.impl.close(nil)
|
||||
if state := metricsStateFromContext(mrd.impl.getSpanCtx()); state != nil && state.record != nil {
|
||||
state.record(err)
|
||||
}
|
||||
endSpan(mrd.impl.getSpanCtx(), err)
|
||||
return err
|
||||
}
|
||||
|
||||
61
vendor/cloud.google.com/go/storage/storage.go
generated
vendored
61
vendor/cloud.google.com/go/storage/storage.go
generated
vendored
@@ -127,6 +127,8 @@ type Client struct {
|
||||
|
||||
// Option to use gRRPC appendable upload API was set.
|
||||
grpcAppendableUploads bool
|
||||
|
||||
bucketMetadataCache *bucketMetadataCache
|
||||
}
|
||||
|
||||
// credsJSON returns the raw JSON of the Client's creds and true, or an empty slice
|
||||
@@ -224,14 +226,27 @@ func NewClient(ctx context.Context, opts ...option.ClientOption) (*Client, error
|
||||
return nil, fmt.Errorf("storage: %w", err)
|
||||
}
|
||||
|
||||
return &Client{
|
||||
var tcWrapped storageClient = tc
|
||||
if httpClient, ok := tc.(*httpStorageClient); ok && httpClient.metrics != nil {
|
||||
tcWrapped = &metricsStorageClient{
|
||||
storageClient: tc,
|
||||
metrics: httpClient.metrics,
|
||||
isHTTP: true,
|
||||
}
|
||||
}
|
||||
|
||||
c := &Client{
|
||||
hc: hc,
|
||||
raw: rawService,
|
||||
scheme: u.Scheme,
|
||||
xmlHost: u.Host,
|
||||
creds: creds,
|
||||
tc: tc,
|
||||
}, nil
|
||||
tc: tcWrapped,
|
||||
}
|
||||
if isACOEnabled() {
|
||||
c.bucketMetadataCache = newBucketMetadataCache(defaultBucketMetadataCacheLimit, c.tc)
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// NewGRPCClient creates a new Storage client using the gRPC transport and API.
|
||||
@@ -251,10 +266,22 @@ func NewGRPCClient(ctx context.Context, opts ...option.ClientOption) (*Client, e
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Client{
|
||||
tc: tc,
|
||||
var tcWrapped storageClient = tc
|
||||
if tc.metrics != nil {
|
||||
tcWrapped = &metricsStorageClient{
|
||||
storageClient: tc,
|
||||
metrics: tc.metrics,
|
||||
isHTTP: false,
|
||||
}
|
||||
}
|
||||
c := &Client{
|
||||
tc: tcWrapped,
|
||||
grpcAppendableUploads: tc.config.grpcAppendableUploads,
|
||||
}, nil
|
||||
}
|
||||
if isACOEnabled() {
|
||||
c.bucketMetadataCache = newBucketMetadataCache(defaultBucketMetadataCacheLimit, c.tc)
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// CheckDirectConnectivitySupported checks if gRPC direct connectivity
|
||||
@@ -321,6 +348,7 @@ func (c *Client) Close() error {
|
||||
c.hc = nil
|
||||
c.raw = nil
|
||||
c.creds = nil
|
||||
c.bucketMetadataCache = nil
|
||||
if c.tc != nil {
|
||||
return c.tc.Close()
|
||||
}
|
||||
@@ -1038,7 +1066,7 @@ func (o *ObjectHandle) Key(encryptionKey []byte) *ObjectHandle {
|
||||
// Attrs returns meta information about the object.
|
||||
// ErrObjectNotExist will be returned if the object is not found.
|
||||
func (o *ObjectHandle) Attrs(ctx context.Context) (attrs *ObjectAttrs, err error) {
|
||||
ctx, _ = startSpan(ctx, "Object.Attrs")
|
||||
ctx, _ = startSpanWithBucket(ctx, o.c, o.bucket, "Object.Attrs")
|
||||
defer func() { endSpan(ctx, err) }()
|
||||
|
||||
if err := o.validate(); err != nil {
|
||||
@@ -1052,7 +1080,7 @@ func (o *ObjectHandle) Attrs(ctx context.Context) (attrs *ObjectAttrs, err error
|
||||
// ObjectAttrsToUpdate docs for details on treatment of zero values.
|
||||
// ErrObjectNotExist will be returned if the object is not found.
|
||||
func (o *ObjectHandle) Update(ctx context.Context, uattrs ObjectAttrsToUpdate) (oa *ObjectAttrs, err error) {
|
||||
ctx, _ = startSpan(ctx, "Object.Update")
|
||||
ctx, _ = startSpanWithBucket(ctx, o.c, o.bucket, "Object.Update")
|
||||
defer func() { endSpan(ctx, err) }()
|
||||
|
||||
if err := o.validate(); err != nil {
|
||||
@@ -1130,7 +1158,7 @@ type ObjectAttrsToUpdate struct {
|
||||
|
||||
// Delete deletes the single specified object.
|
||||
func (o *ObjectHandle) Delete(ctx context.Context) (err error) {
|
||||
ctx, _ = startSpan(ctx, "Object.Delete")
|
||||
ctx, _ = startSpanWithBucket(ctx, o.c, o.bucket, "Object.Delete")
|
||||
defer func() { endSpan(ctx, err) }()
|
||||
if err := o.validate(); err != nil {
|
||||
return err
|
||||
@@ -1252,7 +1280,7 @@ type MoveObjectDestination struct {
|
||||
// It is the caller's responsibility to call Close when writing is done. To
|
||||
// stop writing without saving the data, cancel the context.
|
||||
func (o *ObjectHandle) NewWriter(ctx context.Context) *Writer {
|
||||
ctx, _ = startSpan(ctx, "Object.Writer")
|
||||
ctx, _ = startSpanWithBucket(ctx, o.c, o.bucket, "Object.Writer")
|
||||
return &Writer{
|
||||
ctx: ctx,
|
||||
o: o,
|
||||
@@ -1288,7 +1316,7 @@ func (o *ObjectHandle) NewWriter(ctx context.Context) *Writer {
|
||||
// objects which were created append semantics and not finalized.
|
||||
// This feature is in preview and is not yet available for general use.
|
||||
func (o *ObjectHandle) NewWriterFromAppendableObject(ctx context.Context, opts *AppendableWriterOpts) (*Writer, int64, error) {
|
||||
ctx, _ = startSpan(ctx, "Object.WriterFromAppendableObject")
|
||||
ctx, _ = startSpanWithBucket(ctx, o.c, o.bucket, "Object.WriterFromAppendableObject")
|
||||
if o.gen < 0 {
|
||||
return nil, 0, errors.New("storage: ObjectHandle.Generation must be set to use NewWriterFromAppendableObject")
|
||||
}
|
||||
@@ -1342,6 +1370,13 @@ type AppendableWriterOpts struct {
|
||||
ProgressFunc func(int64)
|
||||
// FinalizeOnClose: See Writer.FinalizeOnClose.
|
||||
FinalizeOnClose bool
|
||||
// DisableAutoChecksum: See Writer.DisableAutoChecksum.
|
||||
DisableAutoChecksum bool
|
||||
// SendCRC32C: See Writer.SendCRC32C.
|
||||
SendCRC32C bool
|
||||
// CRC32C of the whole object.
|
||||
// See Writer.CRC32C.
|
||||
CRC32C uint32
|
||||
}
|
||||
|
||||
func (opts *AppendableWriterOpts) apply(w *Writer) {
|
||||
@@ -1352,6 +1387,9 @@ func (opts *AppendableWriterOpts) apply(w *Writer) {
|
||||
w.ProgressFunc = opts.ProgressFunc
|
||||
w.ChunkSize = opts.ChunkSize
|
||||
w.FinalizeOnClose = opts.FinalizeOnClose
|
||||
w.DisableAutoChecksum = opts.DisableAutoChecksum
|
||||
w.CRC32C = opts.CRC32C
|
||||
w.SendCRC32C = opts.SendCRC32C
|
||||
}
|
||||
|
||||
func (o *ObjectHandle) validate() error {
|
||||
@@ -1569,6 +1607,7 @@ type ObjectAttrs struct {
|
||||
// MD5 is the MD5 hash of the object's content. This field is read-only,
|
||||
// except when used from a Writer. If set on a Writer, the uploaded
|
||||
// data is rejected if its MD5 hash does not match this field.
|
||||
// Note: MD5 validation is not supported for appendable writes.
|
||||
MD5 []byte
|
||||
|
||||
// CRC32C is the CRC32 checksum of the object's content using the Castagnoli93
|
||||
|
||||
93
vendor/cloud.google.com/go/storage/trace.go
generated
vendored
93
vendor/cloud.google.com/go/storage/trace.go
generated
vendored
@@ -16,8 +16,11 @@ package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
internalTrace "cloud.google.com/go/internal/trace"
|
||||
"cloud.google.com/go/storage/internal"
|
||||
@@ -25,13 +28,35 @@ import (
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
otelcodes "go.opentelemetry.io/otel/codes"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"google.golang.org/api/googleapi"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
type traceContextKey string
|
||||
|
||||
const (
|
||||
storageOtelTracingDevVar = "GO_STORAGE_DEV_OTEL_TRACING"
|
||||
defaultTracerName = "cloud.google.com/go/storage"
|
||||
gcpClientRepo = "googleapis/google-cloud-go"
|
||||
gcpClientArtifact = "cloud.google.com/go/storage"
|
||||
cacheContextKey traceContextKey = "bucketMetadataCache"
|
||||
bucketContextKey traceContextKey = "bucketName"
|
||||
isBucketContextKey traceContextKey = "isBucketOp"
|
||||
traceAttributesKey traceContextKey = "traceAttributes"
|
||||
)
|
||||
|
||||
func contextWithTraceAttributes(ctx context.Context, attrs []attribute.KeyValue) context.Context {
|
||||
return context.WithValue(ctx, traceAttributesKey, attrs)
|
||||
}
|
||||
|
||||
func traceAttributesFromContext(ctx context.Context) ([]attribute.KeyValue, bool) {
|
||||
attrs, ok := ctx.Value(traceAttributesKey).([]attribute.KeyValue)
|
||||
return attrs, ok
|
||||
}
|
||||
|
||||
const (
|
||||
storageOtelTracingDevVar = "GO_STORAGE_DEV_OTEL_TRACING"
|
||||
defaultTracerName = "cloud.google.com/go/storage"
|
||||
gcpClientRepo = "googleapis/google-cloud-go"
|
||||
gcpClientArtifact = "cloud.google.com/go/storage"
|
||||
storageBucketMetadataDisabledVar = "GO_OTEL_BUCKETMETADATA_DISABLED"
|
||||
)
|
||||
|
||||
// isOTelTracingDevEnabled checks the development flag until experimental feature is launched.
|
||||
@@ -40,10 +65,45 @@ func isOTelTracingDevEnabled() bool {
|
||||
return os.Getenv(storageOtelTracingDevVar) == "true"
|
||||
}
|
||||
|
||||
func isACOEnabled() bool {
|
||||
return os.Getenv(storageBucketMetadataDisabledVar) != "true"
|
||||
}
|
||||
|
||||
func tracer() trace.Tracer {
|
||||
return otel.Tracer(defaultTracerName, trace.WithInstrumentationVersion(internal.Version))
|
||||
}
|
||||
|
||||
func startSpanWithBucket(ctx context.Context, client *Client, bucket string, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) {
|
||||
if !isOTelTracingDevEnabled() {
|
||||
return startSpan(ctx, name, opts...)
|
||||
}
|
||||
if client != nil && client.bucketMetadataCache != nil && bucket != "" {
|
||||
ctx = context.WithValue(ctx, cacheContextKey, client.bucketMetadataCache)
|
||||
ctx = context.WithValue(ctx, bucketContextKey, bucket)
|
||||
isBucket := strings.HasPrefix(name, "Bucket.") || strings.HasPrefix(name, "ACL.") || strings.HasPrefix(name, "storage.IAM.")
|
||||
ctx = context.WithValue(ctx, isBucketContextKey, isBucket)
|
||||
|
||||
cache := client.bucketMetadataCache
|
||||
meta, hit := cache.get(bucket)
|
||||
if !hit {
|
||||
placeholder := bucketMetadata{
|
||||
resource: fmt.Sprintf("projects/_/buckets/%s", bucket),
|
||||
location: "global",
|
||||
placeholder: true,
|
||||
}
|
||||
cache.put(bucket, placeholder)
|
||||
cache.fetchBackground(bucket)
|
||||
meta = placeholder
|
||||
}
|
||||
attrs := []attribute.KeyValue{
|
||||
attribute.String("gcp.resource.destination.id", meta.resource),
|
||||
attribute.String("gcp.resource.destination.location", meta.location),
|
||||
}
|
||||
ctx = contextWithTraceAttributes(ctx, attrs)
|
||||
}
|
||||
return startSpan(ctx, name, opts...)
|
||||
}
|
||||
|
||||
// startSpan creates a span and a context.Context containing the newly-created span.
|
||||
// If the context.Context provided in `ctx` contains a span then the newly-created
|
||||
// span will be a child of that span, otherwise it will be a root span.
|
||||
@@ -55,14 +115,39 @@ func startSpan(ctx context.Context, name string, opts ...trace.SpanStartOption)
|
||||
return ctx, nil
|
||||
}
|
||||
opts = append(opts, getCommonTraceOptions()...)
|
||||
if attrs, ok := traceAttributesFromContext(ctx); ok {
|
||||
opts = append(opts, trace.WithAttributes(attrs...))
|
||||
}
|
||||
ctx, span := tracer().Start(ctx, name, opts...)
|
||||
return ctx, span
|
||||
}
|
||||
|
||||
func isNotFoundError(err error) bool {
|
||||
if errors.Is(err, ErrBucketNotExist) {
|
||||
return true
|
||||
}
|
||||
var e *googleapi.Error
|
||||
if s, ok := status.FromError(err); (ok && s.Code() == codes.NotFound) ||
|
||||
(errors.As(err, &e) && e.Code == http.StatusNotFound) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// endSpan retrieves the current span from ctx and completes the span.
|
||||
// If an error occurs, the error is recorded as an exception span event for this span,
|
||||
// and the span status is set in the form of a code and a description.
|
||||
func endSpan(ctx context.Context, err error) {
|
||||
if err != nil && isNotFoundError(err) {
|
||||
isBucket, _ := ctx.Value(isBucketContextKey).(bool)
|
||||
cache, _ := ctx.Value(cacheContextKey).(*bucketMetadataCache)
|
||||
bucket, _ := ctx.Value(bucketContextKey).(string)
|
||||
|
||||
if isBucket && cache != nil && bucket != "" {
|
||||
cache.evict(bucket)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Remove internalTrace upon experimental launch.
|
||||
if !isOTelTracingDevEnabled() {
|
||||
internalTrace.EndSpan(ctx, err)
|
||||
|
||||
116
vendor/cloud.google.com/go/storage/writer.go
generated
vendored
116
vendor/cloud.google.com/go/storage/writer.go
generated
vendored
@@ -21,8 +21,12 @@ import (
|
||||
"io"
|
||||
"log"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
)
|
||||
|
||||
// Interface internalWriter wraps low-level implementations which may vary
|
||||
@@ -33,6 +37,9 @@ type internalWriter interface {
|
||||
// CloseWithError terminates the write operation and sets its status.
|
||||
// Note that CloseWithError always returns nil.
|
||||
CloseWithError(error) error
|
||||
// Set final object checksum for appendable objects after write
|
||||
// and before finalization.
|
||||
setAppendFinalCRC32C(sendAppendFinalCRC32C bool, c uint32)
|
||||
}
|
||||
|
||||
// A Writer writes a Cloud Storage object.
|
||||
@@ -200,6 +207,28 @@ type Writer struct {
|
||||
// in future releases. It is not yet recommended for production use.
|
||||
ParallelUploadConfig ParallelUploadConfig
|
||||
|
||||
// SendAppendFinalCRC32C indicates that AppendFinalCRC32C should be sent as the
|
||||
// full-object checksum when finalizing an appendable object.
|
||||
//
|
||||
// This field is only supported for gRPC clients and appendable objects.
|
||||
SendAppendFinalCRC32C bool
|
||||
|
||||
// AppendFinalCRC32C is the expected full-object CRC32C checksum to be validated
|
||||
// by the server when finalizing an appendable object.
|
||||
//
|
||||
// This field must be set on the Writer, along with SendAppendFinalCRC32C = true,
|
||||
// before calling Close(). It allows callers to defer providing the checksum
|
||||
// until the final write is complete.
|
||||
//
|
||||
// If SendAppendFinalCRC32C is false, checksum validation for the full object will
|
||||
// fall back to using ObjectAttrs.CRC32C if Writer.SendCRC32C is true. If both are
|
||||
// configured, AppendFinalCRC32C takes precedence.
|
||||
//
|
||||
// This field is ignored if Writer.Append is false or if using the JSON API.
|
||||
// Chunk-level validation will still be performed for all chunks during upload if
|
||||
// Writer.DisableAutoChecksum is false.
|
||||
AppendFinalCRC32C uint32
|
||||
|
||||
ctx context.Context
|
||||
o *ObjectHandle
|
||||
|
||||
@@ -215,6 +244,9 @@ type Writer struct {
|
||||
mu sync.Mutex
|
||||
err error
|
||||
setTakeoverOffset func(int64)
|
||||
|
||||
// bytesWritten is the cumulative bytes written for request size metric.
|
||||
bytesWritten int64
|
||||
}
|
||||
|
||||
func (w *Writer) wrapWriteError(n int, err error) (int, error) {
|
||||
@@ -280,27 +312,36 @@ func (w *Writer) Write(p []byte) (int, error) {
|
||||
return 0, fmt.Errorf("storage: Writer is closed")
|
||||
}
|
||||
|
||||
var n int
|
||||
var err error
|
||||
if pcu != nil {
|
||||
return w.wrapWriteError(pcu.write(p))
|
||||
}
|
||||
|
||||
if !w.opened {
|
||||
// First time initialization: freeze the configuration to either PCU or standard.
|
||||
if w.EnableParallelUpload {
|
||||
var err error
|
||||
if pcu, err = w.getOrInitPCU(); err != nil {
|
||||
return 0, err
|
||||
n, err = pcu.write(p)
|
||||
} else {
|
||||
if !w.opened {
|
||||
// First time initialization: freeze the configuration to either PCU or standard.
|
||||
if w.EnableParallelUpload {
|
||||
if pcu, err = w.getOrInitPCU(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
if pcu != nil {
|
||||
return w.wrapWriteError(pcu.write(p))
|
||||
if pcu == nil {
|
||||
if err = w.openWriter(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := w.openWriter(); err != nil {
|
||||
return 0, err
|
||||
if pcu != nil {
|
||||
n, err = pcu.write(p)
|
||||
} else {
|
||||
n, err = w.iw.Write(p)
|
||||
}
|
||||
}
|
||||
|
||||
return w.wrapWriteError(w.iw.Write(p))
|
||||
if n > 0 {
|
||||
atomic.AddInt64(&w.bytesWritten, int64(n))
|
||||
}
|
||||
|
||||
return w.wrapWriteError(n, err)
|
||||
}
|
||||
|
||||
// Flush syncs all bytes currently in the Writer's buffer to Cloud Storage.
|
||||
@@ -361,38 +402,54 @@ func (w *Writer) Close() error {
|
||||
if pcu != nil || (!w.opened && w.EnableParallelUpload) {
|
||||
var err error
|
||||
if pcu, err = w.getOrInitPCU(); err != nil {
|
||||
return err
|
||||
return w.markClosed(err)
|
||||
}
|
||||
|
||||
if pcu != nil {
|
||||
err = pcu.close()
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
w.closed = true
|
||||
if w.err == nil && err != nil {
|
||||
w.err = err
|
||||
}
|
||||
endSpan(w.ctx, w.err)
|
||||
return w.err
|
||||
return w.markClosed(pcu.close())
|
||||
}
|
||||
}
|
||||
|
||||
if !w.opened {
|
||||
if err := w.openWriter(); err != nil {
|
||||
return err
|
||||
return w.markClosed(err)
|
||||
}
|
||||
}
|
||||
|
||||
if w.Append {
|
||||
w.iw.setAppendFinalCRC32C(w.SendAppendFinalCRC32C, w.AppendFinalCRC32C)
|
||||
}
|
||||
|
||||
if err := w.iw.Close(); err != nil {
|
||||
return err
|
||||
return w.markClosed(err)
|
||||
}
|
||||
|
||||
<-w.donec
|
||||
return w.markClosed(nil)
|
||||
}
|
||||
|
||||
// markClosed marks the Writer as closed, records any closing error on Writer.err,
|
||||
// and records request body size metrics and trace span completion.
|
||||
func (w *Writer) markClosed(err error) error {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
w.closed = true
|
||||
endSpan(w.ctx, w.err)
|
||||
return w.err
|
||||
if w.err == nil && err != nil {
|
||||
w.err = err
|
||||
}
|
||||
closingErr := w.err
|
||||
total := atomic.LoadInt64(&w.bytesWritten)
|
||||
w.mu.Unlock()
|
||||
|
||||
if state := metricsStateFromContext(w.ctx); state != nil {
|
||||
if state.metrics != nil && total > 0 {
|
||||
state.metrics.requestBodySize.Record(w.ctx, total, metric.WithAttributes(attribute.String("rpc.method", "WriteObject")))
|
||||
}
|
||||
if state.record != nil {
|
||||
state.record(closingErr)
|
||||
}
|
||||
}
|
||||
endSpan(w.ctx, closingErr)
|
||||
return closingErr
|
||||
}
|
||||
|
||||
func (w *Writer) openWriter() (err error) {
|
||||
@@ -440,6 +497,7 @@ func (w *Writer) openWriter() (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w.ctx = params.ctx
|
||||
w.opened = true
|
||||
go w.monitorCancel()
|
||||
|
||||
|
||||
@@ -17,5 +17,5 @@ package metric
|
||||
// Version is the current release version of the OpenTelemetry
|
||||
// Operations Metric Exporter in use.
|
||||
func Version() string {
|
||||
return "0.57.0"
|
||||
return "0.58.0"
|
||||
}
|
||||
|
||||
8
vendor/github.com/aws/aws-sdk-go-v2/aws/config.go
generated
vendored
8
vendor/github.com/aws/aws-sdk-go-v2/aws/config.go
generated
vendored
@@ -164,6 +164,14 @@ type Config struct {
|
||||
// the shared config profile attribute request_min_compression_size_bytes
|
||||
RequestMinCompressSizeBytes int64
|
||||
|
||||
// DisableClockSkewCorrection turns off SDK clock skew correction. When set
|
||||
// the SDK will not adjust request signing timestamps to compensate for
|
||||
// drift between the client and service clocks. Set to false (enabled) by
|
||||
// default. This variable is sourced from the environment variable
|
||||
// AWS_DISABLE_CLOCK_SKEW_CORRECTION or the shared config profile attribute
|
||||
// disable_clock_skew_correction.
|
||||
DisableClockSkewCorrection bool
|
||||
|
||||
// Controls how a resolved AWS account ID is handled for endpoint routing.
|
||||
AccountIDEndpointMode AccountIDEndpointMode
|
||||
|
||||
|
||||
2
vendor/github.com/aws/aws-sdk-go-v2/aws/go_module_metadata.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go-v2/aws/go_module_metadata.go
generated
vendored
@@ -3,4 +3,4 @@
|
||||
package aws
|
||||
|
||||
// goModuleVersion is the tagged release for this module
|
||||
const goModuleVersion = "1.42.0"
|
||||
const goModuleVersion = "1.43.0"
|
||||
|
||||
47
vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/middleware.go
generated
vendored
47
vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/middleware.go
generated
vendored
@@ -43,7 +43,12 @@ func (r ClientRequestID) HandleBuild(ctx context.Context, in middleware.BuildInp
|
||||
}
|
||||
|
||||
// RecordResponseTiming records the response timing for the SDK client requests.
|
||||
type RecordResponseTiming struct{}
|
||||
type RecordResponseTiming struct {
|
||||
// DisableClockSkewCorrection suppresses recording of clock skew observed
|
||||
// from the response, per the Clock Skew Correction SEP. Response timing is
|
||||
// still recorded.
|
||||
DisableClockSkewCorrection bool
|
||||
}
|
||||
|
||||
// ID is the middleware identifier
|
||||
func (a *RecordResponseTiming) ID() string {
|
||||
@@ -54,14 +59,17 @@ func (a *RecordResponseTiming) ID() string {
|
||||
func (a RecordResponseTiming) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) (
|
||||
out middleware.DeserializeOutput, metadata middleware.Metadata, err error,
|
||||
) {
|
||||
requestAt := sdk.NowTime()
|
||||
out, metadata, err = next.HandleDeserialize(ctx, in)
|
||||
responseAt := sdk.NowTime()
|
||||
setResponseAt(&metadata, responseAt)
|
||||
|
||||
var serverTime time.Time
|
||||
var hasAgeHeader bool
|
||||
|
||||
switch resp := out.RawResponse.(type) {
|
||||
case *smithyhttp.Response:
|
||||
hasAgeHeader = len(resp.Header.Get("Age")) > 0
|
||||
respDateHeader := resp.Header.Get("Date")
|
||||
if len(respDateHeader) == 0 {
|
||||
break
|
||||
@@ -77,14 +85,45 @@ func (a RecordResponseTiming) HandleDeserialize(ctx context.Context, in middlewa
|
||||
setServerTime(&metadata, serverTime)
|
||||
}
|
||||
|
||||
if !serverTime.IsZero() {
|
||||
attemptSkew := serverTime.Sub(responseAt)
|
||||
setAttemptSkew(&metadata, attemptSkew)
|
||||
if !a.DisableClockSkewCorrection {
|
||||
if skew, ok := computeClockSkew(serverTime, requestAt, responseAt, hasAgeHeader); ok {
|
||||
setAttemptSkew(&metadata, skew)
|
||||
}
|
||||
}
|
||||
|
||||
return out, metadata, err
|
||||
}
|
||||
|
||||
// maxTrustedRequestDuration bounds how long a request may take before the SDK
|
||||
// discards the skew measurement derived from its response. A slower round trip
|
||||
// could only produce a signing failure if it pushed the timestamp outside the
|
||||
// SigV4 validity window. See the Clock Skew Correction SEP.
|
||||
const maxTrustedRequestDuration = 15 * time.Minute
|
||||
|
||||
// computeClockSkew derives a clock skew candidate from a response per the Clock
|
||||
// Skew Correction SEP. It returns ok=false (no candidate) when the Date header
|
||||
// was absent/unparseable (serverTime zero), the round trip exceeded the maximum
|
||||
// trusted request duration, or the response was served from a cache (Age
|
||||
// header present). Otherwise the skew is the difference between the server's
|
||||
// Date and the midpoint of the request round trip.
|
||||
func computeClockSkew(serverTime, requestAt, responseAt time.Time, hasAgeHeader bool) (time.Duration, bool) {
|
||||
if serverTime.IsZero() {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
if hasAgeHeader {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
elapsed := responseAt.Sub(requestAt)
|
||||
if elapsed > maxTrustedRequestDuration {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
midpoint := requestAt.Add(elapsed / 2)
|
||||
return serverTime.Sub(midpoint), true
|
||||
}
|
||||
|
||||
type responseAtKey struct{}
|
||||
|
||||
// GetResponseAt returns the time response was received at.
|
||||
|
||||
4
vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/CHANGELOG.md
generated
vendored
4
vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/CHANGELOG.md
generated
vendored
@@ -1,3 +1,7 @@
|
||||
# v1.7.14 (2026-07-01)
|
||||
|
||||
* No change notes available for this release.
|
||||
|
||||
# v1.7.13 (2026-06-04)
|
||||
|
||||
* **Dependency Update**: Update to smithy-go v1.27.1 to fix several union-related deserialization bugs in schema-serde-enabled services.
|
||||
|
||||
2
vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/go_module_metadata.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/go_module_metadata.go
generated
vendored
@@ -3,4 +3,4 @@
|
||||
package eventstream
|
||||
|
||||
// goModuleVersion is the tagged release for this module
|
||||
const goModuleVersion = "1.7.13"
|
||||
const goModuleVersion = "1.7.14"
|
||||
|
||||
78
vendor/github.com/aws/aws-sdk-go-v2/aws/retry/middleware.go
generated
vendored
78
vendor/github.com/aws/aws-sdk-go-v2/aws/retry/middleware.go
generated
vendored
@@ -48,6 +48,12 @@ type Attempt struct {
|
||||
// call.
|
||||
ClientSkew *atomic.Int64
|
||||
|
||||
// DisableClockSkewCorrection disables clock skew correction per the Clock
|
||||
// Skew Correction SEP: observed skew is not applied to the signing
|
||||
// timestamp, not recorded into ClientSkew, and clock skew error codes are
|
||||
// not treated as retry candidates.
|
||||
DisableClockSkewCorrection bool
|
||||
|
||||
retryer aws.RetryerV2
|
||||
requestCloner RequestCloner
|
||||
}
|
||||
@@ -88,7 +94,7 @@ func (r *Attempt) HandleFinalize(ctx context.Context, in smithymiddle.FinalizeIn
|
||||
out smithymiddle.FinalizeOutput, metadata smithymiddle.Metadata, err error,
|
||||
) {
|
||||
var attemptClockSkew time.Duration
|
||||
if r.ClientSkew != nil {
|
||||
if !r.DisableClockSkewCorrection && r.ClientSkew != nil {
|
||||
attemptClockSkew = time.Duration(r.ClientSkew.Load())
|
||||
}
|
||||
|
||||
@@ -159,7 +165,7 @@ func (r *Attempt) HandleFinalize(ctx context.Context, in smithymiddle.FinalizeIn
|
||||
|
||||
// this guarantees we are staying on top of the persistent skew value
|
||||
// (either to apply it or to heal it back if the clocks realign)
|
||||
if r.ClientSkew != nil {
|
||||
if !r.DisableClockSkewCorrection && r.ClientSkew != nil {
|
||||
if resultSkew, ok := awsmiddle.GetAttemptSkew(metadata); ok {
|
||||
r.ClientSkew.Store(resultSkew.Nanoseconds())
|
||||
}
|
||||
@@ -245,7 +251,10 @@ func (r *Attempt) handleAttempt(
|
||||
return out, attemptResult, nopRelease, err
|
||||
}
|
||||
|
||||
err = wrapAsClockSkew(ctx, err)
|
||||
if !r.DisableClockSkewCorrection {
|
||||
candidateSkew, hasCandidateSkew := awsmiddle.GetAttemptSkew(metadata)
|
||||
err = wrapAsClockSkew(err, candidateSkew, hasCandidateSkew, retryMetadata.AttemptClockSkew)
|
||||
}
|
||||
|
||||
//------------------------------
|
||||
// Is Retryable and Should Retry
|
||||
@@ -316,37 +325,66 @@ func (r *Attempt) handleAttempt(
|
||||
return out, attemptResult, releaseRetryToken, err
|
||||
}
|
||||
|
||||
// errors that, if detected when we know there's a clock skew,
|
||||
// can be retried and have a high chance of success
|
||||
var possibleSkewCodes = map[string]struct{}{
|
||||
// clockSkewCodes are the error codes that may indicate a clock skew problem.
|
||||
// Per the Clock Skew Correction SEP these are retryable only when the absolute
|
||||
// skew observed from the response Date header exceeds the detection threshold.
|
||||
// The SEP does not distinguish "definite" from "possible" skew errors: modern
|
||||
// services overload a single code (e.g. InvalidSignatureException) for both
|
||||
// skewed and genuinely malformed signatures, so every code is gated on the
|
||||
// observed skew.
|
||||
var clockSkewCodes = map[string]struct{}{
|
||||
"InvalidSignatureException": {},
|
||||
"SignatureDoesNotMatch": {},
|
||||
"AuthFailure": {},
|
||||
"RequestTimeTooSkewed": {},
|
||||
"AccessDeniedException": {},
|
||||
}
|
||||
|
||||
var definiteSkewCodes = map[string]struct{}{
|
||||
"RequestExpired": {},
|
||||
"RequestInTheFuture": {},
|
||||
"RequestTimeTooSkewed": {},
|
||||
}
|
||||
|
||||
// wrapAsClockSkew checks if this error could be related to a clock skew
|
||||
// error and if so, wrap the error.
|
||||
func wrapAsClockSkew(ctx context.Context, err error) error {
|
||||
// wrapAsClockSkew classifies err as a retryable clock skew error when its code
|
||||
// is a known clock skew code and the signing time diverges from the server
|
||||
// time by more than the detection threshold.
|
||||
//
|
||||
// The signing time is now() + attemptSkew. The server time is now() +
|
||||
// candidateSkew (derived from the response Date header). The signing error is:
|
||||
//
|
||||
// |attemptSkew - candidateSkew| > skewThreshold
|
||||
//
|
||||
// This single check covers both fresh skew detection (attemptSkew is zero on
|
||||
// first attempt, so the error equals |candidateSkew|) and stale offset healing
|
||||
// (attemptSkew is large but the server and client clocks have realigned, so
|
||||
// candidateSkew is near zero).
|
||||
//
|
||||
// If no candidate was observed (the Date header was absent, unparseable, or
|
||||
// discarded as untrusted), the error is not treated as clock skew.
|
||||
func wrapAsClockSkew(err error, candidateSkew time.Duration, hasCandidateSkew bool, attemptSkew time.Duration) error {
|
||||
var v interface{ ErrorCode() string }
|
||||
if !errors.As(err, &v) {
|
||||
return err
|
||||
}
|
||||
if _, ok := definiteSkewCodes[v.ErrorCode()]; ok {
|
||||
return &retryableClockSkewError{Err: err}
|
||||
}
|
||||
_, isPossibleSkewCode := possibleSkewCodes[v.ErrorCode()]
|
||||
if skew := internalcontext.GetAttemptSkewContext(ctx); skew > skewThreshold && isPossibleSkewCode {
|
||||
|
||||
if _, ok := clockSkewCodes[v.ErrorCode()]; !ok {
|
||||
return err
|
||||
}
|
||||
|
||||
if !hasCandidateSkew {
|
||||
return err
|
||||
}
|
||||
|
||||
if absDuration(attemptSkew-candidateSkew) > skewThreshold {
|
||||
return &retryableClockSkewError{Err: err}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func absDuration(d time.Duration) time.Duration {
|
||||
if d < 0 {
|
||||
return -d
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
// MetricsHeader attaches SDK request metric header for retries to the transport
|
||||
type MetricsHeader struct{}
|
||||
|
||||
|
||||
25
vendor/github.com/aws/aws-sdk-go-v2/config/CHANGELOG.md
generated
vendored
25
vendor/github.com/aws/aws-sdk-go-v2/config/CHANGELOG.md
generated
vendored
@@ -1,3 +1,28 @@
|
||||
# v1.32.31 (2026-07-21)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.32.30 (2026-07-13)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.32.29 (2026-07-08.2)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.32.28 (2026-07-06)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.32.27 (2026-07-01)
|
||||
|
||||
* **Bug Fix**: Bump smithy-go to 1.27.3, fix JSON encorder for document.Number, endpoint host label format validation and CBOR union serialization on new serde
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.32.26 (2026-06-29)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.32.25 (2026-06-10)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
2
vendor/github.com/aws/aws-sdk-go-v2/config/config.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go-v2/config/config.go
generated
vendored
@@ -77,6 +77,8 @@ var defaultAWSConfigResolvers = []awsConfigResolver{
|
||||
|
||||
// Sets the DisableRequestCompression if present in env var or shared config profile
|
||||
resolveDisableRequestCompression,
|
||||
// Sets the DisableClockSkewCorrection if present in env var or shared config profile
|
||||
resolveDisableClockSkewCorrection,
|
||||
|
||||
// Sets the RequestMinCompressSizeBytes if present in env var or shared config profile
|
||||
resolveRequestMinCompressSizeBytes,
|
||||
|
||||
16
vendor/github.com/aws/aws-sdk-go-v2/config/env_config.go
generated
vendored
16
vendor/github.com/aws/aws-sdk-go-v2/config/env_config.go
generated
vendored
@@ -78,6 +78,8 @@ const (
|
||||
awsDisableRequestCompressionEnv = "AWS_DISABLE_REQUEST_COMPRESSION"
|
||||
awsRequestMinCompressionSizeBytesEnv = "AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES"
|
||||
|
||||
awsDisableClockSkewCorrectionEnv = "AWS_DISABLE_CLOCK_SKEW_CORRECTION"
|
||||
|
||||
awsS3DisableExpressSessionAuthEnv = "AWS_S3_DISABLE_EXPRESS_SESSION_AUTH"
|
||||
|
||||
awsAccountIDEnv = "AWS_ACCOUNT_ID"
|
||||
@@ -293,6 +295,10 @@ type EnvConfig struct {
|
||||
// retrieved from env var AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES
|
||||
RequestMinCompressSizeBytes *int64
|
||||
|
||||
// determine if clock skew correction is disabled, default to false
|
||||
// retrieved from env var AWS_DISABLE_CLOCK_SKEW_CORRECTION
|
||||
DisableClockSkewCorrection *bool
|
||||
|
||||
// Whether S3Express auth is disabled.
|
||||
//
|
||||
// This will NOT prevent requests from being made to S3Express buckets, it
|
||||
@@ -364,6 +370,9 @@ func NewEnvConfig() (EnvConfig, error) {
|
||||
if err := setInt64PtrFromEnvVal(&cfg.RequestMinCompressSizeBytes, []string{awsRequestMinCompressionSizeBytesEnv}, smithyrequestcompression.MaxRequestMinCompressSizeBytes); err != nil {
|
||||
return cfg, err
|
||||
}
|
||||
if err := setBoolPtrFromEnvVal(&cfg.DisableClockSkewCorrection, []string{awsDisableClockSkewCorrectionEnv}); err != nil {
|
||||
return cfg, err
|
||||
}
|
||||
|
||||
if err := setEndpointDiscoveryTypeFromEnvVal(&cfg.EnableEndpointDiscovery, []string{awsEnableEndpointDiscoveryEnv}); err != nil {
|
||||
return cfg, err
|
||||
@@ -453,6 +462,13 @@ func (c EnvConfig) getDisableRequestCompression(context.Context) (bool, bool, er
|
||||
return *c.DisableRequestCompression, true, nil
|
||||
}
|
||||
|
||||
func (c EnvConfig) getDisableClockSkewCorrection(context.Context) (bool, bool, error) {
|
||||
if c.DisableClockSkewCorrection == nil {
|
||||
return false, false, nil
|
||||
}
|
||||
return *c.DisableClockSkewCorrection, true, nil
|
||||
}
|
||||
|
||||
func (c EnvConfig) getRequestMinCompressSizeBytes(context.Context) (int64, bool, error) {
|
||||
if c.RequestMinCompressSizeBytes == nil {
|
||||
return 0, false, nil
|
||||
|
||||
2
vendor/github.com/aws/aws-sdk-go-v2/config/go_module_metadata.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go-v2/config/go_module_metadata.go
generated
vendored
@@ -3,4 +3,4 @@
|
||||
package config
|
||||
|
||||
// goModuleVersion is the tagged release for this module
|
||||
const goModuleVersion = "1.32.25"
|
||||
const goModuleVersion = "1.32.31"
|
||||
|
||||
23
vendor/github.com/aws/aws-sdk-go-v2/config/load_options.go
generated
vendored
23
vendor/github.com/aws/aws-sdk-go-v2/config/load_options.go
generated
vendored
@@ -214,6 +214,9 @@ type LoadOptions struct {
|
||||
// The inclusive min bytes of a request body that could be compressed
|
||||
RequestMinCompressSizeBytes *int64
|
||||
|
||||
// Specifies whether SDK clock skew correction is disabled
|
||||
DisableClockSkewCorrection *bool
|
||||
|
||||
// Whether S3 Express auth is disabled.
|
||||
S3DisableExpressAuth *bool
|
||||
|
||||
@@ -299,6 +302,14 @@ func (o LoadOptions) getDisableRequestCompression(ctx context.Context) (bool, bo
|
||||
return *o.DisableRequestCompression, true, nil
|
||||
}
|
||||
|
||||
// getDisableClockSkewCorrection returns DisableClockSkewCorrection from config's LoadOptions
|
||||
func (o LoadOptions) getDisableClockSkewCorrection(ctx context.Context) (bool, bool, error) {
|
||||
if o.DisableClockSkewCorrection == nil {
|
||||
return false, false, nil
|
||||
}
|
||||
return *o.DisableClockSkewCorrection, true, nil
|
||||
}
|
||||
|
||||
// getRequestMinCompressSizeBytes returns RequestMinCompressSizeBytes from config's LoadOptions
|
||||
func (o LoadOptions) getRequestMinCompressSizeBytes(ctx context.Context) (int64, bool, error) {
|
||||
if o.RequestMinCompressSizeBytes == nil {
|
||||
@@ -369,6 +380,18 @@ func WithDisableRequestCompression(DisableRequestCompression *bool) LoadOptionsF
|
||||
}
|
||||
}
|
||||
|
||||
// WithDisableClockSkewCorrection is a helper function to construct functional
|
||||
// options that sets DisableClockSkewCorrection on config's LoadOptions.
|
||||
func WithDisableClockSkewCorrection(DisableClockSkewCorrection *bool) LoadOptionsFunc {
|
||||
return func(o *LoadOptions) error {
|
||||
if DisableClockSkewCorrection == nil {
|
||||
return nil
|
||||
}
|
||||
o.DisableClockSkewCorrection = DisableClockSkewCorrection
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithRequestMinCompressSizeBytes is a helper function to construct functional options
|
||||
// that sets RequestMinCompressSizeBytes on config's LoadOptions.
|
||||
func WithRequestMinCompressSizeBytes(RequestMinCompressSizeBytes *int64) LoadOptionsFunc {
|
||||
|
||||
17
vendor/github.com/aws/aws-sdk-go-v2/config/provider.go
generated
vendored
17
vendor/github.com/aws/aws-sdk-go-v2/config/provider.go
generated
vendored
@@ -208,6 +208,23 @@ func getDisableRequestCompression(ctx context.Context, configs configs) (value b
|
||||
return
|
||||
}
|
||||
|
||||
// disableClockSkewCorrectionProvider provides access to the DisableClockSkewCorrection
|
||||
type disableClockSkewCorrectionProvider interface {
|
||||
getDisableClockSkewCorrection(context.Context) (bool, bool, error)
|
||||
}
|
||||
|
||||
func getDisableClockSkewCorrection(ctx context.Context, configs configs) (value bool, found bool, err error) {
|
||||
for _, cfg := range configs {
|
||||
if p, ok := cfg.(disableClockSkewCorrectionProvider); ok {
|
||||
value, found, err = p.getDisableClockSkewCorrection(ctx)
|
||||
if err != nil || found {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// requestMinCompressSizeBytesProvider provides access to the MinCompressSizeBytes
|
||||
type requestMinCompressSizeBytesProvider interface {
|
||||
getRequestMinCompressSizeBytes(context.Context) (int64, bool, error)
|
||||
|
||||
12
vendor/github.com/aws/aws-sdk-go-v2/config/resolve.go
generated
vendored
12
vendor/github.com/aws/aws-sdk-go-v2/config/resolve.go
generated
vendored
@@ -151,6 +151,18 @@ func resolveDisableRequestCompression(ctx context.Context, cfg *aws.Config, conf
|
||||
return nil
|
||||
}
|
||||
|
||||
// resolveDisableClockSkewCorrection extracts the DisableClockSkewCorrection from
|
||||
// the configs slice's SharedConfig or EnvConfig
|
||||
func resolveDisableClockSkewCorrection(ctx context.Context, cfg *aws.Config, configs configs) error {
|
||||
disable, _, err := getDisableClockSkewCorrection(ctx, configs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg.DisableClockSkewCorrection = disable
|
||||
return nil
|
||||
}
|
||||
|
||||
// resolveRequestMinCompressSizeBytes extracts the RequestMinCompressSizeBytes from the configs slice's
|
||||
// SharedConfig or EnvConfig
|
||||
func resolveRequestMinCompressSizeBytes(ctx context.Context, cfg *aws.Config, configs configs) error {
|
||||
|
||||
16
vendor/github.com/aws/aws-sdk-go-v2/config/shared_config.go
generated
vendored
16
vendor/github.com/aws/aws-sdk-go-v2/config/shared_config.go
generated
vendored
@@ -113,6 +113,8 @@ const (
|
||||
disableRequestCompression = "disable_request_compression"
|
||||
requestMinCompressionSizeBytes = "request_min_compression_size_bytes"
|
||||
|
||||
disableClockSkewCorrection = "disable_clock_skew_correction"
|
||||
|
||||
s3DisableExpressSessionAuthKey = "s3_disable_express_session_auth"
|
||||
|
||||
accountIDKey = "aws_account_id"
|
||||
@@ -346,6 +348,10 @@ type SharedConfig struct {
|
||||
// retrieved from config file's profile field request_min_compression_size_bytes
|
||||
RequestMinCompressSizeBytes *int64
|
||||
|
||||
// determine if clock skew correction is disabled, default to false
|
||||
// retrieved from config file's profile field disable_clock_skew_correction
|
||||
DisableClockSkewCorrection *bool
|
||||
|
||||
// Whether S3Express auth is disabled.
|
||||
//
|
||||
// This will NOT prevent requests from being made to S3Express buckets, it
|
||||
@@ -1149,6 +1155,9 @@ func (c *SharedConfig) setFromIniSection(profile string, section ini.Section) er
|
||||
if err := updateDisableRequestCompression(&c.DisableRequestCompression, section, disableRequestCompression); err != nil {
|
||||
return fmt.Errorf("failed to load %s from shared config, %w", disableRequestCompression, err)
|
||||
}
|
||||
if err := updateDisableRequestCompression(&c.DisableClockSkewCorrection, section, disableClockSkewCorrection); err != nil {
|
||||
return fmt.Errorf("failed to load %s from shared config, %w", disableClockSkewCorrection, err)
|
||||
}
|
||||
if err := updateRequestMinCompressSizeBytes(&c.RequestMinCompressSizeBytes, section, requestMinCompressionSizeBytes); err != nil {
|
||||
return fmt.Errorf("failed to load %s from shared config, %w", requestMinCompressionSizeBytes, err)
|
||||
}
|
||||
@@ -1292,6 +1301,13 @@ func (c SharedConfig) getDisableRequestCompression(ctx context.Context) (bool, b
|
||||
return *c.DisableRequestCompression, true, nil
|
||||
}
|
||||
|
||||
func (c SharedConfig) getDisableClockSkewCorrection(ctx context.Context) (bool, bool, error) {
|
||||
if c.DisableClockSkewCorrection == nil {
|
||||
return false, false, nil
|
||||
}
|
||||
return *c.DisableClockSkewCorrection, true, nil
|
||||
}
|
||||
|
||||
func (c SharedConfig) getAccountIDEndpointMode(ctx context.Context) (aws.AccountIDEndpointMode, bool, error) {
|
||||
return c.AccountIDEndpointMode, len(c.AccountIDEndpointMode) > 0, nil
|
||||
}
|
||||
|
||||
25
vendor/github.com/aws/aws-sdk-go-v2/credentials/CHANGELOG.md
generated
vendored
25
vendor/github.com/aws/aws-sdk-go-v2/credentials/CHANGELOG.md
generated
vendored
@@ -1,3 +1,28 @@
|
||||
# v1.19.30 (2026-07-21)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.19.29 (2026-07-13)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.19.28 (2026-07-08.2)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.19.27 (2026-07-06)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.19.26 (2026-07-01)
|
||||
|
||||
* **Bug Fix**: Bump smithy-go to 1.27.3, fix JSON encorder for document.Number, endpoint host label format validation and CBOR union serialization on new serde
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.19.25 (2026-06-29)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.19.24 (2026-06-10)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
2
vendor/github.com/aws/aws-sdk-go-v2/credentials/go_module_metadata.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go-v2/credentials/go_module_metadata.go
generated
vendored
@@ -3,4 +3,4 @@
|
||||
package credentials
|
||||
|
||||
// goModuleVersion is the tagged release for this module
|
||||
const goModuleVersion = "1.19.24"
|
||||
const goModuleVersion = "1.19.30"
|
||||
|
||||
8
vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/CHANGELOG.md
generated
vendored
8
vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/CHANGELOG.md
generated
vendored
@@ -1,3 +1,11 @@
|
||||
# v1.18.31 (2026-07-21)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.18.30 (2026-07-01)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.18.29 (2026-06-08)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
2
vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/go_module_metadata.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/go_module_metadata.go
generated
vendored
@@ -3,4 +3,4 @@
|
||||
package imds
|
||||
|
||||
// goModuleVersion is the tagged release for this module
|
||||
const goModuleVersion = "1.18.29"
|
||||
const goModuleVersion = "1.18.31"
|
||||
|
||||
33
vendor/github.com/aws/aws-sdk-go-v2/feature/s3/manager/CHANGELOG.md
generated
vendored
33
vendor/github.com/aws/aws-sdk-go-v2/feature/s3/manager/CHANGELOG.md
generated
vendored
@@ -1,3 +1,36 @@
|
||||
# v1.22.35 (2026-07-21)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.22.34 (2026-07-16)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.22.33 (2026-07-13)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.22.32 (2026-07-08.2)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.22.31 (2026-07-06)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.22.30 (2026-07-01)
|
||||
|
||||
* **Bug Fix**: Bump smithy-go to 1.27.3, fix JSON encorder for document.Number, endpoint host label format validation and CBOR union serialization on new serde
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.22.29 (2026-06-29)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.22.28 (2026-06-16)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.22.27 (2026-06-10)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
2
vendor/github.com/aws/aws-sdk-go-v2/feature/s3/manager/go_module_metadata.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go-v2/feature/s3/manager/go_module_metadata.go
generated
vendored
@@ -3,4 +3,4 @@
|
||||
package manager
|
||||
|
||||
// goModuleVersion is the tagged release for this module
|
||||
const goModuleVersion = "1.22.27"
|
||||
const goModuleVersion = "1.22.35"
|
||||
|
||||
8
vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/CHANGELOG.md
generated
vendored
8
vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/CHANGELOG.md
generated
vendored
@@ -1,3 +1,11 @@
|
||||
# v1.4.31 (2026-07-21)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.4.30 (2026-07-01)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.4.29 (2026-06-08)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
2
vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/go_module_metadata.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/go_module_metadata.go
generated
vendored
@@ -3,4 +3,4 @@
|
||||
package configsources
|
||||
|
||||
// goModuleVersion is the tagged release for this module
|
||||
const goModuleVersion = "1.4.29"
|
||||
const goModuleVersion = "1.4.31"
|
||||
|
||||
8
vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/CHANGELOG.md
generated
vendored
8
vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/CHANGELOG.md
generated
vendored
@@ -1,3 +1,11 @@
|
||||
# v2.7.31 (2026-07-21)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v2.7.30 (2026-07-01)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v2.7.29 (2026-06-08)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
2
vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/go_module_metadata.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/go_module_metadata.go
generated
vendored
@@ -3,4 +3,4 @@
|
||||
package endpoints
|
||||
|
||||
// goModuleVersion is the tagged release for this module
|
||||
const goModuleVersion = "2.7.29"
|
||||
const goModuleVersion = "2.7.31"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user