func deletePodsForOldHosts(c *client.Client, ns string, annotations map[string]string, pods *api.PodList, hostEntries []HostEntry) { for annKey, podName := range annotations { if strings.HasPrefix(annKey, AnsibleHostPodAnnotationPrefix) { hostName := annKey[len(AnsibleHostPodAnnotationPrefix):] if k8s.PodIsRunning(pods, podName) { hostEntry := getHostEntryByName(hostEntries, hostName) if hostEntry == nil { log.Info("Deleting pod %s as there is no longer an Ansible inventory host called %s", podName, hostName) c.Pods(ns).Delete(podName, nil) } } } } }
// ChooseHostAndPrivateKey parses the given Ansbile inventory file for the hosts // and chooses a single host inside it, returning the host name and the private key func ChooseHostAndPrivateKey(inventoryFile string, hosts string, c *client.Client, ns string, rcName string) (*HostEntry, error) { hostEntries, err := LoadHostEntries(inventoryFile, hosts) if err != nil { return nil, err } log.Info("Found %d host entries", len(hostEntries)) // lets pick a random entry if len(hostEntries) > 0 { thisPodName := os.Getenv("HOSTNAME") if len(thisPodName) == 0 { return nil, fmt.Errorf("Could not find the pod name using $HOSTNAME!") } retryAttempts := 20 for i := 0; i < retryAttempts; i++ { if i > 0 { // lets sleep before retrying time.Sleep(time.Duration(random(1000, 20000)) * time.Millisecond) } if c == nil { return nil, fmt.Errorf("No Kubernetes Client specified!") } rc, err := c.ReplicationControllers(ns).Get(rcName) if err != nil { return nil, err } if rc == nil { return nil, fmt.Errorf("No ReplicationController found for name %s", rcName) } pods, err := c.Pods(ns).List(nil, nil) if err != nil { return nil, err } metadata := &rc.ObjectMeta resourceVersion := metadata.ResourceVersion if metadata.Annotations == nil { metadata.Annotations = make(map[string]string) } annotations := metadata.Annotations log.Info("found RC with name %s.%s and version %s", ns, rcName, resourceVersion) filteredHostEntries := hostEntries for annKey, podName := range annotations { if strings.HasPrefix(annKey, AnsibleHostPodAnnotationPrefix) { hostName := annKey[len(AnsibleHostPodAnnotationPrefix):] if k8s.PodIsRunning(pods, podName) { if podName != thisPodName { log.Info("Pod %s podName has already claimed host %s", podName, hostName) filteredHostEntries = removeHostEntry(filteredHostEntries, hostName) } } else { // lets remove this annotation as the pod is no longer valid log.Info("Pod %s is no longer running so removing the annotation %s", podName, annKey) delete(metadata.Annotations, annKey) } } } count := len(filteredHostEntries) if count == 0 { log.Info("There are no more hosts available to be supervised by this pod!") return nil, fmt.Errorf("No more hosts available to be supervised!") } log.Info("After filtering out hosts owned by other pods we have %v host entries left", count) pickedEntry := filteredHostEntries[random(0, count)] hostName := pickedEntry.Name if len(pickedEntry.Host) == 0 { return nil, fmt.Errorf("Could not find host name for entry %s", pickedEntry.Name) } if len(pickedEntry.PrivateKey) == 0 { return nil, fmt.Errorf("Could not find PrivateKey for entry %s", pickedEntry.Name) } if len(pickedEntry.User) == 0 { return nil, fmt.Errorf("Could not find User for entry %s", pickedEntry.Name) } // lets try pick this pod annotations[AnsibleHostPodAnnotationPrefix+hostName] = thisPodName _, err = c.ReplicationControllers(ns).Update(rc) if err != nil { log.Info("Failed to update the RC, could be concurrent update failure: %s", err) } else { log.Info("Picked host " + pickedEntry.Host) return &pickedEntry, nil } } } return nil, fmt.Errorf("Could not find any hosts for inventory file %s and hosts %s", inventoryFile, hosts) }