Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Needed changes operator sdk upgrade #327

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
9dbc7f7
Update tools.go which does not need content anymore
miguelsorianod Feb 17, 2020
dcea7d5
Set same dependencies as a new operator-sdk v0.15.2 project with an a…
miguelsorianod Feb 17, 2020
df7c554
Add 3scale project specific dependencies automatically added by go lo…
miguelsorianod Feb 17, 2020
2926986
Replace ExposeMetricsPort by CreateMetricsService
miguelsorianod Feb 17, 2020
267d999
Fix ListOptions change of signature
miguelsorianod Feb 17, 2020
06a1900
Add dependencies that are specific to the templates generator binary …
miguelsorianod Feb 17, 2020
f33c920
Remove deprecated IncludeUninitialized attribute from Options
miguelsorianod Feb 17, 2020
395956b
Add dependencies that are added when compiling/running unit tests, in…
miguelsorianod Feb 17, 2020
68ba843
Add dependencies added by go mod tidy
miguelsorianod Feb 17, 2020
1277c31
Replace deprecated controller-runtime scheme package location
miguelsorianod Feb 17, 2020
82d994c
Replace deprecated controller-runtime signals package location
miguelsorianod Feb 17, 2020
22a8ed3
Replace deprecated controller-runtime log package location
miguelsorianod Feb 17, 2020
deadc47
Upgrade Dockerfile base image from ubi7minimal to ubi8minimal
miguelsorianod Feb 17, 2020
18957db
Print operator version when running the operator binary
miguelsorianod Feb 17, 2020
e5846b6
Remove DynamicRestMapper operator-sdk implementation and use controll…
miguelsorianod Feb 17, 2020
847d269
Update cmd/manager/main.go to include refactors and additions by oper…
miguelsorianod Feb 17, 2020
c728f43
Modify operator user setup and entrypoint scripts to no longer dynami…
miguelsorianod Feb 17, 2020
eebb91d
Update operator.yaml to add a comment to make more clear image is to …
miguelsorianod Feb 17, 2020
f3d3976
Add service/finalizers into role.yaml
miguelsorianod Feb 17, 2020
2989442
Replace '*' by set of verbs and reorder some array elements
miguelsorianod Feb 17, 2020
523dcc9
Define groups.go file with explicit package name on the api groups di…
miguelsorianod Feb 17, 2020
baf3ac8
Update initial reconcile logging in APIManager controller
miguelsorianod Feb 17, 2020
1366918
Rename CRD yaml files to new naming format
miguelsorianod Feb 17, 2020
5ebe08e
Rename olm-catalog CRD symlinks to the new CRD names
miguelsorianod Feb 17, 2020
278ad05
Rename CR yaml files to new naming format
miguelsorianod Feb 17, 2020
de68074
Update CRD validation tests to use the new CRD and CR names
miguelsorianod Feb 17, 2020
196df08
Set scope as kubebuilder annotation
miguelsorianod Feb 17, 2020
bd70307
BREAKING CHANGE: Change PlanCost fields from float64 to string due to…
miguelsorianod Feb 17, 2020
ee57a6a
Generate k8s and openapi
miguelsorianod Feb 17, 2020
e612ad8
Regenerate APIManager CRD
miguelsorianod Feb 17, 2020
29f54d3
Regenerate Capabilities CRDs
miguelsorianod Feb 17, 2020
f5d1a9d
generator: update templates with the new kubernetes api being used
miguelsorianod Feb 17, 2020
f12d264
Use operator-sdk v0.15.2 in CircleCI and update documentation
miguelsorianod Feb 17, 2020
e3f6451
Makefile: up local is now run --local
miguelsorianod Feb 17, 2020
ffefb31
Reorganize deploy/olm-catalog/3scale-operator-master to multi-CSV ver…
miguelsorianod Feb 17, 2020
12df9ed
Add CSV code annotations to autogenerate APIManager owned resources i…
miguelsorianod Feb 17, 2020
e8c27fd
Add CSV autogeneration info for APIManager WildcardDomain and Status …
miguelsorianod Feb 17, 2020
54a6f6f
auto-regenerate 3scale-operator-master CSV
miguelsorianod Feb 17, 2020
7c788be
Update some CSV description attributes and links
miguelsorianod Feb 17, 2020
0250537
Update licenses.xml
miguelsorianod Feb 17, 2020
94402d3
Ensure returned DeploymentConfigs in APIManager controller are ordered
miguelsorianod Feb 17, 2020
b7d2280
Add DisplayName CSV annotation in all operator API types
miguelsorianod Feb 17, 2020
61d3d73
Update CSV to include autogenerated DisplayName fields on owned resou…
miguelsorianod Feb 17, 2020
df49604
Filter the GVKs to desired ones
miguelsorianod Feb 18, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ commands:
- run:
name: Install operator-sdk
command: |
export OPERATOR_SDK_RELEASE_VERSION=v0.8.0
export OPERATOR_SDK_RELEASE_VERSION=v0.15.2
curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${OPERATOR_SDK_RELEASE_VERSION}/operator-sdk-${OPERATOR_SDK_RELEASE_VERSION}-x86_64-linux-gnu
chmod +x operator-sdk-${OPERATOR_SDK_RELEASE_VERSION}-x86_64-linux-gnu && sudo cp operator-sdk-${OPERATOR_SDK_RELEASE_VERSION}-x86_64-linux-gnu /usr/local/bin/operator-sdk && rm operator-sdk-${OPERATOR_SDK_RELEASE_VERSION}-x86_64-linux-gnu

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ tag:

## local: push operator docker image to remote repo
local:
OPERATOR_NAME=$(OPERATOR_NAME) $(OPERATOR_SDK) up local --namespace $(NAMESPACE)
OPERATOR_NAME=$(OPERATOR_NAME) $(OPERATOR_SDK) run --local --namespace $(NAMESPACE)

## e2e-setup: create OCP project for the operator
e2e-setup:
Expand Down
2 changes: 1 addition & 1 deletion build/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM registry.access.redhat.com/ubi7/ubi-minimal:latest
FROM registry.access.redhat.com/ubi8/ubi-minimal:latest
eguzki marked this conversation as resolved.
Show resolved Hide resolved

ENV OPERATOR=/usr/local/bin/3scale-operator \
USER_UID=1001 \
Expand Down
9 changes: 0 additions & 9 deletions build/bin/entrypoint
Original file line number Diff line number Diff line change
@@ -1,12 +1,3 @@
#!/bin/sh -e

# This is documented here:
eguzki marked this conversation as resolved.
Show resolved Hide resolved
# https://docs.openshift.com/container-platform/3.11/creating_images/guidelines.html#openshift-specific-guidelines

if ! whoami &>/dev/null; then
if [ -w /etc/passwd ]; then
echo "${USER_NAME:-3scale-operator}:x:$(id -u):$(id -g):${USER_NAME:-3scale-operator} user:${HOME}:/sbin/nologin" >> /etc/passwd
fi
fi

exec ${OPERATOR} $@
4 changes: 1 addition & 3 deletions build/bin/user_setup
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@
set -x

# ensure $HOME exists and is accessible by group 0 (we don't know what the runtime UID will be)
echo "${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin" >> /etc/passwd
mkdir -p ${HOME}
chown ${USER_UID}:0 ${HOME}
chmod ug+rwx ${HOME}

# runtime user will need to be able to self-insert in /etc/passwd
chmod g+rw /etc/passwd

# no need for this script to remain in the image after running
rm $0
157 changes: 145 additions & 12 deletions cmd/manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ package main

import (
"context"
"errors"
"flag"
"fmt"
"os"
"runtime"

// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
_ "k8s.io/client-go/plugin/pkg/client/auth"
"k8s.io/client-go/rest"

"github.com/3scale/3scale-operator/pkg/3scale/amp/product"
"github.com/3scale/3scale-operator/pkg/apis"
Expand All @@ -17,27 +19,32 @@ import (
"github.com/prometheus/client_golang/prometheus"

"github.com/operator-framework/operator-sdk/pkg/k8sutil"
kubemetrics "github.com/operator-framework/operator-sdk/pkg/kube-metrics"
"github.com/operator-framework/operator-sdk/pkg/leader"
"github.com/operator-framework/operator-sdk/pkg/log/zap"
"github.com/operator-framework/operator-sdk/pkg/metrics"
"github.com/operator-framework/operator-sdk/pkg/restmapper"
sdkVersion "github.com/operator-framework/operator-sdk/version"
"github.com/spf13/pflag"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/intstr"
"sigs.k8s.io/controller-runtime/pkg/client/config"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/manager/signals"
crmetrics "sigs.k8s.io/controller-runtime/pkg/metrics"
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
"sigs.k8s.io/controller-runtime/pkg/runtime/signals"
)

// Change below variables to serve metrics on different host or port.
var (
metricsHost = "0.0.0.0"
metricsPort int32 = 8383
metricsHost = "0.0.0.0"
metricsPort int32 = 8383
operatorMetricsPort int32 = 8686
)
var log = logf.Log.WithName("cmd")

func printVersion() {
log.Info(fmt.Sprintf("Operator Version: %s", version.Version))
log.Info(fmt.Sprintf("Go Version: %s", runtime.Version()))
log.Info(fmt.Sprintf("Go OS/Arch: %s/%s", runtime.GOOS, runtime.GOARCH))
log.Info(fmt.Sprintf("Version of operator-sdk: %v", sdkVersion.Version))
Expand Down Expand Up @@ -80,7 +87,6 @@ func main() {
}

ctx := context.TODO()

// Become the leader before proceeding
err = leader.Become(ctx, "3scale-operator-lock")
if err != nil {
Expand All @@ -91,7 +97,6 @@ func main() {
// Create a new Cmd to provide shared dependencies and start components
mgr, err := manager.New(cfg, manager.Options{
Namespace: namespace,
MapperProvider: restmapper.NewDynamicRESTMapper,
MetricsBindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort),
})
if err != nil {
Expand All @@ -115,11 +120,8 @@ func main() {

register3scaleVersionInfoMetric()

// Create Service object to expose the metrics port.
_, err = metrics.ExposeMetricsPort(ctx, metricsPort)
if err != nil {
log.Info(err.Error())
}
// Add the Metrics Service
addMetrics(ctx, cfg, namespace)

log.Info("Starting the Cmd.")

Expand All @@ -144,3 +146,134 @@ func register3scaleVersionInfoMetric() {
// Register custom metrics with the global prometheus registry
crmetrics.Registry.MustRegister(threeScaleVersionInfo)
}

// addMetrics will create the Services and Service Monitors to allow the operator export the metrics by using
// the Prometheus operator
func addMetrics(ctx context.Context, cfg *rest.Config, namespace string) {
if err := serveCRMetrics(cfg); err != nil {
if errors.Is(err, k8sutil.ErrRunLocal) {
log.Info("Skipping CR metrics server creation; not running in a cluster.")
return
}
log.Info("Could not generate and serve custom resource metrics", "error", err.Error())
}

// Add to the below struct any other metrics ports you want to expose.
servicePorts := []v1.ServicePort{
{Port: metricsPort, Name: metrics.OperatorPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: metricsPort}},
{Port: operatorMetricsPort, Name: metrics.CRPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: operatorMetricsPort}},
}

// Create Service object to expose the metrics port(s).
service, err := metrics.CreateMetricsService(ctx, cfg, servicePorts)
if err != nil {
log.Info("Could not create metrics Service", "error", err.Error())
}

// CreateServiceMonitors will automatically create the prometheus-operator ServiceMonitor resources
// necessary to configure Prometheus to scrape metrics from this operator.
services := []*v1.Service{service}
_, err = metrics.CreateServiceMonitors(cfg, namespace, services)
if err != nil {
log.Info("Could not create ServiceMonitor object", "error", err.Error())
// If this operator is deployed to a cluster without the prometheus-operator running, it will return
// ErrServiceMonitorNotPresent, which can be used to safely skip ServiceMonitor creation.
if err == metrics.ErrServiceMonitorNotPresent {
log.Info("Install prometheus-operator in your cluster to create ServiceMonitor objects", "error", err.Error())
}
}
}

// serveCRMetrics gets the Operator/CustomResource GVKs and generates metrics based on those types.
// It serves those metrics on "http://metricsHost:operatorMetricsPort".
func serveCRMetrics(cfg *rest.Config) error {
// Below function returns filtered operator/CustomResource specific GVKs.
// For more control override the below GVK list with your own custom logic.
gvks, err := k8sutil.GetGVKsFromAddToScheme(apis.AddToScheme)
if err != nil {
return err
}

// We perform our custom GKV filtering on top of the one performed
// by operator-sdk code
filteredGVK := filterGKVsFromAddToScheme(gvks)
if err != nil {
return err
}

// Get the namespace the operator is currently deployed in.
operatorNs, err := k8sutil.GetOperatorNamespace()
if err != nil {
return err
}
// To generate metrics in other namespaces, add the values below.
ns := []string{operatorNs}
// Generate and serve custom resource specific metrics.
err = kubemetrics.GenerateAndServeCRMetrics(cfg, ns, filteredGVK, metricsHost, operatorMetricsPort)
if err != nil {
return err
}
return nil
}

func filterGKVsFromAddToScheme(gvks []schema.GroupVersionKind) []schema.GroupVersionKind {
// We use gkvFilters to filter from the existing GKVs defined in the used
// runtime.Schema for the operator. The reason for that is that
// kube-metrics tries to list all of the defined Kinds in the schemas
// that are passed, including Kinds that the operator doesn't use and
// thus the role used the operator doesn't have them set and we don't want
// to set as they are not used by the operator.
// For the fields that the filters have we have defined the value '*' to
// specify any will be a match (accepted)
matchAnyValue := "*"
gvkFilters := []schema.GroupVersionKind{
// Kubernetes types
schema.GroupVersionKind{Kind: "PersistentVolumeClaim", Version: matchAnyValue},
schema.GroupVersionKind{Kind: "ServiceAccount", Version: matchAnyValue},
schema.GroupVersionKind{Kind: "Secret", Version: matchAnyValue},
schema.GroupVersionKind{Kind: "Pod", Version: matchAnyValue},
schema.GroupVersionKind{Kind: "ConfigMap", Version: matchAnyValue},
schema.GroupVersionKind{Kind: "Service", Version: matchAnyValue},

// OpenShift types
schema.GroupVersionKind{Group: "route.openshift.io", Kind: "Route", Version: matchAnyValue},
schema.GroupVersionKind{Group: "image.openshift.io", Kind: "ImageStream", Version: matchAnyValue},
schema.GroupVersionKind{Group: "apps.openshift.io", Kind: "DeploymentConfig", Version: matchAnyValue},

// Custom resource types
schema.GroupVersionKind{Group: "capabilities.3scale.net", Kind: "Plan", Version: matchAnyValue},
schema.GroupVersionKind{Group: "capabilities.3scale.net", Kind: "API", Version: matchAnyValue},
schema.GroupVersionKind{Group: "capabilities.3scale.net", Kind: "Limit", Version: matchAnyValue},
schema.GroupVersionKind{Group: "capabilities.3scale.net", Kind: "MappingRule", Version: matchAnyValue},
schema.GroupVersionKind{Group: "capabilities.3scale.net", Kind: "Tenant", Version: matchAnyValue},
schema.GroupVersionKind{Group: "capabilities.3scale.net", Kind: "Metric", Version: matchAnyValue},
schema.GroupVersionKind{Group: "capabilities.3scale.net", Kind: "Binding", Version: matchAnyValue},
schema.GroupVersionKind{Group: "apps.3scale.net", Kind: "APIManager", Version: matchAnyValue},
}

ownGVKs := []schema.GroupVersionKind{}
for _, gvk := range gvks {
for _, gvkFilter := range gvkFilters {
match := true
if gvkFilter.Kind == matchAnyValue && gvkFilter.Group == matchAnyValue && gvkFilter.Version == matchAnyValue {
log.V(1).Info("gvkFilter should at least have one of its fields defined. Skipping...")
match = false
} else {
if gvkFilter.Kind != matchAnyValue && gvkFilter.Kind != gvk.Kind {
match = false
}
if gvkFilter.Group != matchAnyValue && gvkFilter.Group != gvk.Group {
match = false
}
if gvkFilter.Version != matchAnyValue && gvkFilter.Version != gvk.Version {
match = false
}
}
if match {
ownGVKs = append(ownGVKs, gvk)
}
}
}

return ownGVKs
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,22 @@ spec:
status: {}
validation:
openAPIV3Schema:
description: APIManager is the Schema for the apimanagers 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/api-conventions.md#resources'
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/api-conventions.md#types-kinds'
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: APIManagerSpec defines the desired state of APIManager
properties:
apicast:
properties:
Expand Down Expand Up @@ -126,18 +128,20 @@ spec:
description: Deprecated
type: string
awsCredentialsSecret:
description: Deprecated
properties:
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
description: Deprecated
type: object
awsRegion:
description: Deprecated
type: string
required:
- awsBucket
- awsRegion
- awsCredentialsSecret
- awsRegion
type: object
persistentVolumeClaim:
description: Union type. Only one of the fields can be set.
Expand All @@ -148,10 +152,15 @@ spec:
simpleStorageService:
properties:
configurationSecretRef:
type: object
description: LocalObjectReference contains enough information
to let you locate the referenced object inside the same
namespace.
properties:
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
type: object
required:
- configurationSecretRef
type: object
Expand All @@ -172,6 +181,7 @@ spec:
tenantName:
type: string
wildcardDomain:
description: Wildcard domain as configured in the API Manager object
type: string
zync:
properties:
Expand All @@ -196,6 +206,7 @@ spec:
- wildcardDomain
type: object
status:
description: APIManagerStatus defines the observed state of APIManager
properties:
conditions:
items:
Expand All @@ -205,11 +216,12 @@ spec:
type:
type: string
required:
- type
- status
- type
type: object
type: array
deployments:
description: APIManager Deployment Configs
properties:
ready:
description: Deployments are ready to serve requests
Expand All @@ -231,6 +243,7 @@ spec:
required:
- deployments
type: object
type: object
version: v1alpha1
versions:
- name: v1alpha1
Expand Down
Loading