exec credential provider: add rest_client_exec_plugin_call_total metric

Signed-off-by: Andrew Keesler <akeesler@vmware.com>

Kubernetes-commit: 31eec29b098f790cd96fd6d2441e68938f15363b
This commit is contained in:
Andrew Keesler
2021-02-08 15:20:15 -05:00
committed by Kubernetes Publisher
parent a5abe9cdbf
commit 8aa3e0f684
4 changed files with 170 additions and 1 deletions

View File

@@ -17,8 +17,14 @@ limitations under the License.
package exec
import (
"fmt"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"k8s.io/client-go/pkg/apis/clientauthentication"
"k8s.io/client-go/tools/clientcmd/api"
"k8s.io/client-go/tools/metrics"
)
type mockExpiryGauge struct {
@@ -94,3 +100,98 @@ func TestCertificateExpirationTracker(t *testing.T) {
})
}
}
type mockCallsMetric struct {
exitCode int
errorType string
}
type mockCallsMetricCounter struct {
calls []mockCallsMetric
}
func (f *mockCallsMetricCounter) Increment(exitCode int, errorType string) {
f.calls = append(f.calls, mockCallsMetric{exitCode: exitCode, errorType: errorType})
}
func TestCallsMetric(t *testing.T) {
const (
goodOutput = `{
"kind": "ExecCredential",
"apiVersion": "client.authentication.k8s.io/v1beta1",
"status": {
"token": "foo-bar"
}
}`
)
callsMetricCounter := &mockCallsMetricCounter{}
originalExecPluginCalls := metrics.ExecPluginCalls
t.Cleanup(func() { metrics.ExecPluginCalls = originalExecPluginCalls })
metrics.ExecPluginCalls = callsMetricCounter
exitCodes := []int{0, 1, 2, 0}
var wantCallsMetrics []mockCallsMetric
for _, exitCode := range exitCodes {
c := api.ExecConfig{
Command: "./testdata/test-plugin.sh",
APIVersion: "client.authentication.k8s.io/v1beta1",
Env: []api.ExecEnvVar{
{Name: "TEST_EXIT_CODE", Value: fmt.Sprintf("%d", exitCode)},
{Name: "TEST_OUTPUT", Value: goodOutput},
},
}
a, err := newAuthenticator(newCache(), &c, nil)
if err != nil {
t.Fatal(err)
}
// Run refresh creds twice so that our test validates that the metrics are set correctly twice
// in a row with the same authenticator.
refreshCreds := func() {
if err := a.refreshCredsLocked(&clientauthentication.Response{}); (err == nil) != (exitCode == 0) {
if err != nil {
t.Fatalf("wanted no error, but got %q", err.Error())
} else {
t.Fatal("wanted error, but got nil")
}
}
mockCallsMetric := mockCallsMetric{exitCode: exitCode, errorType: "no_error"}
if exitCode != 0 {
mockCallsMetric.errorType = "plugin_execution_error"
}
wantCallsMetrics = append(wantCallsMetrics, mockCallsMetric)
}
refreshCreds()
refreshCreds()
}
// Run some iterations of the authenticator where the exec plugin fails to run to test special
// metric values.
refreshCreds := func(command string) {
c := api.ExecConfig{
Command: "does not exist",
APIVersion: "client.authentication.k8s.io/v1beta1",
}
a, err := newAuthenticator(newCache(), &c, nil)
if err != nil {
t.Fatal(err)
}
if err := a.refreshCredsLocked(&clientauthentication.Response{}); err == nil {
t.Fatal("expected the authenticator to fail because the plugin does not exist")
}
wantCallsMetrics = append(wantCallsMetrics, mockCallsMetric{exitCode: 1, errorType: "plugin_not_found_error"})
}
refreshCreds("does not exist without path slashes")
refreshCreds("./does/not/exist/with/relative/path")
refreshCreds("/does/not/exist/with/absolute/path")
callsMetricComparer := cmp.Comparer(func(a, b mockCallsMetric) bool {
return a.exitCode == b.exitCode && a.errorType == b.errorType
})
actuallCallsMetrics := callsMetricCounter.calls
if diff := cmp.Diff(wantCallsMetrics, actuallCallsMetrics, callsMetricComparer); diff != "" {
t.Fatalf("got unexpected metrics calls; -want, +got:\n%s", diff)
}
}