Skip to content

Commit

Permalink
provide a basic operator v1 API
Browse files Browse the repository at this point in the history
  • Loading branch information
deads2k committed Nov 13, 2018
1 parent 602ca28 commit 8453618
Show file tree
Hide file tree
Showing 8 changed files with 288 additions and 2 deletions.
1 change: 1 addition & 0 deletions config/v1/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&ConsoleList{},
&DNS{},
&DNSList{},
&GenericControllerConfig{},
&IdentityProvider{},
&IdentityProviderList{},
&Image{},
Expand Down
30 changes: 30 additions & 0 deletions config/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,3 +244,33 @@ type ClientConnectionOverrides struct {
// burst allows extra queries to accumulate when a client is exceeding its rate.
Burst int32 `json:"burst"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// GenericControllerConfig provides information to configure a controller
type GenericControllerConfig struct {
metav1.TypeMeta `json:",inline"`

// ServingInfo is the HTTP serving information for the controller's endpoints
ServingInfo HTTPServingInfo `json:"servingInfo,omitempty"`

// leaderElection provides information to elect a leader. Only override this if you have a specific need
LeaderElection LeaderElection `json:"leaderElection,omitempty"`

// authentication allows configuration of authentication for the endpoints
Authentication DelegatedAuthentication `json:"authentication,omitempty"`
// authorization allows configuration of authentication for the endpoints
Authorization DelegatedAuthorization `json:"authorization,omitempty"`
}

// DelegatedAuthentication allows authentication to be disabled.
type DelegatedAuthentication struct {
// disabled indicates that authentication should be disabled. By default it will use delegated authentication.
Disabled bool `json:"disabled,omitempty"`
}

// DelegatedAuthorization allows authorization to be disabled.
type DelegatedAuthorization struct {
// disabled indicates that authorization should be disabled. By default it will use delegated authorization.
Disabled bool `json:"disabled,omitempty"`
}
1 change: 1 addition & 0 deletions hack/lib/init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ legacyconfig/v1 \
network/v1 \
oauth/v1 \
openshiftcontrolplane/v1 \
operator/v1 \
operator/v1alpha1 \
project/v1 \
quota/v1 \
Expand Down
2 changes: 1 addition & 1 deletion hack/update-deepcopy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ verify="${VERIFY:-}"
${CODEGEN_PKG}/generate-groups.sh "deepcopy" \
github.com/openshift/api/generated \
github.com/openshift/api \
"apps:v1 authorization:v1 build:v1 config:v1 image:v1,docker10,dockerpre012 kubecontrolplane:v1 legacyconfig:v1 network:v1 oauth:v1 openshiftcontrolplane:v1 operator:v1alpha1 osin:v1 project:v1 quota:v1 route:v1 security:v1 servicecertsigner:v1alpha1 template:v1 user:v1 webconsole:v1" \
"apps:v1 authorization:v1 build:v1 config:v1 image:v1,docker10,dockerpre012 kubecontrolplane:v1 legacyconfig:v1 network:v1 oauth:v1 openshiftcontrolplane:v1 operator:v1 operator:v1alpha1 osin:v1 project:v1 quota:v1 route:v1 security:v1 servicecertsigner:v1alpha1 template:v1 user:v1 webconsole:v1" \
--go-header-file ${SCRIPT_ROOT}/hack/empty.txt \
${verify}
3 changes: 2 additions & 1 deletion operator/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"

operatorv1 "github.com/openshift/api/operator/v1"
operatorv1alpha1 "github.com/openshift/api/operator/v1alpha1"
)

Expand All @@ -12,7 +13,7 @@ const (
)

var (
schemeBuilder = runtime.NewSchemeBuilder(operatorv1alpha1.Install)
schemeBuilder = runtime.NewSchemeBuilder(operatorv1alpha1.Install, operatorv1.Install)
// Install is a function which adds every version of this group to a scheme
Install = schemeBuilder.AddToScheme
)
Expand Down
6 changes: 6 additions & 0 deletions operator/v1/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// +k8s:deepcopy-gen=package,register
// +k8s:defaulter-gen=TypeMeta
// +k8s:openapi-gen=true

// +groupName=operator.openshift.io
package v1
37 changes: 37 additions & 0 deletions operator/v1/register.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package v1

import (
configv1 "github.com/openshift/api/config/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)

var (
GroupName = "operator.openshift.io"
GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"}
schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes, configv1.Install)
// Install is a function which adds this version to a scheme
Install = schemeBuilder.AddToScheme

// SchemeGroupVersion generated code relies on this name
// Deprecated
SchemeGroupVersion = GroupVersion
// AddToScheme exists solely to keep the old generators creating valid code
// DEPRECATED
AddToScheme = schemeBuilder.AddToScheme
)

// Resource generated code relies on this being here, but it logically belongs to the group
// DEPRECATED
func Resource(resource string) schema.GroupResource {
return schema.GroupResource{Group: GroupName, Resource: resource}
}

func addKnownTypes(scheme *runtime.Scheme) error {
metav1.AddToGroupVersion(scheme, GroupVersion)

scheme.AddKnownTypes(GroupVersion)

return nil
}
210 changes: 210 additions & 0 deletions operator/v1/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
package v1

import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)

// MyOperatorResource is an example operator configuration type
type MyOperatorResource struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata"`

Spec MyOperatorResourceSpec `json:"spec"`
Status MyOperatorResourceStatus `json:"status"`
}

type MyOperatorResourceSpec struct {
OperatorSpec `json:",inline"`
}

type MyOperatorResourceStatus struct {
OperatorStatus `json:",inline"`
}

type ManagementState string

var (
// Force means that the operator is actively managing its resources and ignoring unmet prereqs
Force ManagementState = "Force"
// Managed means that the operator is actively managing its resources and trying to keep the component active
Managed ManagementState = "Managed"
// Unmanaged means that the operator is not taking any action related to the component
Unmanaged ManagementState = "Unmanaged"
// Removed means that the operator is actively managing its resources and trying to remove all traces of the component
Removed ManagementState = "Removed"
)

// OperatorSpec contains common fields for an operator to need. It is intended to be anonymous included
// inside of the Spec struct for you particular operator.
type OperatorSpec struct {
// managementState indicates whether and how the operator should manage the component
ManagementState ManagementState `json:"managementState"`

// operandSpecs provide information about customization for particular units
OperandSpecs []OperandSpec `json:"operandSpecs"`

// unsupportedConfigOverrides holds a sparse config that will override any previously set options. It only needs to be the fields to override
// it will end up overlaying in the following order:
// 1. hardcoded defaults
// 2. observedConfig
// 3. unsupportedConfigOverrides
UnsupportedConfigOverrides runtime.RawExtension `json:"unsupportedConfigOverrides"`

// observedConfig holds a sparse config that controller has observed from the cluster state. It exists in spec because
// it is an input to the level for the operator
ObservedConfig runtime.RawExtension `json:"observedConfig"`
}

// ResourcePatch is a way to represent the patch you would issue to `kubectl patch` in the API
type ResourcePatch struct {
// type is the type of patch to apply: jsonmerge, strategicmerge
Type string `json:"type"`
// patch the patch itself
Patch string `json:"patch"`
}

// OperandSpec holds information for customatization of a particular unit (logical pod)
type OperandSpec struct {
// name is the name of this unit. The operator must be aware of it.
Name string `json:"name"`

// operandContainerSpecs are per-container options
OperandContainerSpecs []OperandContainerSpec `json:"operandContainerSpecs"`

// Alternatively, we could simply include a RawExtension which is used in place of the "normal" default manifest
UnsupportedResourcePatches []ResourcePatch `json:"unsupportedResourcePatches"`
}

type OperandContainerSpec struct {
// name is the name of the container to modify
Name string `json:"name"`

// resources are the requests and limits to place in the container. Nil means to accept the defaults.
Resources *corev1.ResourceRequirements `json:"resources,omitempty"`

// logging contains parameters for setting log values on the operand. Nil means to accept the defaults.
Logging LoggingConfig `json:"logging,omitempty"`
}

// LoggingConfig holds information about configuring logging
type LoggingConfig struct {
Type string `json:"type"`

Glog *GlogConfig `json:"glog,omitempty"`
CapnsLog *CapnsLogConfig `json:"capnsLog,omitempty"`
Java *JavaLog `json:"java,omitempty"`
}

// GlogConfig holds information about configuring logging
type GlogConfig struct {
// level is passed to glog.
Level int64 `json:"level"`

// vmodule is passed to glog.
Vmodule string `json:"vmodule"`
}

type CapnsLogConfig struct {
// level is passed to capnslog: critical, error, warning, notice, info, debug, trace
Level string `json:"level"`

// There is some kind of repo/package level thing for this
}

type JavaLog struct {
// level is passed to jsr47: fatal, error, warning, info, fine, finer, finest
Level string `json:"level"`

// There is some kind of repo/package level thing for this. might end up hierarchical
}

type OperatorStatus struct {
// conditions is a list of conditions and their status
Conditions []OperatorCondition `json:"conditions,omitempty"`

// version is the level this availability applies to
Version string `json:"version"`

// readyReplicas indicates how many replicas are ready and at the desired state
ReadyReplicas int32 `json:"readyReplicas"`

// generations are used to determine when an item needs to be reconciled or has changed in a way that needs a reaction.
Generations []GenerationStatus `json:"generations"`
}

// GenerationStatus keeps track of the generation for a given resource so that decisions about forced updated can be made.
type GenerationStatus struct {
// group is the group of the thing you're tracking
Group string `json:"group"`
// resource is the resource type of the thing you're tracking
Resource string `json:"resource"`
// namespace is where the thing you're tracking is
Namespace string `json:"namespace"`
// name is the name of the thing you're tracking
Name string `json:"name"`
// lastGeneration is the last generation of the workload controller involved
LastGeneration int64 `json:"lastGeneration"`
// hash is an optional field set for resources without generation that are content sensitive like secrets and configmaps
Hash string `json:"hash"`
}

var (
// Available indicates that the operand is present and accessible in the cluster
OperatorStatusTypeAvailable = "Available"
// Progressing indicates that the operator is trying to transition the operand to a different state
OperatorStatusTypeProgressing = "Progressing"
// Failing indicates that the operator (not the operand) is unable to fulfill the user intent
OperatorStatusTypeFailing = "Failing"
// PrereqsSatisfied indicates that the things this operator depends on are present and at levels compatible with the
// current and desired states.
OperatorStatusTypePrereqsSatisfied = "PrereqsSatisfied"
// Upgradeable indicates that the operator configuration itself (not prereqs) can be auto-upgraded by the CVO
OperatorStatusTypeUpgradeable = "Upgradeable"
)

// OperatorCondition is just the standard condition fields.
type OperatorCondition struct {
Type string `json:"type"`
Status ConditionStatus `json:"status"`
LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`
Reason string `json:"reason,omitempty"`
Message string `json:"message,omitempty"`
}

type ConditionStatus string

const (
ConditionTrue ConditionStatus = "True"
ConditionFalse ConditionStatus = "False"
ConditionUnknown ConditionStatus = "Unknown"
)

// StaticPodOperatorStatus is status for controllers that manage static pods. There are different needs because individual
// node status must be tracked.
type StaticPodOperatorStatus struct {
OperatorStatus `json:",inline"`

// latestAvailableDeploymentGeneration is the deploymentID of the most recent deployment
LatestAvailableDeploymentGeneration int32 `json:"latestAvailableDeploymentGeneration"`

// nodeStatuses track the deployment values and errors across individual nodes
NodeStatuses []NodeStatus `json:"nodeStatuses"`
}

// NodeStatus provides information about the current state of a particular node managed by this operator.
type NodeStatus struct {
// nodeName is the name of the node
NodeName string `json:"nodeName"`

// currentDeploymentGeneration is the generation of the most recently successful deployment
CurrentDeploymentGeneration int32 `json:"currentDeploymentGeneration"`
// targetDeploymentGeneration is the generation of the deployment we're trying to apply
TargetDeploymentGeneration int32 `json:"targetDeploymentGeneration"`
// lastFailedDeploymentGeneration is the generation of the deployment we tried and failed to deploy.
LastFailedDeploymentGeneration int32 `json:"lastFailedDeploymentGeneration"`

// lastFailedDeploymentGenerationErrors is a list of the errors during the failed deployment referenced in lastFailedDeploymentGeneration
LastFailedDeploymentErrors []string `json:"lastFailedDeploymentErrors"`
}

0 comments on commit 8453618

Please sign in to comment.