diff --git a/prog/kube-peers/annotations.go b/prog/kube-peers/annotations.go index 86915618..20b45cdd 100644 --- a/prog/kube-peers/annotations.go +++ b/prog/kube-peers/annotations.go @@ -73,8 +73,10 @@ const ( retryPeriod = time.Second * 2 jitterFactor = 1.0 + // Prefix all our annotation keys with this string so they don't clash with anyone else's + KubePeersPrefix = "kube-peers.weave.works/" // KubePeersAnnotationKey is the default annotation key - KubePeersAnnotationKey = "kube-peers.weave.works/peers" + KubePeersAnnotationKey = KubePeersPrefix + "peers" ) func (cml *configMapAnnotations) Init() error { @@ -130,13 +132,32 @@ func (cml *configMapAnnotations) UpdatePeerList(list peerList) error { return cml.UpdateAnnotation(KubePeersAnnotationKey, string(recordBytes)) } +// Clean up a string so it meets the Kubernetes requiremements for Annotation keys: +// name part must consist of alphanumeric characters, '-', '_' or '.', and must +// start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or '123-abc') +func cleanKey(key string) string { + buf := []byte(key) + for i, c := range buf { + if (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.' || c == '/' { + continue + } + buf[i] = '_' + } + return string(buf) +} + +func (cml *configMapAnnotations) GetAnnotation(key string) (string, bool) { + value, ok := cml.cm.Annotations[cleanKey(key)] + return value, ok +} + func (cml *configMapAnnotations) UpdateAnnotation(key, value string) (err error) { if cml.cm == nil { return errors.New("endpoint not initialized, call Init first") } // speculatively change the state, then replace with whatever comes back // from Update(), which will be the latest on the server whatever happened - cml.cm.Annotations[key] = value + cml.cm.Annotations[cleanKey(key)] = value cml.cm, err = cml.Client.ConfigMaps(cml.Namespace).Update(cml.cm) return err } @@ -147,7 +168,7 @@ func (cml *configMapAnnotations) RemoveAnnotation(key string) (err error) { } // speculatively change the state, then replace with whatever comes back // from Update(), which will be the latest on the server whatever happened - delete(cml.cm.Annotations, key) + delete(cml.cm.Annotations, cleanKey(key)) cml.cm, err = cml.Client.ConfigMaps(cml.Namespace).Update(cml.cm) return err } @@ -160,7 +181,7 @@ func (cml *configMapAnnotations) RemoveAnnotationsWithValue(valueToRemove string // from Update(), which will be the latest on the server whatever happened for key, value := range cml.cm.Annotations { if value == valueToRemove { - delete(cml.cm.Annotations, key) + delete(cml.cm.Annotations, key) // don't need to clean this key as it came from the map } } cml.cm, err = cml.Client.ConfigMaps(cml.Namespace).Update(cml.cm) diff --git a/prog/kube-peers/main.go b/prog/kube-peers/main.go index 1961f70c..8872a4a6 100644 --- a/prog/kube-peers/main.go +++ b/prog/kube-peers/main.go @@ -122,7 +122,7 @@ func reclaimRemovedPeers(weave *weaveapi.Client, cml *configMapAnnotations, node common.Log.Debugln("[kube-peers] Preparing to remove disappeared peer", peer) okToRemove := false // 3. Check if there is an existing annotation with key X - if existingAnnotation, found := cml.cm.Annotations[peer.PeerName]; found { + if existingAnnotation, found := cml.GetAnnotation(KubePeersPrefix + peer.PeerName); found { common.Log.Debugln("[kube-peers] Existing annotation", existingAnnotation) // 4. If annotation already contains my identity, ok; if existingAnnotation == myPeerName { @@ -131,7 +131,7 @@ func reclaimRemovedPeers(weave *weaveapi.Client, cml *configMapAnnotations, node } else { // 5. If non-existent, write an annotation with key X and contents "my identity" common.Log.Debugln("[kube-peers] Noting I plan to remove ", peer.PeerName) - if err := cml.UpdateAnnotation(peer.PeerName, myPeerName); err == nil { + if err := cml.UpdateAnnotation(KubePeersPrefix+peer.PeerName, myPeerName); err == nil { okToRemove = true } } @@ -155,7 +155,7 @@ func reclaimRemovedPeers(weave *weaveapi.Client, cml *configMapAnnotations, node } common.Log.Infoln("[kube-peers] Removing annotation ", peer.PeerName) // 7b. Remove annotation with key X - return cml.RemoveAnnotation(peer.PeerName) + return cml.RemoveAnnotation(KubePeersPrefix + peer.PeerName) }) common.Log.Debugln("[kube-peers] Finished removal of ", peer.PeerName) }