Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This commit contains the first versions of the various CRDs and some logic for the controllers. Signed-off-by: Simon Beck <simon.beck@vshn.ch>
- Loading branch information
Showing
41 changed files
with
2,988 additions
and
0 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 |
---|---|---|
@@ -0,0 +1 @@ | ||
build/_output/* |
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,17 @@ | ||
{ | ||
// Use IntelliSense to learn about possible attributes. | ||
// Hover to view descriptions of existing attributes. | ||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||
"version": "0.2.0", | ||
"configurations": [ | ||
{ | ||
"name": "Launch", | ||
"type": "go", | ||
"request": "launch", | ||
"mode": "auto", | ||
"program": "${workspaceFolder}/cmd/manager/main.go", | ||
"env": {}, | ||
"args": [] | ||
} | ||
] | ||
} |
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,15 @@ | ||
FROM registry.access.redhat.com/ubi8/ubi-minimal:latest | ||
|
||
ENV OPERATOR=/usr/local/bin/lieutenant-operator \ | ||
USER_UID=1001 \ | ||
USER_NAME=lieutenant-operator | ||
|
||
# install operator binary | ||
COPY build/_output/bin/lieutenant-operator ${OPERATOR} | ||
|
||
COPY build/bin /usr/local/bin | ||
RUN /usr/local/bin/user_setup | ||
|
||
ENTRYPOINT ["/usr/local/bin/entrypoint"] | ||
|
||
USER ${USER_UID} |
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,12 @@ | ||
#!/bin/sh -e | ||
|
||
# This is documented here: | ||
# 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:-lieutenant-operator}:x:$(id -u):$(id -g):${USER_NAME:-lieutenant-operator} user:${HOME}:/sbin/nologin" >> /etc/passwd | ||
fi | ||
fi | ||
|
||
exec ${OPERATOR} $@ |
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,13 @@ | ||
#!/bin/sh | ||
set -x | ||
|
||
# ensure $HOME exists and is accessible by group 0 (we don't know what the runtime UID will be) | ||
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 |
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 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/projectsyn/lieutenant-operator/pkg/apis" | ||
"github.com/projectsyn/lieutenant-operator/pkg/controller" | ||
"github.com/projectsyn/lieutenant-operator/version" | ||
|
||
"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" | ||
sdkVersion "github.com/operator-framework/operator-sdk/version" | ||
"github.com/spf13/pflag" | ||
v1 "k8s.io/api/core/v1" | ||
"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" | ||
) | ||
|
||
// Change below variables to serve metrics on different host or port. | ||
var ( | ||
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)) | ||
} | ||
|
||
func main() { | ||
// Add the zap logger flag set to the CLI. The flag set must | ||
// be added before calling pflag.Parse(). | ||
pflag.CommandLine.AddFlagSet(zap.FlagSet()) | ||
|
||
// Add flags registered by imported packages (e.g. glog and | ||
// controller-runtime) | ||
pflag.CommandLine.AddGoFlagSet(flag.CommandLine) | ||
|
||
pflag.Parse() | ||
|
||
// Use a zap logr.Logger implementation. If none of the zap | ||
// flags are configured (or if the zap flag set is not being | ||
// used), this defaults to a production zap logger. | ||
// | ||
// The logger instantiated here can be changed to any logger | ||
// implementing the logr.Logger interface. This logger will | ||
// be propagated through the whole operator, generating | ||
// uniform and structured logs. | ||
logf.SetLogger(zap.Logger()) | ||
|
||
printVersion() | ||
|
||
namespace, err := k8sutil.GetWatchNamespace() | ||
if err != nil { | ||
log.Info("Failed to get watch namespace, setting empty") | ||
namespace = "" | ||
} | ||
|
||
// Get a config to talk to the apiserver | ||
cfg, err := config.GetConfig() | ||
if err != nil { | ||
log.Error(err, "") | ||
os.Exit(1) | ||
} | ||
|
||
ctx := context.TODO() | ||
// Become the leader before proceeding | ||
err = leader.Become(ctx, "lieutenant-operator-lock") | ||
if err != nil { | ||
log.Error(err, "") | ||
os.Exit(1) | ||
} | ||
|
||
// Create a new Cmd to provide shared dependencies and start components | ||
mgr, err := manager.New(cfg, manager.Options{ | ||
Namespace: namespace, | ||
MetricsBindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort), | ||
}) | ||
if err != nil { | ||
log.Error(err, "") | ||
os.Exit(1) | ||
} | ||
|
||
log.Info("Registering Components.") | ||
|
||
// Setup Scheme for all resources | ||
if err := apis.AddToScheme(mgr.GetScheme()); err != nil { | ||
log.Error(err, "") | ||
os.Exit(1) | ||
} | ||
|
||
// Setup all Controllers | ||
if err := controller.AddToManager(mgr); err != nil { | ||
log.Error(err, "") | ||
os.Exit(1) | ||
} | ||
|
||
// Add the Metrics Service | ||
addMetrics(ctx, cfg, namespace) | ||
|
||
log.Info("Starting the Cmd.") | ||
|
||
// Start the Cmd | ||
if err := mgr.Start(signals.SetupSignalHandler()); err != nil { | ||
log.Error(err, "Manager exited non-zero") | ||
os.Exit(1) | ||
} | ||
} | ||
|
||
// 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. | ||
filteredGVK, err := k8sutil.GetGVKsFromAddToScheme(apis.AddToScheme) | ||
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 | ||
} |
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,147 @@ | ||
apiVersion: apiextensions.k8s.io/v1beta1 | ||
kind: CustomResourceDefinition | ||
metadata: | ||
name: clusters.syn.tools | ||
spec: | ||
group: syn.tools | ||
names: | ||
kind: Cluster | ||
listKind: ClusterList | ||
plural: clusters | ||
singular: cluster | ||
scope: Namespaced | ||
subresources: | ||
status: {} | ||
validation: | ||
openAPIV3Schema: | ||
description: Cluster is the Schema for the clusters 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: ClusterSpec defines the desired state of Cluster | ||
properties: | ||
apiEndpointSecretRef: | ||
description: APIEndpointSecretRef references the secret containing connection | ||
information to Kubernetes API endpoint of the registered Kubernetes | ||
cluster. | ||
properties: | ||
name: | ||
description: Name is unique within a namespace to reference a secret | ||
resource. | ||
type: string | ||
namespace: | ||
description: Namespace defines the space within which the secret | ||
name must be unique. | ||
type: string | ||
type: object | ||
displayName: | ||
description: DisplayName of cluster which could be different from metadata.name. | ||
Allows cluster renaming should it be needed. | ||
type: string | ||
facts: | ||
additionalProperties: | ||
description: FactValue is the value for the facts map | ||
type: string | ||
description: Facts are key/value pairs for statically configured facts | ||
type: object | ||
gitRepoTemplate: | ||
description: GitRepoTemplate template for managing the GitRepo object. | ||
properties: | ||
spec: | ||
description: GitRepoSpec defines the desired state of GitRepo | ||
properties: | ||
apiSecretRef: | ||
description: APISecretRef reference to secret containing connection | ||
information | ||
properties: | ||
name: | ||
description: Name is unique within a namespace to reference | ||
a secret resource. | ||
type: string | ||
namespace: | ||
description: Namespace defines the space within which the | ||
secret name must be unique. | ||
type: string | ||
type: object | ||
deployKeys: | ||
description: DeployKeys optional list of SSH deploy keys. If | ||
not set, not deploy keys will be configured | ||
items: | ||
description: DeployKey defines an SSH key to be used for git | ||
operations. | ||
properties: | ||
key: | ||
type: string | ||
type: | ||
type: string | ||
writeAccess: | ||
type: boolean | ||
type: object | ||
type: array | ||
path: | ||
description: Path to Git repository | ||
type: string | ||
repoName: | ||
description: RepoName ame of Git repository | ||
type: string | ||
tenantRef: | ||
description: TenantRef references the tenant this repo belongs | ||
to | ||
properties: | ||
name: | ||
type: string | ||
namespace: | ||
type: string | ||
type: object | ||
type: object | ||
type: object | ||
gitRepoURL: | ||
description: GitRepoURL git repository storing the cluster configuration | ||
catalog. If this is set, no gitRepoTemplate is needed. | ||
type: string | ||
tenantRef: | ||
description: TenantRef reference to Tenant object the cluster belongs | ||
to. | ||
properties: | ||
name: | ||
type: string | ||
namespace: | ||
type: string | ||
type: object | ||
tokenLifeTime: | ||
description: TokenLifetime set the token lifetime | ||
type: string | ||
type: object | ||
status: | ||
description: ClusterStatus defines the observed state of Cluster | ||
properties: | ||
bootstrapToken: | ||
description: BootstrapTokenValid validity of the bootstrap token, set | ||
by the Lieutenant API. | ||
properties: | ||
bootstrapTokenValid: | ||
type: boolean | ||
token: | ||
type: string | ||
validUntil: | ||
format: date-time | ||
type: string | ||
type: object | ||
type: object | ||
type: object | ||
version: v1alpha1 | ||
versions: | ||
- name: v1alpha1 | ||
served: true | ||
storage: true |
Oops, something went wrong.