Skip to content

Commit

Permalink
MGMT-9272 Automatic agent classification labels (openshift#3721)
Browse files Browse the repository at this point in the history
* MGMT-9272: Define AgentClassification CRD

This CRD defines the API for users to classify Agents by providing a
query that is run on the Agent's inventory along with a corresponding
label.

* MGMT-9272: AgentClassification and AgentLabel controllers

The AgentLabel controller updates Agents' labels according to defined
AgentClassification CRs in the same namespace.

The AgentClassification controller maintain counts for each
AgentClassification of how many Agents matched and how many had errors
when trying to match. It also has a finalizer such that the
AgentClassification won't be deleted as long as there are Agents
matching it.

* MGMT-9272: AgentClassification admission hooks

This ensures that:
1. Specified labels are valid and do not change
2. The specified query can be parsed

* MGMT-9272: AgentClassification documentation

* MGMT-9272: go.mod and go.sum

* MGMT-9272: Agent labels subsystem test
  • Loading branch information
avishayt authored Apr 27, 2022
1 parent d3f6c41 commit 0ad1709
Show file tree
Hide file tree
Showing 24 changed files with 1,880 additions and 17 deletions.
83 changes: 83 additions & 0 deletions api/v1beta1/agentclassification_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
Copyright 2022.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1beta1

import (
conditionsv1 "github.com/openshift/custom-resource-status/conditions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
QueryErrorsCondition conditionsv1.ConditionType = "QueryErrors"
QueryNoErrorsReason string = "NoQueryErrors"
QueryHasErrorsReason string = "HasQueryErrors"
)

// AgentClassificationSpec defines the desired state of AgentClassification
type AgentClassificationSpec struct {
// LabelKey specifies the label key to apply to matched Agents
//
// +immutable
LabelKey string `json:"labelKey"`

// LabelValue specifies the label value to apply to matched Agents
//
// +immutable
LabelValue string `json:"labelValue"`

// Query is in gojq format (https://github.com/itchyny/gojq#difference-to-jq)
// and will be invoked on each Agent's inventory. The query should return a
// boolean. The operator will apply the label to any Agent for which "true"
// is returned.
Query string `json:"query"`
}

// AgentClassificationStatus defines the observed state of AgentClassification
type AgentClassificationStatus struct {
// MatchedCount shows how many Agents currently match the classification
MatchedCount int `json:"matchedCount,omitempty"`

// ErrorCount shows how many Agents encountered errors when matching the classification
ErrorCount int `json:"errorCount,omitempty"`

Conditions []conditionsv1.Condition `json:"conditions,omitempty"`
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status

// AgentClassification is the Schema for the AgentClassifications API
type AgentClassification struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec AgentClassificationSpec `json:"spec,omitempty"`
Status AgentClassificationStatus `json:"status,omitempty"`
}

//+kubebuilder:object:root=true

// AgentClassificationList contains a list of AgentClassification
type AgentClassificationList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []AgentClassification `json:"items"`
}

func init() {
SchemeBuilder.Register(&AgentClassification{}, &AgentClassificationList{})
}
96 changes: 96 additions & 0 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,16 @@ func main() {
CRDEventsHandler: crdEventsHandler,
}).SetupWithManager(ctrlMgr), "unable to create controller AgentClusterInstall")

failOnError((&controllers.AgentClassificationReconciler{
Client: ctrlMgr.GetClient(),
Log: log,
}).SetupWithManager(ctrlMgr), "unable to create controller AgentClassification")

failOnError((&controllers.AgentLabelReconciler{
Client: ctrlMgr.GetClient(),
Log: log,
}).SetupWithManager(ctrlMgr), "unable to create controller AgentLabel")

log.Infof("Starting controllers")
failOnError(ctrlMgr.Start(ctrl.SetupSignalHandler()), "failed to run manager")
}
Expand Down
1 change: 1 addition & 0 deletions cmd/webadmission/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func main() {
hiveextvalidatingwebhooks.NewAgentClusterInstallValidatingAdmissionHook(decoder),
agentinstallvalidatingwebhooks.NewInfraEnvValidatingAdmissionHook(decoder),
agentinstallvalidatingwebhooks.NewAgentValidatingAdmissionHook(decoder),
agentinstallvalidatingwebhooks.NewAgentClassificationValidatingAdmissionHook(decoder),
)
}

Expand Down
107 changes: 107 additions & 0 deletions config/crd/bases/agent-install.openshift.io_agentclassifications.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@

---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.6.2
creationTimestamp: null
name: agentclassifications.agent-install.openshift.io
spec:
group: agent-install.openshift.io
names:
kind: AgentClassification
listKind: AgentClassificationList
plural: agentclassifications
singular: agentclassification
scope: Namespaced
versions:
- name: v1beta1
schema:
openAPIV3Schema:
description: AgentClassification is the Schema for the AgentClassifications
API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: AgentClassificationSpec defines the desired state of AgentClassification
properties:
labelKey:
description: LabelKey specifies the label key to apply to matched
Agents
type: string
labelValue:
description: LabelValue specifies the label value to apply to matched
Agents
type: string
query:
description: Query is in gojq format (https://github.com/itchyny/gojq#difference-to-jq)
and will be invoked on each Agent's inventory. The query should
return a boolean. The operator will apply the label to any Agent
for which "true" is returned.
type: string
required:
- labelKey
- labelValue
- query
type: object
status:
description: AgentClassificationStatus defines the observed state of AgentClassification
properties:
conditions:
items:
description: Condition represents the state of the operator's reconciliation
functionality.
properties:
lastHeartbeatTime:
format: date-time
type: string
lastTransitionTime:
format: date-time
type: string
message:
type: string
reason:
type: string
status:
type: string
type:
description: ConditionType is the state of the operator's reconciliation
functionality.
type: string
required:
- status
- type
type: object
type: array
errorCount:
description: ErrorCount shows how many Agents encountered errors when
matching the classification
type: integer
matchedCount:
description: MatchedCount shows how many Agents currently match the
classification
type: integer
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
1 change: 1 addition & 0 deletions config/crd/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ resources:
- bases/agent-install.openshift.io_infraenvs.yaml
- bases/agent-install.openshift.io_agents.yaml
- bases/agent-install.openshift.io_nmstateconfigs.yaml
- bases/agent-install.openshift.io_agentclassifications.yaml
- bases/extensions.hive.openshift.io_agentclusterinstalls.yaml
# +kubebuilder:scaffold:crdkustomizeresource

Expand Down
Loading

0 comments on commit 0ad1709

Please sign in to comment.