Contributing to Model Relationships
Relationships within Model play a crucial role in establishing concrete visualisations of efficient data flow between different components of Meshery. These are used to classify the nature of interaction between one or more interconnected Components.
Overview of Tasks
- Identify the relationship and any specific constraints to be enforced between the two specific components, their models, or potentially other components, models, or environmental considerations.
- Propose the appropriate relationship type, using one of the predefined set of relationship types, or suggest a new relationship where an existing type does not fit.
- Create a Relationship Definition (yaml), including the following attributes:
- Identify an existing OPA policy as the
evaluationQuery
suitable to the relationship. If no policy exists, propose a new policy (rego). - Submit a pull request to the Meshery repository with the new relationship definition.
Relationship Visualizations
Example Visual Representations
Kind: Hierarchical
Kind: Sibling
Kind: Edge
</figure>
</figure>
Defining Relationships: Kinds, Types, Subtypes
Relationships are defined in the relationships.yaml
file in the Meshery repository. Each relationship definition includes the following attributes:
kind
: The genre of relationship (e.g., hierarchical, edge, sibling).type
: The augmentative category of the relationship (e.g., binding, non-binding, inventory).subType
: The specific represenative visual paradigm (e.g., parent, mount, network, wallet, badge).selectors
: The scope of the relationship, including the components involved and any constraints.evaluationQuery
: The OPA policy to invoke for relationship evaluation.documentation
: A description of the relationship, its purpose, and any constraints or considerations.
Existing Relationships as Examples
-
Hierarchical relationships involve either an ancestral connection of the components i.e. the creation/ deletion of a Component higher up affects the existence of the Components below in the lineage or a connection that involves the inheritance of features from one Component to the other.
- Parent: A parent-child relationship implies the requirement of the parent component before the child component can be created. For example, a “Namespace” in Kubernetes can be a parent of “Pods” within that namespace. The namespace must exist before creating pods within it.
- Inventory: A hierarchical inventory relationship implies the configuration of a(parent) component is patched with the configuration of other (child) component. For example, Wasm filters can inherit features and functionalities from Envoy filters. This can be used to build on existing functionalities provided by Envoy filters and further extend them using Wasm filters. It enables a modular and scalable approach to customize the behavior of the proxy while maintaining a clear hierarchy of features.
-
Edge relationships indicate the possibility of traffic flow between two components. They enable communication and interaction between different Components within the system.
- Mount: This subtype addresses the storage and access possibility between involved components. For example, a “PersistentVolume” can be mounted to a “Pod” to provide persistent storage for the pod’s data.
- Network: This deals with IP addresses and DNS names and provides stable endpoints for communication. For example, a “Service” provides a stable endpoint for accessing multiple replicas of a “Deployment”.
- Firewall: This acts as an intermediary for communications which include standard networking protocols like TCP and UDP. It can enforce network policies to control traffic between components. For example, a “NetworkPolicy” can be used to manage the traffic flow between different “Pods” in the cluster.
- Permission: This defines the permissions for components if they can have a possible relationship with other Components. It ensures that only authorized Components can interact with each other. For example, a “Role” can define permissions for Components to access specific resources.
-
Sibling relationships represent connections between components that are at the same hierarchical level or share a common parent. Siblings can have the same or similar functionalities or may interact with each other in specific ways. These relationships facilitate communication and cooperation between components that are in the same group or category. For example, a Service and a Pod in Kubernetes are siblings as they share a common parent and are at the same hierarchical level.
Structure of Selectors
Selectors are structured as an array, wherein each entry comprises a ‘from(self)’ field and a ‘to(other)’ field ([from: [{..}], to: [{..}]]
), delineating the components involved in a particular relationship. These entries define the constraints necessary for the existence of said relationship, thus providing scoping within a relationship.
Each item in the selector uniquely defines a relation between the components listed. i.e. from
and to
fields are evaluated within the context of the selector.
Only the components within the same selector relate to each other via 1:many kind of relation between components listed inside the from
and to
field. i.e. Each object inside the from
relates to each item inside the two
field within a particular selector.
When defining relationships that involve a large number of combinations between from
and to
, selectors provide a mechanism to organize and manage these relationships. This prevents the need for crafting complex deny attributes and facilitates easier maintenance.
This arrangement enhances flexibility and reusability in the definition and configuration of relationships among components.
Note:
When defining Hierarchical relationships, remember that the from
field represents the child component, while the to
field represents the parent component.
Selector example
The `selector` defined for the relationship between `WasmFilter` and `EnvoyFilter` (the first item in the array) is entirely independent of the `selector` defined for the relationship between `ConfigMap` and `Deployment`. This ensures independence in how these components relate to each other while still permitting similar types of relationships. The above relation shows `WASMFilter` and `EBPFFilter` defined inside `from` relates to each component defined inside `to` `(EnvoyFilter, WASMPlugin...)`. Similarly, `ConfigMap` defined inside `from` relates to each component defined inside `to` `(Deployment, StatefulSet,...)`What is evaluationQuery
attribute and how to determine the value for evaluationQuery
inside a relationship definition?
As all relationship definitions are backed by OPA policies and the relationships depending upon their Kind and Subtype needs to be evaluated with respective policies, the policy to invoke for evaluation is determined by the property evaluationQuery
, which follows the convention as kind_subtype_relationship
.
Eg: If you are defining/updating a relationship definition with kind: Edge and subType: Network, the value for the attribute `evaluationQuery` should be edge_network_relationship.
Each policy has a set of rules defined and the evaluationQuery
attribute corresponds to the main rule defined inside the policy, during the policy eval the results are collected from this rule.
Configuring the scopes of the relationship definitions
The extent to which a relationship affects components within a model or beyond a model is defined and controlled using scopes. Scopes are defined using the model
and version
attributes within the relationship schema.
Global Scope
Relationships can be confined to a specific model, a specific model version, or can be allowed to affect all models. The relationship schema has a model
and version
attribute which facilitates this control. For example, if the model is specified as aws-ec2-controller
, the relationship will work for those components that belong to the aws-ec2-controller
model.
Local Scope
Scope is defined and controlled via the selectors
Selectors attribute in the relationships.
Best practices for defining new relationships
- Ensure that the
deny
selectors andallow
selectors do not conflict with each other i.e. relations are not getting overlapped forallow
anddeny
selectors. - To configure a relationship to be applied across models, ensure the
model
property for those relationships is set to*
, to limit the relationships to a specific model, specify the correctmodel
(case sensitive). - To configure a relationship to be applied across all versions of a particular model, ensure the
version
property for those relationships is set to*
, to limit the relationships to a specific version of a model, specify the correct model version. - Support for specifying version property as a regex to ensure relationships are applied to a subset of versions of a model is coming soon.
- The
evaluationQuery
property determines the OPA policy to invoke for relationship evaluation, specify the correct rego query. - If a path
mutatedRef/mutatorRef
contains more than one array path then only the first array position can be specified as _ for others explicitly mention them as 0 - Currently
mutatedRef
doesn’t support having an array
Things to keep in mind while defining relationships
- Targets of a Relationship can be specific Components or entire Models.
- The values for Kind, Version, and Model are case-sensitive.
- The convention is to use camel-casing for Kind and SubType values.
- Absence of a field means in the selector means “*” (or wildcard).
- If we have a selector with {Kind: Pod, Model: Kubernetes}, the absence of the Version field here means that all the versions of the Kubernetes Pod resource (e.g. k8s.io/v1/betav2) will match.
- In the event of conflicting Relationship Definitions, the union between them is taken.
- If we have two Relationships, one from (Component A) to (Component B and Component F), and another from (Component A) to (Component B and Component C), then it is similar to having a Relationship from Component A to Component B, C and F
- In the event of an overlapping set of complementary Relationship Definitions, Union.
- In the event of an overlapping set of conflicting Relationship Definitions:
- No relationship type (Kind) is inherently more important than the next one, so will not be any case of conflict
For more information refer - Model - Construct Models in Meshery
Suggested Reading
- Build & Release (CI) - Details of Meshery's build and release strategy.
- Contributing to Meshery Adapters - How to contribute to Meshery Adapters
- Contributing to Meshery CLI - How to contribute to Meshery Command Line Interface.
- Contributing to Meshery's End-to-End Tests using Cypress - How to contribute to End-to-End Tests using Cypress.
- Contributing to Meshery Docker Extension - How to contribute to Meshery Docker Extension
- Contributing to Meshery Docs - How to contribute to Meshery Docs.
- How to write MeshKit compatible errors - How to declare errors in Meshery components.
- Contributing to Meshery using git - How to contribute to Meshery using git
- Meshery CLI Contributing Guidelines - Design principles and code conventions.
- Contributing to Models - How to contribute to Meshery Models, Components, Relationships, Policies...
- Contributing to Meshery Server Events - Guide is to help backend contributors send server events using Golang.
- Contributing to Meshery UI - Notification Center - How to contribute to the Notification Center in Meshery's web-based UI.
- Contributing to Meshery UI - How to contribute to Meshery UI (web-based user interface).
- Contributing to Meshery Server - How to contribute to Meshery Server
- Setting up Meshery Development Environment on Windows - How to set up Meshery Development Environment on Windows