mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 06:27:05 +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
|
// RootCACertConfigMapName is name of the configmap which stores certificates
|
||||||
// to access api-server
|
// 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() {
|
func init() {
|
||||||
registerMetrics()
|
registerMetrics()
|
||||||
@ -186,7 +191,8 @@ func (c *Publisher) syncNamespace(ns string) (err error) {
|
|||||||
case apierrors.IsNotFound(err):
|
case apierrors.IsNotFound(err):
|
||||||
_, err = c.client.CoreV1().ConfigMaps(ns).Create(context.TODO(), &v1.ConfigMap{
|
_, err = c.client.CoreV1().ConfigMaps(ns).Create(context.TODO(), &v1.ConfigMap{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: RootCACertConfigMapName,
|
Name: RootCACertConfigMapName,
|
||||||
|
Annotations: map[string]string{DescriptionAnnotation: Description},
|
||||||
},
|
},
|
||||||
Data: map[string]string{
|
Data: map[string]string{
|
||||||
"ca.crt": string(c.rootCA),
|
"ca.crt": string(c.rootCA),
|
||||||
@ -205,13 +211,18 @@ func (c *Publisher) syncNamespace(ns string) (err error) {
|
|||||||
"ca.crt": string(c.rootCA),
|
"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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy so we don't modify the cache's instance of the configmap
|
// copy so we don't modify the cache's instance of the configmap
|
||||||
cm = cm.DeepCopy()
|
cm = cm.DeepCopy()
|
||||||
cm.Data = data
|
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{})
|
_, err = c.client.CoreV1().ConfigMaps(ns).Update(context.TODO(), cm, metav1.UpdateOptions{})
|
||||||
return err
|
return err
|
||||||
|
@ -22,9 +22,13 @@ import (
|
|||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/diff"
|
"k8s.io/apimachinery/pkg/util/diff"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"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"
|
"k8s.io/kubernetes/pkg/controller"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -175,3 +179,96 @@ func defaultCrtConfigMapPtr(rootCA []byte) *v1.ConfigMap {
|
|||||||
tmp.Namespace = metav1.NamespaceDefault
|
tmp.Namespace = metav1.NamespaceDefault
|
||||||
return &tmp
|
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