-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ca0ca91
commit f434c2b
Showing
7 changed files
with
617 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,5 @@ coverage.out | |
.idea/* | ||
*.xml | ||
|
||
.env | ||
.env | ||
bin/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,71 @@ | ||
.PHONY: clean dev push push-tester-image e2e run-e2e | ||
# Run `make help` for usage information on commands in this file. | ||
|
||
.PHONY: help clean dev push e2e unit crd manifests generate controller-gen | ||
|
||
-include .env | ||
|
||
# can have values of "public" or "private" | ||
CLUSTER_TYPE="public" | ||
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) | ||
ifeq (,$(shell go env GOBIN)) | ||
GOBIN=$(shell go env GOPATH)/bin | ||
else | ||
GOBIN=$(shell go env GOBIN) | ||
endif | ||
|
||
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen | ||
CONTROLLER_TOOLS_VERSION ?= v0.13.0 | ||
|
||
# Setting SHELL to bash allows bash commands to be executed by recipes. | ||
# Options are set to exit when a recipe line exits non-zero or a piped command fails. | ||
SHELL = /usr/bin/env bash -o pipefail | ||
.SHELLFLAGS = -ec | ||
|
||
## Location to install dependencies to | ||
LOCALBIN ?= $(shell pwd)/bin | ||
$(LOCALBIN): | ||
mkdir -p $(LOCALBIN) | ||
|
||
help: ## Display this help. | ||
# prints all targets with comments next to them, extracted from this file | ||
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) | ||
|
||
clean: | ||
clean: ## Cleans the development environment state | ||
rm -rf devenv/state devenv/tf/.terraform.lock.hcl devenv/tf/.terraform devenv/tf/terraform.tfstate devenv/tf/terraform.tfstate.backup | ||
|
||
dev: | ||
# can have values of "public" or "private" | ||
CLUSTER_TYPE="public" | ||
|
||
dev: clean ## Deploys a development environment useful for testing the operator inside a cluster | ||
terraform --version | ||
cd devenv && mkdir -p state && cd tf && terraform init && terraform apply -auto-approve -var="clustertype=$(CLUSTER_TYPE)" | ||
./devenv/scripts/deploy_operator.sh | ||
|
||
push: | ||
push: ## Pushes the current operator code to the current development environment | ||
echo "$(shell cat devenv/state/registry.txt)/app-routing-operator:$(shell date +%s)" > devenv/state/operator-image-tag.txt | ||
az acr login -n `cat devenv/state/registry.txt` | ||
docker build -t `cat devenv/state/operator-image-tag.txt` . | ||
docker push `cat devenv/state/operator-image-tag.txt` | ||
./devenv/scripts/push_image.sh | ||
|
||
e2e: | ||
e2e: ## Runs end-to-end tests | ||
# parenthesis preserve current working directory | ||
(cd testing/e2e && \ | ||
go run ./main.go infra --subscription=${SUBSCRIPTION_ID} --tenant=${TENANT_ID} --names=${INFRA_NAMES} && \ | ||
go run ./main.go deploy) | ||
|
||
unit: | ||
unit: ## Runs unit tests | ||
docker build ./devenv/ -t app-routing-dev:latest | ||
docker run --rm -v "$(shell pwd)":/usr/src/project -w /usr/src/project app-routing-dev:latest go test ./... | ||
|
||
crd: generate manifests ## Generates all associated files from CRD | ||
|
||
manifests: controller-gen ## Generate CRD manifest | ||
$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./api/..." output:crd:artifacts:config=config/crd/bases | ||
|
||
generate: $(CONTROLLER_GEN) ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. | ||
$(CONTROLLER_GEN) object paths="./api/..." | ||
|
||
|
||
controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary. If wrong version is installed, it will be overwritten. | ||
$(CONTROLLER_GEN): $(LOCALBIN) | ||
test -s $(LOCALBIN)/controller-gen && $(LOCALBIN)/controller-gen --version | grep -q $(CONTROLLER_TOOLS_VERSION) || \ | ||
GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Code generated by tool. DO NOT EDIT. | ||
# This file is used to track the info used to scaffold your project | ||
# and allow the plugins properly work. | ||
# More info: https://book.kubebuilder.io/reference/project-config.html | ||
domain: kubernetes.azure.com | ||
layout: | ||
- go.kubebuilder.io/v4 | ||
projectName: app-routing | ||
repo: github.com/Azure/aks-app-routing-operator | ||
resources: | ||
- api: | ||
crdVersion: v1 | ||
namespaced: false | ||
controller: true | ||
domain: kubernetes.azure.com | ||
group: approuting | ||
kind: NginxIngressController | ||
path: github.com/Azure/aks-app-routing-operator/api/v1alpha1 | ||
version: v1alpha1 | ||
version: "3" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// Package v1alpha1 contains API Schema definitions for the approuting v1alpha1 API group | ||
// +kubebuilder:object:generate=true | ||
// +groupName=approuting.kubernetes.azure.com | ||
package v1alpha1 | ||
|
||
import ( | ||
"k8s.io/apimachinery/pkg/runtime/schema" | ||
"sigs.k8s.io/controller-runtime/pkg/scheme" | ||
) | ||
|
||
var ( | ||
// GroupVersion is group version used to register these objects | ||
GroupVersion = schema.GroupVersion{Group: "approuting.kubernetes.azure.com", Version: "v1alpha1"} | ||
|
||
// SchemeBuilder is used to add go types to the GroupVersionKind scheme | ||
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} | ||
|
||
// AddToScheme adds the types in this group-version to the given scheme. | ||
AddToScheme = SchemeBuilder.AddToScheme | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
package v1alpha1 | ||
|
||
import ( | ||
"k8s.io/apimachinery/pkg/api/meta" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
) | ||
|
||
// Important: Run "make crd" to regenerate code after modifying this file | ||
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. | ||
|
||
// NginxIngressControllerSpec defines the desired state of NginxIngressController | ||
type NginxIngressControllerSpec struct { | ||
// IngressClassName is the name of the IngressClass that will be used for the NGINX Ingress Controller. Defaults to metadata.name if | ||
// not specified. | ||
// +optional | ||
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable" | ||
IngressClassName string `json:"ingressClassName,omitempty"` | ||
|
||
// ControllerNamePrefix is the name to use for the managed NGINX Ingress Controller resources. | ||
// +optional | ||
// +kubebuilder:default=nginx | ||
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable" | ||
ControllerNamePrefix string `json:"controllerNamePrefix,omitempty"` | ||
|
||
// LoadBalancerAnnotations is a map of annotations to apply to the NGINX Ingress Controller's Service. Common annotations | ||
// will be from the Azure LoadBalancer annotations here https://cloud-provider-azure.sigs.k8s.io/topics/loadbalancer/#loadbalancer-annotations | ||
// +optional | ||
LoadBalancerAnnotations map[string]string `json:"loadBalancerAnnotations,omitempty"` | ||
} | ||
|
||
// NginxIngressControllerStatus defines the observed state of NginxIngressController | ||
type NginxIngressControllerStatus struct { | ||
// Conditions is an array of current observed conditions for the NGINX Ingress Controller | ||
// +optional | ||
// +patchMergeKey=type | ||
// +patchStrategy=merge | ||
// +listType=map | ||
// +listMapKey=type | ||
Conditions []metav1.Condition `json:"conditions"` | ||
|
||
// ControllerReplicas is the desired number of replicas of the NGINX Ingress Controller | ||
// +optional | ||
ControllerReplicas int32 `json:"controllerReplicas"` | ||
|
||
// ControllerReadyReplicas is the number of ready replicas of the NGINX Ingress Controller deployment | ||
// +optional | ||
ControllerReadyReplicas int32 `json:"controllerReadyReplicas"` | ||
|
||
// ControllerAvailableReplicas is the number of available replicas of the NGINX Ingress Controller deployment | ||
// +optional | ||
ControllerAvailableReplicas int32 `json:"controllerAvailableReplicas"` | ||
|
||
// ControllerUnavailableReplicas is the number of unavailable replicas of the NGINX Ingress Controller deployment | ||
// +optional | ||
ControllerUnavailableReplicas int32 `json:"controllerUnavailableReplicas"` | ||
|
||
// Count of hash collisions for the managed resources. The App Routing Operator uses this field | ||
// as a collision avoidance mechanism when it needs to create the name for the managed resources. | ||
// +optional | ||
CollisionCount int32 `json:"collisionCount"` | ||
|
||
// ManagedResourceRefs is a list of references to the managed resources | ||
// +optional | ||
ManagedResourceRefs []ManagedObjectReference `json:"managedResourceRefs,omitempty"` | ||
} | ||
|
||
const ( | ||
// ConditionTypeAvailable indicates whether the NGINX Ingress Controller is available. Its condition status is one of | ||
// - "True" when the NGINX Ingress Controller is available and can be used | ||
// - "False" when the NGINX Ingress Controller is not available and cannot offer full functionality | ||
// - "Unknown" when the NGINX Ingress Controller's availability cannot be determined | ||
ConditionTypeAvailable = "Available" | ||
|
||
// ConditionTypeIngressClassReady indicates whether the IngressClass exists. Its condition status is one of | ||
// - "True" when the IngressClass exists | ||
// - "False" when the IngressClass does not exist | ||
// - "Collision" when the IngressClass exists, but it's not owned by the NginxIngressController. | ||
// - "Unknown" when the IngressClass's existence cannot be determined | ||
ConditionTypeIngressClassReady = "IngressClassReady" | ||
|
||
// ConditionTypeControllerAvailable indicates whether the NGINX Ingress Controller deployment is available. Its condition status is one of | ||
// - "True" when the NGINX Ingress Controller deployment is available | ||
// - "False" when the NGINX Ingress Controller deployment is not available | ||
// - "Unknown" when the NGINX Ingress Controller deployment's availability cannot be determined | ||
ConditionTypeControllerAvailable = "ControllerAvailable" | ||
|
||
// ConditionTypeProgressing indicates whether the NGINX Ingress Controller availability is progressing. Its condition status is one of | ||
// - "True" when the NGINX Ingress Controller availability is progressing | ||
// - "False" when the NGINX Ingress Controller availability is not progressing | ||
// - "Unknown" when the NGINX Ingress Controller availability's progress cannot be determined | ||
ConditionTypeProgressing = "Progressing" | ||
) | ||
|
||
// ManagedObjectReference is a reference to an object | ||
type ManagedObjectReference struct { | ||
// Name is the name of the managed object | ||
Name string `json:"name"` | ||
|
||
// Namespace is the namespace of the managed object. If not specified, the resource is cluster-scoped | ||
// +optional | ||
Namespace string `json:"namespace"` | ||
|
||
// Kind is the kind of the managed object | ||
Kind string `json:"kind"` | ||
|
||
// APIGroup is the API group of the managed object. If not specified, the resource is in the core API group | ||
// +optional | ||
APIGroup string `json:"apiGroup"` | ||
} | ||
|
||
//+kubebuilder:object:root=true | ||
//+kubebuilder:subresource:status | ||
//+kubebuilder:resource:scope=Cluster,shortName=nic | ||
//+kubebuilder:printcolumn:name="IngressClass",type="string",JSONPath=`.spec.ingressClassName` | ||
//+kubebuilder:printcolumn:name="ControllerNamePrefix",type="string",JSONPath=`.spec.controllerNamePrefix` | ||
//+kubebuilder:printcolumn:name="Available",type="string",JSONPath=`.status.conditions[?(@.type=="Available")].status` | ||
|
||
// NginxIngressController is the Schema for the nginxingresscontrollers API | ||
type NginxIngressController struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ObjectMeta `json:"metadata,omitempty"` | ||
|
||
// +required | ||
Spec NginxIngressControllerSpec `json:"spec,omitempty"` | ||
|
||
// +optional | ||
Status NginxIngressControllerStatus `json:"status,omitempty"` | ||
} | ||
|
||
func (n *NginxIngressController) GetCondition(t string) *metav1.Condition { | ||
return meta.FindStatusCondition(n.Status.Conditions, t) | ||
} | ||
|
||
func (n *NginxIngressController) SetCondition(c metav1.Condition) { | ||
current := n.GetCondition(c.Type) | ||
|
||
if current != nil && current.Status == c.Status && current.Message == c.Message && current.Reason == c.Reason { | ||
current.ObservedGeneration = n.Generation | ||
return | ||
} | ||
|
||
c.ObservedGeneration = n.Generation | ||
c.LastTransitionTime = metav1.Now() | ||
meta.SetStatusCondition(&n.Status.Conditions, c) | ||
} | ||
|
||
// Valid checks this NginxIngressController to see if it's valid. Returns a string describing the validation error, if any, or empty string if there is no error. | ||
func (n *NginxIngressController) Valid() string { | ||
if n.Spec.ControllerNamePrefix == "" { | ||
return "spec.controllerNamePrefix must be specified" | ||
} | ||
|
||
if n.Spec.IngressClassName == "" { | ||
return "spec.ingressClassName must be specified" | ||
} | ||
|
||
if len(n.Name) > 100 { | ||
return "Name length must be less than or equal to 100 characters" | ||
} | ||
|
||
// TODO: add more specific validations https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names | ||
|
||
return "" | ||
} | ||
|
||
func (n *NginxIngressController) Default() { | ||
if n.Spec.IngressClassName == "" { | ||
n.Spec.IngressClassName = n.Name | ||
} | ||
|
||
if n.Spec.ControllerNamePrefix == "" { | ||
n.Spec.ControllerNamePrefix = "nginx" | ||
} | ||
} | ||
|
||
//+kubebuilder:object:root=true | ||
//+kubebuilder:resource:scope=Cluster | ||
|
||
// NginxIngressControllerList contains a list of NginxIngressController | ||
type NginxIngressControllerList struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ListMeta `json:"metadata,omitempty"` | ||
Items []NginxIngressController `json:"items"` | ||
} | ||
|
||
func init() { | ||
SchemeBuilder.Register(&NginxIngressController{}, &NginxIngressControllerList{}) | ||
} |
Oops, something went wrong.