mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-28 14:07:14 +00:00
include description of what kube-root-ca.crt can be used to verify
This commit is contained in:
parent
11f95dc047
commit
443e4ea0df
@ -38,7 +38,12 @@ import (
|
||||
|
||||
// RootCACertConfigMapName is name of the configmap which stores certificates
|
||||
// to access api-server
|
||||
const RootCACertConfigMapName = "kube-root-ca.crt"
|
||||
const (
|
||||
RootCACertConfigMapName = "kube-root-ca.crt"
|
||||
DescriptionAnnotation = "kubernetes.io/description"
|
||||
Description = "Contains a CA bundle that can be used to verify the kube-apiserver when using internal endpoints such as the internal service IP or kubernetes.default.svc. " +
|
||||
"No other usage is guaranteed across distributions of Kubernetes clusters."
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerMetrics()
|
||||
@ -186,7 +191,8 @@ func (c *Publisher) syncNamespace(ns string) (err error) {
|
||||
case apierrors.IsNotFound(err):
|
||||
_, err = c.client.CoreV1().ConfigMaps(ns).Create(context.TODO(), &v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: RootCACertConfigMapName,
|
||||
Name: RootCACertConfigMapName,
|
||||
Annotations: map[string]string{DescriptionAnnotation: Description},
|
||||
},
|
||||
Data: map[string]string{
|
||||
"ca.crt": string(c.rootCA),
|
||||
@ -205,13 +211,18 @@ func (c *Publisher) syncNamespace(ns string) (err error) {
|
||||
"ca.crt": string(c.rootCA),
|
||||
}
|
||||
|
||||
if reflect.DeepEqual(cm.Data, data) {
|
||||
// ensure the data and the one annotation describing usage of this configmap match.
|
||||
if reflect.DeepEqual(cm.Data, data) && len(cm.Annotations[DescriptionAnnotation]) > 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// copy so we don't modify the cache's instance of the configmap
|
||||
cm = cm.DeepCopy()
|
||||
cm.Data = data
|
||||
if cm.Annotations == nil {
|
||||
cm.Annotations = map[string]string{}
|
||||
}
|
||||
cm.Annotations[DescriptionAnnotation] = Description
|
||||
|
||||
_, err = c.client.CoreV1().ConfigMaps(ns).Update(context.TODO(), cm, metav1.UpdateOptions{})
|
||||
return err
|
||||
|
@ -22,9 +22,13 @@ import (
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
corev1listers "k8s.io/client-go/listers/core/v1"
|
||||
clienttesting "k8s.io/client-go/testing"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
)
|
||||
|
||||
@ -175,3 +179,96 @@ func defaultCrtConfigMapPtr(rootCA []byte) *v1.ConfigMap {
|
||||
tmp.Namespace = metav1.NamespaceDefault
|
||||
return &tmp
|
||||
}
|
||||
|
||||
func TestConfigMapUpdateNoHotLoop(t *testing.T) {
|
||||
testcases := map[string]struct {
|
||||
ExistingConfigMaps []runtime.Object
|
||||
ExpectActions func(t *testing.T, actions []clienttesting.Action)
|
||||
}{
|
||||
"update-configmap-annotation": {
|
||||
ExistingConfigMaps: []runtime.Object{
|
||||
&v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: RootCACertConfigMapName,
|
||||
},
|
||||
Data: map[string]string{"ca.crt": "fake"},
|
||||
},
|
||||
},
|
||||
ExpectActions: func(t *testing.T, actions []clienttesting.Action) {
|
||||
if len(actions) != 1 {
|
||||
t.Fatal(actions)
|
||||
}
|
||||
if actions[0].GetVerb() != "update" {
|
||||
t.Fatal(actions)
|
||||
}
|
||||
actualObj := actions[0].(clienttesting.UpdateAction).GetObject()
|
||||
if actualObj.(*v1.ConfigMap).Annotations[DescriptionAnnotation] != Description {
|
||||
t.Fatal(actions)
|
||||
}
|
||||
if !reflect.DeepEqual(actualObj.(*v1.ConfigMap).Data["ca.crt"], "fake") {
|
||||
t.Fatal(actions)
|
||||
}
|
||||
},
|
||||
},
|
||||
"no-update-configmap-if-annotation-present-and-equal": {
|
||||
ExistingConfigMaps: []runtime.Object{
|
||||
&v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: RootCACertConfigMapName,
|
||||
Annotations: map[string]string{DescriptionAnnotation: Description},
|
||||
},
|
||||
Data: map[string]string{"ca.crt": "fake"},
|
||||
},
|
||||
},
|
||||
ExpectActions: func(t *testing.T, actions []clienttesting.Action) {
|
||||
if len(actions) != 0 {
|
||||
t.Fatal(actions)
|
||||
}
|
||||
},
|
||||
},
|
||||
"no-update-configmap-if-annotation-present-and-different": {
|
||||
ExistingConfigMaps: []runtime.Object{
|
||||
&v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: RootCACertConfigMapName,
|
||||
Annotations: map[string]string{DescriptionAnnotation: "different"},
|
||||
},
|
||||
Data: map[string]string{"ca.crt": "fake"},
|
||||
},
|
||||
},
|
||||
ExpectActions: func(t *testing.T, actions []clienttesting.Action) {
|
||||
if len(actions) != 0 {
|
||||
t.Fatal(actions)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for k, tc := range testcases {
|
||||
t.Run(k, func(t *testing.T) {
|
||||
client := fake.NewSimpleClientset(tc.ExistingConfigMaps...)
|
||||
configMapIndexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
|
||||
for _, obj := range tc.ExistingConfigMaps {
|
||||
configMapIndexer.Add(obj)
|
||||
}
|
||||
|
||||
// Publisher manages certificate ConfigMap objects inside Namespaces
|
||||
controller := Publisher{
|
||||
client: client,
|
||||
rootCA: []byte("fake"),
|
||||
cmLister: corev1listers.NewConfigMapLister(configMapIndexer),
|
||||
cmListerSynced: func() bool { return true },
|
||||
nsListerSynced: func() bool { return true },
|
||||
}
|
||||
|
||||
err := controller.syncNamespace("default")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tc.ExpectActions(t, client.Actions())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user