func addPods(store cache.Store, namespace string, nPods int, nPorts int) { for i := 0; i < nPods; i++ { p := &api.Pod{ TypeMeta: api.TypeMeta{APIVersion: testapi.Version()}, ObjectMeta: api.ObjectMeta{ Namespace: namespace, Name: fmt.Sprintf("pod%d", i), Labels: map[string]string{"foo": "bar"}, }, Spec: api.PodSpec{ Containers: []api.Container{{Ports: []api.ContainerPort{}}}, }, Status: api.PodStatus{ PodIP: fmt.Sprintf("1.2.3.%d", 4+i), Conditions: []api.PodCondition{ { Type: api.PodReady, Status: api.ConditionTrue, }, }, }, } for j := 0; j < nPorts; j++ { p.Spec.Containers[0].Ports = append(p.Spec.Containers[0].Ports, api.ContainerPort{Name: fmt.Sprintf("port%d", i), ContainerPort: 8080 + j}) } store.Add(p) } }
// cacheReviewRecord updates the cache based on the request processed func cacheReviewRecord(request *reviewRequest, lastKnownValue *reviewRecord, review Review, reviewRecordStore cache.Store) { reviewRecord := &reviewRecord{ reviewRequest: &reviewRequest{namespace: request.namespace, policyUIDToResourceVersion: map[types.UID]string{}, policyBindingUIDToResourceVersion: map[types.UID]string{}}, groups: review.Groups(), users: review.Users(), } // keep what we last believe we knew by default if lastKnownValue != nil { reviewRecord.namespaceResourceVersion = lastKnownValue.namespaceResourceVersion for k, v := range lastKnownValue.policyUIDToResourceVersion { reviewRecord.policyUIDToResourceVersion[k] = v } for k, v := range lastKnownValue.policyBindingUIDToResourceVersion { reviewRecord.policyBindingUIDToResourceVersion[k] = v } } // update the review record relative to what drove this request if len(request.namespaceResourceVersion) > 0 { reviewRecord.namespaceResourceVersion = request.namespaceResourceVersion } for k, v := range request.policyUIDToResourceVersion { reviewRecord.policyUIDToResourceVersion[k] = v } for k, v := range request.policyBindingUIDToResourceVersion { reviewRecord.policyBindingUIDToResourceVersion[k] = v } // update the cache record reviewRecordStore.Add(reviewRecord) }
// Wait till the passFunc confirms that the object it expects to see is in the store. // Used to observe reflected events. func waitForReflection(s cache.Store, key string, passFunc func(n interface{}) bool) error { return wait.Poll(time.Millisecond*10, time.Second*20, func() (bool, error) { if n, _, err := s.GetByKey(key); err == nil && passFunc(n) { return true, nil } return false, nil }) }
func lastKnown(reviewRecordStore cache.Store, namespace string) (*reviewRecord, error) { obj, exists, err := reviewRecordStore.GetByKey(namespace) if err != nil { return nil, err } if exists { return obj.(*reviewRecord), nil } return nil, nil }
// purgeDeletedNamespaces will remove all namespaces enumerated in a reviewRecordStore that are not in the namespace set func purgeDeletedNamespaces(namespaceSet *util.StringSet, userSubjectRecordStore cache.Store, groupSubjectRecordStore cache.Store, reviewRecordStore cache.Store) { reviewRecordItems := reviewRecordStore.List() for i := range reviewRecordItems { reviewRecord := reviewRecordItems[i].(*reviewRecord) if !namespaceSet.Has(reviewRecord.namespace) { deleteNamespaceFromSubjects(userSubjectRecordStore, reviewRecord.users, reviewRecord.namespace) deleteNamespaceFromSubjects(groupSubjectRecordStore, reviewRecord.groups, reviewRecord.namespace) reviewRecordStore.Delete(reviewRecord) } } }
// deleteNamespaceFromSubjects removes the namespace from each subject // if no other namespaces are active to that subject, it will also delete the subject from the cache entirely func deleteNamespaceFromSubjects(subjectRecordStore cache.Store, subjects []string, namespace string) { for _, subject := range subjects { obj, exists, _ := subjectRecordStore.GetByKey(subject) if exists { subjectRecord := obj.(*subjectRecord) delete(subjectRecord.namespaces, namespace) if len(subjectRecord.namespaces) == 0 { subjectRecordStore.Delete(subjectRecord) } } } }
// addSubjectsToNamespace adds the specified namespace to each subject func addSubjectsToNamespace(subjectRecordStore cache.Store, subjects []string, namespace string) { for _, subject := range subjects { var item *subjectRecord obj, exists, _ := subjectRecordStore.GetByKey(subject) if exists { item = obj.(*subjectRecord) } else { item = &subjectRecord{subject: subject, namespaces: util.NewStringSet()} subjectRecordStore.Add(item) } item.namespaces.Insert(namespace) } }
// getMatchingSecurityContextConstraints returns constraints from the store that match the group, // uid, or user of the service account. func getMatchingSecurityContextConstraints(store cache.Store, userInfo user.Info) ([]*kapi.SecurityContextConstraints, error) { matchedConstraints := make([]*kapi.SecurityContextConstraints, 0) for _, c := range store.List() { constraint, ok := c.(*kapi.SecurityContextConstraints) if !ok { return nil, errors.NewInternalError(fmt.Errorf("error converting object from store to a security context constraint: %v", c)) } if constraintAppliesTo(constraint, userInfo) { matchedConstraints = append(matchedConstraints, constraint) } } return matchedConstraints, nil }
// create count pods with the given phase for the given rc (same selectors and namespace), and add them to the store. func newPodList(store cache.Store, count int, status api.PodPhase, rc *api.ReplicationController) *api.PodList { pods := []api.Pod{} for i := 0; i < count; i++ { newPod := api.Pod{ ObjectMeta: api.ObjectMeta{ Name: fmt.Sprintf("pod%d", i), Labels: rc.Spec.Selector, Namespace: rc.Namespace, }, Status: api.PodStatus{Phase: status}, } if store != nil { store.Add(&newPod) } pods = append(pods, newPod) } return &api.PodList{ Items: pods, } }