func filterInvalidPods(pods []*api.Pod, source string, recorder record.EventRecorder) (filtered []*api.Pod) { names := sets.String{} for i, pod := range pods { var errlist field.ErrorList if errs := validation.ValidatePod(pod); len(errs) != 0 { errlist = append(errlist, errs...) // If validation fails, don't trust it any further - // even Name could be bad. } else { name := kubecontainer.GetPodFullName(pod) if names.Has(name) { // TODO: when validation becomes versioned, this gets a bit // more complicated. errlist = append(errlist, field.Duplicate(field.NewPath("metadata", "name"), pod.Name)) } else { names.Insert(name) } } if len(errlist) > 0 { name := bestPodIdentString(pod) err := errlist.ToAggregate() glog.Warningf("Pod[%d] (%s) from %s failed validation, ignoring: %v", i+1, name, source, err) recorder.Eventf(pod, api.EventTypeWarning, kubecontainer.FailedValidation, "Error validating pod %s from %s, ignoring: %v", name, source, err) continue } filtered = append(filtered, pod) } return }
// Handles kubernetes pod/container stats requests to: // /stats/<pod name>/<container name> // /stats/<namespace>/<pod name>/<uid>/<container name> func (h *handler) handlePodContainer(request *restful.Request, response *restful.Response) { query, err := parseStatsRequest(request) if err != nil { handleError(response, request.Request.URL.String(), err) return } // Default parameters. params := map[string]string{ "namespace": api.NamespaceDefault, "uid": "", } for k, v := range request.PathParameters() { params[k] = v } if params["podName"] == "" || params["containerName"] == "" { response.WriteErrorString(http.StatusBadRequest, fmt.Sprintf("Invalid pod container request: %v", params)) return } pod, ok := h.provider.GetPodByName(params["namespace"], params["podName"]) if !ok { glog.V(4).Infof("Container not found: %v", params) response.WriteError(http.StatusNotFound, kubecontainer.ErrContainerNotFound) return } stats, err := h.provider.GetContainerInfo( kubecontainer.GetPodFullName(pod), types.UID(params["uid"]), params["containerName"], query.cadvisorRequest()) if err != nil { handleError(response, fmt.Sprintf("%s %v", request.Request.URL.String(), query), err) return } writeResponse(response, stats) }
func (s *podStorage) merge(source string, change interface{}) (adds, updates, deletes, reconciles *kubetypes.PodUpdate) { s.podLock.Lock() defer s.podLock.Unlock() addPods := []*api.Pod{} updatePods := []*api.Pod{} deletePods := []*api.Pod{} reconcilePods := []*api.Pod{} pods := s.pods[source] if pods == nil { pods = make(map[string]*api.Pod) } // updatePodFunc is the local function which updates the pod cache *oldPods* with new pods *newPods*. // After updated, new pod will be stored in the pod cache *pods*. // Notice that *pods* and *oldPods* could be the same cache. updatePodsFunc := func(newPods []*api.Pod, oldPods, pods map[string]*api.Pod) { filtered := filterInvalidPods(newPods, source, s.recorder) for _, ref := range filtered { name := kubecontainer.GetPodFullName(ref) // Annotate the pod with the source before any comparison. if ref.Annotations == nil { ref.Annotations = make(map[string]string) } ref.Annotations[kubetypes.ConfigSourceAnnotationKey] = source if existing, found := oldPods[name]; found { pods[name] = existing needUpdate, needReconcile := checkAndUpdatePod(existing, ref) if needUpdate { updatePods = append(updatePods, existing) } else if needReconcile { reconcilePods = append(reconcilePods, existing) } continue } recordFirstSeenTime(ref) pods[name] = ref addPods = append(addPods, ref) } } update := change.(kubetypes.PodUpdate) switch update.Op { case kubetypes.ADD, kubetypes.UPDATE: if update.Op == kubetypes.ADD { glog.V(4).Infof("Adding new pods from source %s : %v", source, update.Pods) } else { glog.V(4).Infof("Updating pods from source %s : %v", source, update.Pods) } updatePodsFunc(update.Pods, pods, pods) case kubetypes.REMOVE: glog.V(4).Infof("Removing a pod %v", update) for _, value := range update.Pods { name := kubecontainer.GetPodFullName(value) if existing, found := pods[name]; found { // this is a delete delete(pods, name) deletePods = append(deletePods, existing) continue } // this is a no-op } case kubetypes.SET: glog.V(4).Infof("Setting pods for source %s", source) s.markSourceSet(source) // Clear the old map entries by just creating a new map oldPods := pods pods = make(map[string]*api.Pod) updatePodsFunc(update.Pods, oldPods, pods) for name, existing := range oldPods { if _, found := pods[name]; !found { // this is a delete deletePods = append(deletePods, existing) } } default: glog.Warningf("Received invalid update type: %v", update) } s.pods[source] = pods adds = &kubetypes.PodUpdate{Op: kubetypes.ADD, Pods: copyPods(addPods), Source: source} updates = &kubetypes.PodUpdate{Op: kubetypes.UPDATE, Pods: copyPods(updatePods), Source: source} deletes = &kubetypes.PodUpdate{Op: kubetypes.REMOVE, Pods: copyPods(deletePods), Source: source} reconciles = &kubetypes.PodUpdate{Op: kubetypes.RECONCILE, Pods: copyPods(reconcilePods), Source: source} return adds, updates, deletes, reconciles }