Skip to content

Commit 484704b

Browse files
authored
[receiver/kubeletstats] Support specifying context for kubeConfig auth_type (#26665) (#27240)
**Description:** Support specifying context for `kubeConfig` `auth_type` when communicating with a Kubernetes cluster. **Link to tracking Issue:** 26665 **Testing:** unit test added **Documentation:** kubeletstatsreceiver README updated Signed-off-by: JACQUES Francois <[email protected]>
1 parent 4796666 commit 484704b

File tree

5 files changed

+99
-34
lines changed

5 files changed

+99
-34
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
2+
change_type: enhancement
3+
4+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
5+
component: kubeletstatsreceiver
6+
7+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
8+
note: Support specifying context for `kubeConfig` `auth_type`
9+
10+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
11+
issues: [26665]
12+
13+
# (Optional) One or more lines of additional information to render under the primary note.
14+
# These lines will be padded with 2 spaces and then inserted directly into the document.
15+
# Use pipe (|) for multiline entries.
16+
subtext:
17+
18+
# If your change doesn't affect end users or the exported elements of any package,
19+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
20+
# Optional: The change log or logs in which this entry should be included.
21+
# e.g. '[user]' or '[user, api]'
22+
# Include 'user' if the change is relevant to end users.
23+
# Include 'api' if there is a change to a library API.
24+
# Default: '[user]'
25+
change_logs: []

internal/k8sconfig/config.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ type APIConfig struct {
5454
// token provided to the agent pod), or `kubeConfig` to use credentials
5555
// from `~/.kube/config`.
5656
AuthType AuthType `mapstructure:"auth_type"`
57+
58+
// When using auth_type `kubeConfig`, override the current context.
59+
Context string `mapstructure:"context"`
5760
}
5861

5962
// Validate validates the K8s API config
@@ -85,6 +88,9 @@ func CreateRestConfig(apiConf APIConfig) (*rest.Config, error) {
8588
case AuthTypeKubeConfig:
8689
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
8790
configOverrides := &clientcmd.ConfigOverrides{}
91+
if apiConf.Context != "" {
92+
configOverrides.CurrentContext = apiConf.Context
93+
}
8894
authConf, err = clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
8995
loadingRules, configOverrides).ClientConfig()
9096

internal/kubelet/client_test.go

Lines changed: 52 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -154,37 +154,59 @@ func TestSAClientBadTLS(t *testing.T) {
154154
}
155155

156156
func TestNewKubeConfigClient(t *testing.T) {
157-
server := httptest.NewUnstartedServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
158-
// Check if call is authenticated using provided kubeconfig
159-
require.Equal(t, req.Header.Get("Authorization"), "Bearer my-token")
160-
require.Equal(t, "/api/v1/nodes/nodename/proxy/", req.URL.EscapedPath())
161-
// Send response to be tested
162-
_, err := rw.Write([]byte(`OK`))
163-
require.NoError(t, err)
164-
}))
165-
server.StartTLS()
166-
defer server.Close()
167-
168-
kubeConfig, err := clientcmd.LoadFromFile("testdata/kubeconfig")
169-
require.NoError(t, err)
170-
kubeConfig.Clusters["my-cluster"].Server = "https://" + server.Listener.Addr().String()
171-
tempKubeConfig := filepath.Join(t.TempDir(), "kubeconfig")
172-
require.NoError(t, clientcmd.WriteToFile(*kubeConfig, tempKubeConfig))
173-
t.Setenv("KUBECONFIG", tempKubeConfig)
174-
175-
p, err := NewClientProvider("nodename", &ClientConfig{
176-
APIConfig: k8sconfig.APIConfig{
177-
AuthType: k8sconfig.AuthTypeKubeConfig,
157+
tests := []struct {
158+
name string
159+
cluster string
160+
context string
161+
}{
162+
{
163+
name: "current context",
164+
cluster: "my-cluster-1",
165+
context: "",
178166
},
179-
InsecureSkipVerify: true,
180-
}, zap.NewNop())
181-
require.NoError(t, err)
182-
require.NotNil(t, p)
183-
client, err := p.BuildClient()
184-
require.NoError(t, err)
185-
resp, err := client.Get("/")
186-
require.NoError(t, err)
187-
require.Equal(t, []byte(`OK`), resp)
167+
{
168+
name: "override context",
169+
cluster: "my-cluster-2",
170+
context: "my-context-2",
171+
},
172+
}
173+
174+
for _, tt := range tests {
175+
t.Run(tt.name, func(t *testing.T) {
176+
server := httptest.NewUnstartedServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
177+
// Check if call is authenticated using provided kubeconfig
178+
require.Equal(t, req.Header.Get("Authorization"), "Bearer my-token")
179+
require.Equal(t, "/api/v1/nodes/nodename/proxy/", req.URL.EscapedPath())
180+
// Send response to be tested
181+
_, err := rw.Write([]byte(`OK`))
182+
require.NoError(t, err)
183+
}))
184+
server.StartTLS()
185+
defer server.Close()
186+
187+
kubeConfig, err := clientcmd.LoadFromFile("testdata/kubeconfig")
188+
require.NoError(t, err)
189+
kubeConfig.Clusters[tt.cluster].Server = "https://" + server.Listener.Addr().String()
190+
tempKubeConfig := filepath.Join(t.TempDir(), "kubeconfig")
191+
require.NoError(t, clientcmd.WriteToFile(*kubeConfig, tempKubeConfig))
192+
t.Setenv("KUBECONFIG", tempKubeConfig)
193+
194+
p, err := NewClientProvider("nodename", &ClientConfig{
195+
APIConfig: k8sconfig.APIConfig{
196+
AuthType: k8sconfig.AuthTypeKubeConfig,
197+
Context: tt.context,
198+
},
199+
InsecureSkipVerify: true,
200+
}, zap.NewNop())
201+
require.NoError(t, err)
202+
require.NotNil(t, p)
203+
client, err := p.BuildClient()
204+
require.NoError(t, err)
205+
resp, err := client.Get("/")
206+
require.NoError(t, err)
207+
require.Equal(t, []byte(`OK`), resp)
208+
})
209+
}
188210
}
189211

190212
func TestBuildEndpoint(t *testing.T) {

internal/kubelet/testdata/kubeconfig

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,24 @@ clusters:
55
- cluster:
66
certificate-authority-data: Y2VydA==
77
server: https://my-cluster.address
8-
name: my-cluster
8+
name: my-cluster-1
9+
- cluster:
10+
certificate-authority-data: Y2VydA==
11+
server: https://my-cluster.address
12+
name: my-cluster-2
913
contexts:
1014
- context:
11-
cluster: my-cluster
15+
cluster: my-cluster-1
16+
namespace: my-namespace
17+
user: my-user
18+
name: my-context-1
19+
- context:
20+
cluster: my-cluster-2
1221
namespace: my-namespace
1322
user: my-user
14-
name: my-context
15-
current-context: my-context
23+
name: my-context-2
24+
25+
current-context: my-context-1
1626
users:
1727
- name: my-user
1828
user:

receiver/kubeletstatsreceiver/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ receivers:
132132
kubeletstats:
133133
collection_interval: 20s
134134
auth_type: "kubeConfig"
135+
context: "my-context"
135136
insecure_skip_verify: true
136137
endpoint: "${env:K8S_NODE_NAME}"
137138
exporters:
@@ -145,6 +146,7 @@ service:
145146
```
146147
Note that using `auth_type` `kubeConfig`, the endpoint should only be the node name as the communication to the kubelet is proxied by the API server configured in the `kubeConfig`.
147148
`insecure_skip_verify` still applies by overriding the `kubeConfig` settings.
149+
If no `context` is specified, the current context or the default context is used.
148150

149151
### Extra metadata labels
150152

0 commit comments

Comments
 (0)