Beispiel #1
0
func ensureSCCExists(ns string, serviceAccountName string) error {
	binary, err := exec.LookPath("oc")
	if err != nil {
		// no openshift so ignore
		return nil
	}

	text, err := getCommandOutputString(binary, []string{"export", "scc", serviceAccountName}, os.Stdin)
	if err != nil {
		log.Debug("Failed to get SecurityContextConstraints %s. %s", serviceAccountName, err)
	}
	if err != nil || len(text) == 0 {
		text = `
apiVersion: v1
kind: SecurityContextConstraints
groups:
- system:cluster-admins
- system:nodes
metadata:
  creationTimestamp: null
  name: ` + serviceAccountName + `
runAsUser:
  type: RunAsAny
seLinuxContext:
  type: RunAsAny
supplementalGroups:
  type: RunAsAny
users:
`
	}
	// lets ensure there's a users section
	if !strings.Contains(text, "\nusers:") {
		text = text + "\nusers:\n"
	}

	line := "system:serviceaccount:" + ns + ":" + serviceAccountName

	if strings.Contains(text, line) {
		log.Info("No need to modify SecurityContextConstraints as it already contains line for namespace %s and service account %s", ns, serviceAccountName)
		return nil
	}

	text = text + "\n- " + line + "\n"
	log.Debug("created SecurityContextConstraints YAML: %s", text)

	log.Info("Applying changes for SecurityContextConstraints %s for namespace %s and ServiceAccount %s", serviceAccountName, ns, serviceAccountName)
	reader := bytes.NewReader([]byte(text))
	err = runCommand(binary, []string{"apply", "-f", "-"}, reader)
	if err != nil {
		log.Err("Failed to update OpenShift SecurityContextConstraints named %s. %s", serviceAccountName, err)
	}
	return err
}
Beispiel #2
0
func osExpandAndVerifyGlobal(c *cli.Context, name string) (string, error) {
	flag := c.GlobalString(name)
	value := os.ExpandEnv(flag)
	if len(value) == 0 {
		return "", fmt.Errorf("No parameter supplied for: %s", name)
	}
	log.Debug("flag %s is %s", name, value)
	return value, nil
}
Beispiel #3
0
// ChooseHostAndPrivateKey parses the given Ansible inventory file for the hosts
// and chooses a single host inside it, returning the host name and the private key
func ChooseHostAndPrivateKey(thisPodName string, hosts string, c *client.Client, ns string, rcName string) (*HostEntry, *api.ReplicationController, map[string]string, error) {
	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, nil, nil, fmt.Errorf("No Kubernetes Client specified!")
		}
		rc, err := c.ReplicationControllers(ns).Get(rcName)
		if err != nil {
			return nil, nil, nil, err
		}
		if rc == nil {
			return nil, nil, nil, fmt.Errorf("No ReplicationController found for name %s", rcName)
		}

		pods, err := c.Pods(ns).List(api.ListOptions{})
		if err != nil {
			return nil, nil, nil, err
		}

		metadata := &rc.ObjectMeta
		resourceVersion := metadata.ResourceVersion
		if metadata.Annotations == nil {
			metadata.Annotations = make(map[string]string)
		}
		annotations := metadata.Annotations
		log.Info("Using ReplicationController with namespace %s name %s and version %s", ns, rcName, resourceVersion)

		hostsText := annotations[HostInventoryAnnotation]
		if len(hostsText) == 0 {
			return nil, nil, nil, fmt.Errorf("Could not find annotation %s on ReplicationController %s", HostInventoryAnnotation, rcName)
		}
		hostEntries, err := LoadHostEntriesFromText(hostsText)
		if err != nil {
			return nil, nil, nil, err
		}
		log.Info("Found %d host entries", len(hostEntries))

		// lets pick a random entry
		if len(hostEntries) > 0 {
			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, nil, 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, nil, nil, fmt.Errorf("Could not find host name for entry %s", pickedEntry.Name)
			}
			if len(pickedEntry.User) == 0 {
				return nil, nil, nil, fmt.Errorf("Could not find User for entry %s", pickedEntry.Name)
			}

			// lets try pick this pod
			annotations[AnsibleHostPodAnnotationPrefix+hostName] = thisPodName

			rc, 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)

				// lets update the Pod with the host name label
				podClient := c.Pods(ns)
				pod, err := podClient.Get(thisPodName)
				if err != nil {
					return pickedEntry, nil, nil, err
				}
				metadata := &pod.ObjectMeta
				if metadata.Annotations == nil {
					metadata.Annotations = make(map[string]string)
				}
				metadata.Annotations[HostNameAnnotation] = pickedEntry.Name
				metadata.Annotations[HostAddressAnnotation] = pickedEntry.Host
				//pod.Status = api.PodStatus{}
				pod, err = podClient.UpdateStatus(pod)
				if err != nil {
					return pickedEntry, nil, nil, err
				}

				// lets export required environment variables
				exportEnvVars := os.Getenv(EnvExportEnvVars)
				envVars := make(map[string]string)
				if len(exportEnvVars) > 0 {
					names := strings.Split(exportEnvVars, " ")
					for _, name := range names {
						name = strings.TrimSpace(name)
						if len(name) > 0 {
							value := os.Getenv(name)
							if len(value) > 0 {
								envVars[name] = value
								log.Debug("Exporting environment variable %s = %s", name, value)
							}
						}
					}
				}

				err = forwardPorts(pod, pickedEntry)
				return pickedEntry, rc, envVars, err
			}
		}
	}
	return nil, nil, nil, fmt.Errorf("Could not find any available hosts on the ReplicationController %s and hosts %s", rcName, hosts)
}
Beispiel #4
0
func osExpand(c *cli.Context, name string) string {
	flag := c.String(name)
	value := os.ExpandEnv(flag)
	log.Debug("flag %s is %s", name, value)
	return value
}