type Filter … // At time of writing, in practice this is called with a slice with only // one entry, the node also referred to be the resource in the Referrer field. func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) { … } // The node passed in here is the same node as held in Referrer; // that's how the referrer's name field is updated. // Currently, however, this filter still needs the extra methods on Referrer // to consult things like the resource Id, its namespace, etc. // TODO(3455): No filter should use the Resource api; all information // about names should come from annotations, with helper methods // on the RNode object. Resource should get stupider, RNode smarter. func (f Filter) run(node *yaml.RNode) (*yaml.RNode, error) { … } // This function is called on the node found at FieldSpec.Path. // It's some node in the Referrer. func (f Filter) set(node *yaml.RNode) error { … } // This method used when NameFieldToUpdate doesn't lead to // one scalar field (typically called 'name'), but rather // leads to a map field (called anything). In this case we // must complete the field path, looking for both a 'name' // and a 'namespace' field to help select the proper // ReferralTarget to read the name and namespace from. func (f Filter) setMapping(node *yaml.RNode) error { … } func (f Filter) filterMapCandidatesByNamespace( node *yaml.RNode) ([]*resource.Resource, error) { … } func (f Filter) setScalar(node *yaml.RNode) error { … } // In the resource, make a note that it is referred to by the Referrer. func (f Filter) recordTheReferral(referral *resource.Resource) { … } // getRoleRefGvk returns a Gvk in the roleRef field. Return error // if the roleRef, roleRef/apiGroup or roleRef/kind is missing. func getRoleRefGvk(n *resource.Resource) (*resid.Gvk, error) { … } type sieveFunc … // doSieve uses a function to accept or ignore resources from a list. // If list is nil, returns immediately. // It's a filter obviously, but that term is overloaded here. func doSieve(list []*resource.Resource, fn sieveFunc) (s []*resource.Resource) { … } func acceptAll(r *resource.Resource) bool { … } func previousNameMatches(name string) sieveFunc { … } func previousIdSelectedByGvk(gvk *resid.Gvk) sieveFunc { … } // If the we are updating a 'roleRef/name' field, the 'apiGroup' and 'kind' // fields in the same 'roleRef' map must be considered. // If either object is cluster-scoped, there can be a referral. // E.g. a RoleBinding (which exists in a namespace) can refer // to a ClusterRole (cluster-scoped) object. // https://kubernetes.io/docs/reference/access-authn-authz/rbac/#role-and-clusterrole // Likewise, a ClusterRole can refer to a Secret (in a namespace). // Objects in different namespaces generally cannot refer to other // with some exceptions (e.g. RoleBinding and ServiceAccount are both // namespaceable, but the former can refer to accounts in other namespaces). func (f Filter) roleRefFilter() sieveFunc { … } func prefixSuffixEquals(other resource.ResCtx, allowEmpty bool) sieveFunc { … } func (f Filter) sameCurrentNamespaceAsReferrer() sieveFunc { … } // selectReferral picks the best referral from a list of candidates. func (f Filter) selectReferral( // The name referral that may need to be updated. oldName string, candidates []*resource.Resource, // function that returns whether two referrals are identical for the purposes of the transformation candidatesIdentical func(resources []*resource.Resource) bool) (*resource.Resource, error) { … } func (f Filter) failureDetails(resources []*resource.Resource) string { … } func allNamesAreTheSame(resources []*resource.Resource) bool { … } func allNamesAndNamespacesAreTheSame(resources []*resource.Resource) bool { … } func getIds(rs []*resource.Resource) string { … } func checkEqual(k, a, b string) error { … } func (f Filter) confirmNodeMatchesReferrer(node *yaml.RNode) error { … }