Skip to content

Commit

Permalink
feat: Support APIService relationships
Browse files Browse the repository at this point in the history
Signed-off-by: Justin Toh <tohjustin@hotmail.com>
  • Loading branch information
tohjustin committed Oct 16, 2021
1 parent 5dc22a1 commit b329c16
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 3 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ monitoring-system └── ServiceAccount/kube-state-metrics
List of supported relationships used for discovering dependent objects:

- Kubernetes
- [APIService References](https://kubernetes.io/docs/reference/kubernetes-api/cluster-resources/api-service-v1/)
- [ClusterRole References](https://kubernetes.io/docs/reference/kubernetes-api/authorization-resources/cluster-role-v1/), [ClusterRoleBinding References](https://kubernetes.io/docs/reference/kubernetes-api/authorization-resources/cluster-role-binding-v1/), [Role References](https://kubernetes.io/docs/reference/kubernetes-api/authorization-resources/role-v1/) & [RoleBinding References](https://kubernetes.io/docs/reference/kubernetes-api/authorization-resources/role-binding-v1/)
- [Controller References](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/controller-ref.md) & [Owner References](https://kubernetes.io/docs/concepts/overview/working-with-objects/owners-dependents/)
- [CSINode References](https://kubernetes.io/docs/reference/kubernetes-api/config-and-storage-resources/csi-node-v1/)
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ require (
k8s.io/cli-runtime v0.22.1
k8s.io/client-go v0.22.1
k8s.io/klog/v2 v2.9.0
k8s.io/kube-aggregator v0.22.1
k8s.io/kubectl v0.22.1
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1469,6 +1469,8 @@ k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.9.0 h1:D7HV+n1V57XeZ0m6tdRkfknthUaM06VFbWldOFh8kzM=
k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
k8s.io/kube-aggregator v0.22.1 h1:hsntyWsnkLiL4ccmoKfqiUVyxnlnqtqPRMuq/mT2wGQ=
k8s.io/kube-aggregator v0.22.1/go.mod h1:VbmI+8fUeCPkzSvarWTrlIGEgUGEGI/66SFajDQ0Pdc=
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM=
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e h1:KLHHjkdQFomZy8+06csTWZ0m1343QqxZhR2LJ1OxCYM=
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
Expand Down
7 changes: 7 additions & 0 deletions internal/graph/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,13 @@ func ResolveDependents(m meta.RESTMapper, objects []unstructuredv1.Unstructured,
klog.V(4).Infof("Failed to get relationships for validatingwebhookconfiguration named \"%s\": %s", node.Name, err)
continue
}
// Populate dependents based on APIService relationships
case node.Group == "apiregistration.k8s.io" && node.Kind == "APIService":
rmap, err = getAPIServiceRelationships(node)
if err != nil {
klog.V(4).Infof("Failed to get relationships for apiservice named \"%s\": %s", node.Name, err)
continue
}
// Populate dependents based on Event relationships
case (node.Group == "events.k8s.io" || node.Group == "") && node.Kind == "Event":
rmap, err = getEventRelationships(node)
Expand Down
31 changes: 29 additions & 2 deletions internal/graph/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets"
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
)

const (
// Kubernetes APIService relationships.
RelationshipAPIService Relationship = "APIService"

// Kubernetes ClusterRole, ClusterRoleBinding, RoleBinding relationships.
RelationshipClusterRoleAggregationRule Relationship = "ClusterRoleAggregationRule"
RelationshipClusterRolePolicyRule Relationship = "ClusterRolePolicyRule"
Expand Down Expand Up @@ -99,6 +103,29 @@ const (
RelationshipVolumeAttachmentSourceVolumeStorageClass Relationship = "VolumeAttachmentSourceVolumeStorageClass"
)

// getAPIServiceRelationships returns a map of relationships that this
// APIService has with other objects, based on what was referenced in its
// manifest.
func getAPIServiceRelationships(n *Node) (*RelationshipMap, error) {
var apisvc apiregistrationv1.APIService
err := runtime.DefaultUnstructuredConverter.FromUnstructured(n.UnstructuredContent(), &apisvc)
if err != nil {
return nil, err
}

// var os ObjectSelector
var ref ObjectReference
result := newRelationshipMap()

// RelationshipAPIService
if svc := apisvc.Spec.Service; svc != nil {
ref = ObjectReference{Kind: "Service", Namespace: svc.Namespace, Name: svc.Name}
result.AddDependencyByKey(ref.Key(), RelationshipAPIService)
}

return &result, nil
}

// getClusterRoleRelationships returns a map of relationships that this
// ClusterRole has with other objects, based on what was referenced in
// its manifest.
Expand All @@ -109,8 +136,8 @@ func getClusterRoleRelationships(n *Node) (*RelationshipMap, error) {
return nil, err
}

var ols ObjectLabelSelector
var os ObjectSelector
var ols ObjectLabelSelector
var ref ObjectReference
result := newRelationshipMap()

Expand Down Expand Up @@ -645,8 +672,8 @@ func getRoleRelationships(n *Node) (*RelationshipMap, error) {
if err != nil {
return nil, err
}

var os ObjectSelector

var ref ObjectReference
result := newRelationshipMap()

Expand Down
27 changes: 26 additions & 1 deletion internal/printers/printers_humanreadable.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/duration"
"k8s.io/client-go/util/jsonpath"
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"

"github.com/tohjustin/kube-lineage/internal/graph"
)
Expand Down Expand Up @@ -160,6 +161,28 @@ func getObjectReadyStatus(u *unstructuredv1.Unstructured) (string, string, error
return ready, status, nil
}

// getAPIServiceReadyStatus returns the ready & status value of a APIService
// which is based off the table cell values computed by printAPIService from
// https://github.com/kubernetes/kubernetes/blob/v1.22.1/pkg/printers/internalversion/printers.go.
func getAPIServiceReadyStatus(u *unstructuredv1.Unstructured) (string, string, error) {
var apisvc apiregistrationv1.APIService
err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.UnstructuredContent(), &apisvc)
if err != nil {
return "", "", err
}
var ready, status string
for _, condition := range apisvc.Status.Conditions {
if condition.Type == apiregistrationv1.Available {
ready = string(condition.Status)
if condition.Status != apiregistrationv1.ConditionTrue {
status = condition.Reason
}
}
}

return ready, status, nil
}

// getDaemonSetReadyStatus returns the ready & status value of a DaemonSet
// which is based off the table cell values computed by printDaemonSet from
// https://github.com/kubernetes/kubernetes/blob/v1.22.1/pkg/printers/internalversion/printers.go.
Expand Down Expand Up @@ -413,7 +436,7 @@ func getVolumeAttachmentReadyStatus(u *unstructuredv1.Unstructured) (string, str
}

// nodeToTableRow converts the provided node into a table row.
//nolint:gocognit,goconst
//nolint:funlen,gocognit,goconst
func nodeToTableRow(node *graph.Node, rset graph.RelationshipSet, namePrefix string, showGroupFn func(kind string) bool) metav1.TableRow {
var name, ready, status, age string
var relationships interface{}
Expand Down Expand Up @@ -443,6 +466,8 @@ func nodeToTableRow(node *graph.Node, rset graph.RelationshipSet, namePrefix str
ready, status, _ = getStatefulSetReadyStatus(node.Unstructured)
case node.Group == "policy" && node.Kind == "PodDisruptionBudget":
ready, status, _ = getPodDisruptionBudgetReadyStatus(node.Unstructured)
case node.Group == "apiregistration.k8s.io" && node.Kind == "APIService":
ready, status, _ = getAPIServiceReadyStatus(node.Unstructured)
case node.Group == "events.k8s.io" && node.Kind == "Event":
ready, status, _ = getEventReadyStatus(node.Unstructured)
case node.Group == "storage.k8s.io" && node.Kind == "VolumeAttachment":
Expand Down

0 comments on commit b329c16

Please sign in to comment.