Skip to content

Commit

Permalink
Automated merge
Browse files Browse the repository at this point in the history
* upstream/main:
  Add `RemoteIstio` to API concepts in docs (istio-ecosystem#272)
  Ensure `make gen-check` works when go mod cache is empty (istio-ecosystem#270)
  Introduce RemoteIstio (istio-ecosystem#202)
  api_transformer: use `go env` to detect mod cache dir (istio-ecosystem#269)
  Add field values.experimental to API (istio-ecosystem#264)
  Fix errors in tables for api reference documentation (istio-ecosystem#263)
  Generate CNIGlobalConfig from GlobalConfig automatically (istio-ecosystem#260)
  Fix errors in api reference doc (istio-ecosystem#262)
  Rename `addTags` to `addComments` in API transformer (istio-ecosystem#259)
  Add relatedImages to ClusterServiceVersion (istio-ecosystem#243)
  Generate API from versions defined in go.mod (istio-ecosystem#258)
  Fix issues identified during API review (istio-ecosystem#254)

# Conflicts:
#	bundle/manifests/sailoperator.clusterserviceversion.yaml
  • Loading branch information
openshift-service-mesh-bot committed Aug 13, 2024
2 parents a1b31e2 + eb644ad commit 187498d
Show file tree
Hide file tree
Showing 99 changed files with 40,019 additions and 2,665 deletions.
28 changes: 14 additions & 14 deletions Makefile.core.mk
Original file line number Diff line number Diff line change
Expand Up @@ -334,21 +334,9 @@ deploy-example-kubernetes: verify-kubeconfig ## Deploy an example Istio resource
gen-manifests: controller-gen ## Generate WebhookConfiguration and CustomResourceDefinition objects.
$(CONTROLLER_GEN) crd:allowDangerousTypes=true webhook paths="./..." output:crd:artifacts:config=chart/crds

# TODO: move this to versions.yaml or get the files via go.mod instead of downloading them
ISTIO_REPO_BASE=https://raw.githubusercontent.com/istio/istio/0e7ecbd31f9524b063ced1f49f1a6f6e063d2bf5
API_REPO_BASE=https://raw.githubusercontent.com/istio/api/ccd5cd40965ccba232d1f7c3b0e4ecacd0f6ceda
.PHONY: gen-api
gen-api: ## Generate API types from upstream files.
# TODO: should we get these files from the local filesystem by inspecting go.mod?
gen-api: tidy-go ## Generate API types from upstream files.
echo Generating API types from upstream files
curl -sSLfo /tmp/values_types.pb.go $(ISTIO_REPO_BASE)/operator/pkg/apis/istio/v1alpha1/values_types.pb.go
curl -sSLfo /tmp/config.pb.go $(API_REPO_BASE)/mesh/v1alpha1/config.pb.go
curl -sSLfo /tmp/network.pb.go $(API_REPO_BASE)/mesh/v1alpha1/network.pb.go
curl -sSLfo /tmp/proxy.pb.go $(API_REPO_BASE)/mesh/v1alpha1/proxy.pb.go
curl -sSLfo /tmp/proxy_config.pb.go $(API_REPO_BASE)/networking/v1beta1/proxy_config.pb.go
curl -sSLfo /tmp/selector.pb.go $(API_REPO_BASE)/type/v1beta1/selector.pb.go
curl -sSLfo /tmp/destination_rule.pb.go $(API_REPO_BASE)/networking/v1alpha3/destination_rule.pb.go
curl -sSLfo /tmp/virtual_service.pb.go $(API_REPO_BASE)/networking/v1alpha3/virtual_service.pb.go
go run hack/api_transformer/main.go hack/api_transformer/transform.yaml

.PHONY: gen-code
Expand Down Expand Up @@ -386,7 +374,7 @@ OUTPUT_DOCS_PATH := ./docs/api-reference
CONFIG_API_DOCS_GEN_PATH := ./hack/api-docs/config.yaml
TEMPLATES_DIR := ./hack/api-docs/templates/markdown

gen-api-docs: ## Generate API documentation.
gen-api-docs: ## Generate API documentation. Known issues: go fmt does not properly handle tabs and add new line empty. Workaround is applied to the generated markdown files. The crd-ref-docs tool add br tags to the generated markdown files. Workaround is applied to the generated markdown files.
@echo "Generating API documentation..."
@echo "CRD_PATH: $(CRD_PATH)"
mkdir -p $(OUTPUT_DOCS_PATH)
Expand All @@ -397,6 +385,9 @@ gen-api-docs: ## Generate API documentation.
--renderer=markdown \
--output-path=$(OUTPUT_DOCS_PATH) \
--output-mode=group
@find $(OUTPUT_DOCS_PATH) -type f -name "*.md" -exec sed -i 's/<br \/>/ /g' {} \;
@find $(OUTPUT_DOCS_PATH) -type f -name "*.md" -exec sed -i 's/\t/ /g' {} \;
@find $(OUTPUT_DOCS_PATH) -type f -name "*.md" -exec sed -i '/^```/,/^```/ {/./!d;}' {} \;
@echo "API reference documentation generated at $(OUTPUT_DOCS_PATH)"

.PHONY: restore-manifest-dates
Expand Down Expand Up @@ -442,6 +433,10 @@ CONTROLLER_TOOLS_VERSION ?= v0.15.0
OPM_VERSION ?= v1.45.0
GITLEAKS_VERSION ?= v8.18.4

# GENERATE_RELATED_IMAGES defines whether `spec.relatedImages` is going to be generated or not
# To disable set flag to false
GENERATE_RELATED_IMAGES ?= true

.PHONY: helm $(HELM)
helm: $(HELM) ## Download helm to bin directory. If wrong version is installed, it will be overwritten.
$(HELM): $(LOCALBIN)
Expand Down Expand Up @@ -483,6 +478,10 @@ $(GITLEAKS): $(LOCALBIN)
bundle: gen helm operator-sdk ## Generate bundle manifests and metadata, then validate generated files.
$(HELM) template chart chart $(HELM_TEMPL_DEF_FLAGS) --set image='$(IMAGE)' --set platform=openshift --set bundleGeneration=true | $(OPERATOR_SDK) generate bundle $(BUNDLE_GEN_FLAGS)

ifeq ($(GENERATE_RELATED_IMAGES), true)
@hack/patch-csv.sh bundle/manifests/$(OPERATOR_NAME).clusterserviceversion.yaml
endif

# update CSV's spec.customresourcedefinitions.owned field. ideally we could do this straight in ./bundle, but
# sadly this is only possible if the file lives in a `bases` directory
mkdir -p _tmp/bases
Expand All @@ -499,6 +498,7 @@ bundle: gen helm operator-sdk ## Generate bundle manifests and metadata, then va
git checkout "$$csvPath" || echo "failed to revert timestamp change. assuming we're in the middle of a merge"; \
fi \
fi

$(OPERATOR_SDK) bundle validate ./bundle

.PHONY: bundle-build
Expand Down
8 changes: 8 additions & 0 deletions PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ resources:
kind: Istio
path: github.com/istio-ecosystem/sail-operator/api/v1alpha1
version: v1alpha1
- api:
crdVersion: v1
namespaced: false
controller: true
domain: operator.istio.io
kind: RemoteIstio
path: github.com/istio-ecosystem/sail-operator/api/v1alpha1
version: v1alpha1
- api:
crdVersion: v1
namespaced: false
Expand Down
19 changes: 19 additions & 0 deletions api/v1alpha1/istiorevision_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ const (
// IstioRevisionSpec defines the desired state of IstioRevision
// +kubebuilder:validation:XValidation:rule="self.values.global.istioNamespace == self.__namespace__",message="spec.values.global.istioNamespace must match spec.namespace"
type IstioRevisionSpec struct {
// Type indicates whether this revision represents a local or a remote control plane installation.
// +kubebuilder:default=Local
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
Type IstioRevisionType `json:"type"`

// +sail:version
// Defines the version of Istio to install.
// Must be one of: v1.22.3, v1.22.2, v1.22.1, v1.22.0, v1.21.5, v1.21.4, v1.21.3, v1.21.2, v1.21.0, latest.
Expand Down Expand Up @@ -146,6 +151,9 @@ const (
// IstioRevisionReasonIstiodNotReady indicates that the control plane is fully reconciled, but istiod is not ready.
IstioRevisionReasonIstiodNotReady IstioRevisionConditionReason = "IstiodNotReady"

// IstioRevisionReasonRemoteIstiodNotReady indicates that the remote istiod is not ready.
IstioRevisionReasonRemoteIstiodNotReady IstioRevisionConditionReason = "RemoteIstiodNotReady"

// IstioRevisionReasonReadinessCheckFailed indicates that istiod readiness status could not be ascertained.
IstioRevisionReasonReadinessCheckFailed IstioRevisionConditionReason = "ReadinessCheckFailed"
)
Expand All @@ -169,9 +177,20 @@ const (
IstioRevisionReasonHealthy IstioRevisionConditionReason = "Healthy"
)

type IstioRevisionType string

const (
// IstioRevisionTypeLocal indicates that the revision represents a local control plane installation.
IstioRevisionTypeLocal IstioRevisionType = "Local"

// IstioRevisionTypeRemote indicates that the revision represents a remote control plane installation.
IstioRevisionTypeRemote IstioRevisionType = "Remote"
)

// +kubebuilder:object:root=true
// +kubebuilder:resource:scope=Cluster,shortName=istiorev,categories=istio-io
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Type",type="string",JSONPath=".spec.type",description="Whether the control plane is installed locally or in a remote cluster."
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description="Whether the control plane installation is ready to handle requests."
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.state",description="The current state of this object."
// +kubebuilder:printcolumn:name="In use",type="string",JSONPath=".status.conditions[?(@.type==\"InUse\")].status",description="Whether the revision is being used by workloads."
Expand Down
213 changes: 213 additions & 0 deletions api/v1alpha1/remoteistio_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
// Copyright Istio Authors
//
// 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 v1alpha1

import (
"time"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const RemoteIstioKind = "RemoteIstio"

// RemoteIstioSpec defines the desired state of RemoteIstio
// +kubebuilder:validation:XValidation:rule="!has(self.values) || !has(self.values.global) || !has(self.values.global.istioNamespace) || self.values.global.istioNamespace == self.__namespace__",message="spec.values.global.istioNamespace must match spec.namespace"
type RemoteIstioSpec struct {
// +sail:version
// Defines the version of Istio to install.
// Must be one of: v1.22.3, v1.22.2, v1.22.1, v1.22.0, v1.21.5, v1.21.4, v1.21.3, v1.21.2, v1.21.0, latest.
// +operator-sdk:csv:customresourcedefinitions:type=spec,order=1,displayName="Istio Version",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:fieldGroup:General", "urn:alm:descriptor:com.tectonic.ui:select:v1.22.3", "urn:alm:descriptor:com.tectonic.ui:select:v1.22.2", "urn:alm:descriptor:com.tectonic.ui:select:v1.22.1", "urn:alm:descriptor:com.tectonic.ui:select:v1.22.0", "urn:alm:descriptor:com.tectonic.ui:select:v1.21.5", "urn:alm:descriptor:com.tectonic.ui:select:v1.21.4", "urn:alm:descriptor:com.tectonic.ui:select:v1.21.3", "urn:alm:descriptor:com.tectonic.ui:select:v1.21.2", "urn:alm:descriptor:com.tectonic.ui:select:v1.21.0", "urn:alm:descriptor:com.tectonic.ui:select:latest"}
// +kubebuilder:validation:Enum=v1.22.3;v1.22.2;v1.22.1;v1.22.0;v1.21.5;v1.21.4;v1.21.3;v1.21.2;v1.21.0;latest
// +kubebuilder:default=v1.22.3
Version string `json:"version"`

// Defines the update strategy to use when the version in the RemoteIstio CR is updated.
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Update Strategy"
// +kubebuilder:default={type: "InPlace"}
UpdateStrategy *IstioUpdateStrategy `json:"updateStrategy,omitempty"`

// +sail:profile
// The built-in installation configuration profile to use.
// The 'default' profile is always applied. On OpenShift, the 'openshift' profile is also applied on top of 'default'.
// Must be one of: ambient, default, demo, empty, external, minimal, openshift-ambient, openshift, preview, remote, stable.
// +++PROFILES-DROPDOWN-HIDDEN-UNTIL-WE-FULLY-IMPLEMENT-THEM+++operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Profile",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:fieldGroup:General", "urn:alm:descriptor:com.tectonic.ui:select:ambient", "urn:alm:descriptor:com.tectonic.ui:select:default", "urn:alm:descriptor:com.tectonic.ui:select:demo", "urn:alm:descriptor:com.tectonic.ui:select:empty", "urn:alm:descriptor:com.tectonic.ui:select:external", "urn:alm:descriptor:com.tectonic.ui:select:minimal", "urn:alm:descriptor:com.tectonic.ui:select:preview", "urn:alm:descriptor:com.tectonic.ui:select:remote"}
// +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:hidden"}
// +kubebuilder:validation:Enum=ambient;default;demo;empty;external;minimal;openshift-ambient;openshift;preview;remote;stable
Profile string `json:"profile,omitempty"`

// Namespace to which the Istio components should be installed.
// +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:io.kubernetes:Namespace"}
// +kubebuilder:default=istio-system
Namespace string `json:"namespace"`

// Defines the values to be passed to the Helm charts when installing Istio.
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Helm Values"
Values *Values `json:"values,omitempty"`
}

// RemoteIstioStatus defines the observed state of RemoteIstio
type RemoteIstioStatus struct {
// ObservedGeneration is the most recent generation observed for this
// RemoteIstio object. It corresponds to the object's generation, which is
// updated on mutation by the API Server. The information in the status
// pertains to this particular generation of the object.
ObservedGeneration int64 `json:"observedGeneration,omitempty"`

// Represents the latest available observations of the object's current state.
Conditions []RemoteIstioCondition `json:"conditions,omitempty"`

// Reports the current state of the object.
State RemoteIstioConditionReason `json:"state,omitempty"`

// Reports information about the underlying IstioRevisions.
Revisions RevisionSummary `json:"revisions,omitempty"`
}

// GetCondition returns the condition of the specified type
func (s *RemoteIstioStatus) GetCondition(conditionType RemoteIstioConditionType) RemoteIstioCondition {
if s != nil {
for i := range s.Conditions {
if s.Conditions[i].Type == conditionType {
return s.Conditions[i]
}
}
}
return RemoteIstioCondition{Type: conditionType, Status: metav1.ConditionUnknown}
}

// SetCondition sets a specific condition in the list of conditions
func (s *RemoteIstioStatus) SetCondition(condition RemoteIstioCondition) {
var now time.Time
if testTime == nil {
now = time.Now()
} else {
now = *testTime
}

// The lastTransitionTime only gets serialized out to the second. This can
// break update skipping, as the time in the resource returned from the client
// may not match the time in our cached status during a reconcile. We truncate
// here to save any problems down the line.
lastTransitionTime := metav1.NewTime(now.Truncate(time.Second))

for i, prevCondition := range s.Conditions {
if prevCondition.Type == condition.Type {
if prevCondition.Status != condition.Status {
condition.LastTransitionTime = lastTransitionTime
} else {
condition.LastTransitionTime = prevCondition.LastTransitionTime
}
s.Conditions[i] = condition
return
}
}

// If the condition does not exist, initialize the lastTransitionTime
condition.LastTransitionTime = lastTransitionTime
s.Conditions = append(s.Conditions, condition)
}

// RemoteIstioCondition represents a specific observation of the RemoteIstioCondition object's state.
type RemoteIstioCondition struct {
// The type of this condition.
Type RemoteIstioConditionType `json:"type,omitempty"`

// The status of this condition. Can be True, False or Unknown.
Status metav1.ConditionStatus `json:"status,omitempty"`

// Unique, single-word, CamelCase reason for the condition's last transition.
Reason RemoteIstioConditionReason `json:"reason,omitempty"`

// Human-readable message indicating details about the last transition.
Message string `json:"message,omitempty"`

// Last time the condition transitioned from one status to another.
LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`
}

// RemoteIstioConditionType represents the type of the condition. Condition stages are:
// Installed, Reconciled, Ready
type RemoteIstioConditionType string

// RemoteIstioConditionReason represents a short message indicating how the condition came
// to be in its present state.
type RemoteIstioConditionReason string

const (
// RemoteIstioConditionReconciled signifies whether the controller has
// successfully reconciled the resources defined through the CR.
RemoteIstioConditionReconciled RemoteIstioConditionType = "Reconciled"

// RemoteIstioReasonReconcileError indicates that the reconciliation of the resource has failed, but will be retried.
RemoteIstioReasonReconcileError RemoteIstioConditionReason = "ReconcileError"
)

const (
// RemoteIstioConditionReady signifies whether any Deployment, StatefulSet,
// etc. resources are Ready.
RemoteIstioConditionReady RemoteIstioConditionType = "Ready"

// RemoteIstioReasonRevisionNotFound indicates that the active IstioRevision is not found.
RemoteIstioReasonRevisionNotFound RemoteIstioConditionReason = "ActiveRevisionNotFound"

// RemoteIstioReasonFailedToGetActiveRevision indicates that a failure occurred when getting the active IstioRevision
RemoteIstioReasonFailedToGetActiveRevision RemoteIstioConditionReason = "FailedToGetActiveRevision"

// RemoteIstioReasonIstiodNotReady indicates that the control plane is fully reconciled, but istiod is not ready.
RemoteIstioReasonIstiodNotReady RemoteIstioConditionReason = "IstiodNotReady"

// RemoteIstioReasonReadinessCheckFailed indicates that readiness could not be ascertained.
RemoteIstioReasonReadinessCheckFailed RemoteIstioConditionReason = "ReadinessCheckFailed"
)

const (
// RemoteIstioReasonHealthy indicates that the control plane is fully reconciled and that all components are ready.
RemoteIstioReasonHealthy RemoteIstioConditionReason = "Healthy"
)

// +kubebuilder:object:root=true
// +kubebuilder:resource:scope=Cluster,categories=istio-io
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Revisions",type="string",JSONPath=".status.revisions.total",description="Total number of IstioRevision objects currently associated with this object."
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.revisions.ready",description="Number of revisions that are ready."
// +kubebuilder:printcolumn:name="In use",type="string",JSONPath=".status.revisions.inUse",description="Number of revisions that are currently being used by workloads."
// +kubebuilder:printcolumn:name="Active Revision",type="string",JSONPath=".status.state",description="The current state of the active revision."
// +kubebuilder:printcolumn:name="Version",type="string",JSONPath=".spec.version",description="The version of the control plane installation."
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of the object"

// RemoteIstio represents a remote Istio Service Mesh deployment consisting of one or more
// remote control plane instances (represented by one or more IstioRevision objects).
type RemoteIstio struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

// +kubebuilder:default={version: "v1.22.3", namespace: "istio-system", updateStrategy: {type:"InPlace"}}
Spec RemoteIstioSpec `json:"spec,omitempty"`

Status RemoteIstioStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

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

func init() {
SchemeBuilder.Register(&RemoteIstio{}, &RemoteIstioList{})
}
Loading

0 comments on commit 187498d

Please sign in to comment.