Skip to content

Commit

Permalink
feat: labeler logic (#1)
Browse files Browse the repository at this point in the history
* feat: labeler logic

* chore: remove example input

* fix: ineffective assignment

* chore: pin crossplane version

* ci: push package to ghcr

* fix: ci login

* Revert "fix: ci login"

This reverts commit 79f000c.

* fix: use GITHUB_TOKEN

* fix: correct user for login

* fix: error handling

* fix: get namespace from claimref

* feat: configurable label

* fix: create fluentd

* fix: unit tests

* chore: remove commented code

* address review
  • Loading branch information
niklastreml authored Feb 21, 2024
1 parent 23f7cab commit 042a302
Show file tree
Hide file tree
Showing 12 changed files with 290 additions and 98 deletions.
35 changes: 19 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
name: CI

permissions:
contents: write
packages: write

on:
push:
branches:
Expand All @@ -14,23 +18,23 @@ on:

env:
# Common versions
GO_VERSION: '1.21.3'
GOLANGCI_VERSION: 'v1.54.2'
DOCKER_BUILDX_VERSION: 'v0.11.2'
GO_VERSION: "1.21.3"
GOLANGCI_VERSION: "v1.54.2"
DOCKER_BUILDX_VERSION: "v0.11.2"

# These environment variables are important to the Crossplane CLI install.sh
# script. They determine what version it installs.
XP_CHANNEL: master # TODO(negz): Pin to stable once v1.14 is released.
XP_VERSION: current # TODO(negz): Pin to a version once v1.14 is released.
XP_CHANNEL: stable # TODO(negz): Pin to stable once v1.14 is released.
XP_VERSION: v1.14.0 # TODO(negz): Pin to a version once v1.14 is released.

# This CI job will automatically push new builds to xpkg.upbound.io if the
# XPKG_ACCESS_ID and XPKG_TOKEN secrets are set in the GitHub respository (or
# organization) settings. Create a token at https://accounts.upbound.io.
XPKG_ACCESS_ID: ${{ secrets.XPKG_ACCESS_ID }}
XPKG_ACCESS_ID: ${{ github.repository_owner }}

# The package to push, without a version tag. The default matches GitHub. For
# example xpkg.upbound.io/crossplane/function-template-go.
XPKG: xpkg.upbound.io/${{ github.repository}}
XPKG: ghcr.io/${{ github.repository}}

# The package version to push. The default is 0.0.0-gitsha.
XPKG_VERSION: ${{ inputs.version }}
Expand All @@ -46,7 +50,7 @@ jobs:
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
cache: false # The golangci-lint action does its own caching.
cache: false # The golangci-lint action does its own caching.

- name: Lint
uses: golangci/golangci-lint-action@v3
Expand All @@ -70,7 +74,7 @@ jobs:
# We want to build most packages for the amd64 and arm64 architectures. To
# speed this up we build single-platform packages in parallel. We then upload
# those packages to GitHub as a build artifact. The push job downloads those
# artifacts and pushes them as a single multi-platform package.
# artifacts and pushes them as a single multi-platform package.
build:
runs-on: ubuntu-22.04
strategy:
Expand Down Expand Up @@ -105,16 +109,15 @@ jobs:
cache-from: type=gha
cache-to: type=gha,mode=max
target: image
build-args:
GO_VERSION=${{ env.GO_VERSION }}
build-args: GO_VERSION=${{ env.GO_VERSION }}
outputs: type=docker,dest=runtime-${{ matrix.arch }}.tar

- name: Setup the Crossplane CLI
run: "curl -sL https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh | sh"

- name: Build Package
run: ./crossplane xpkg build --package-file=${{ matrix.arch }}.xpkg --package-root=package/ --embed-runtime-image-tarball=runtime-${{ matrix.arch }}.tar

- name: Upload Single-Platform Package
uses: actions/upload-artifact@v4
with:
Expand Down Expand Up @@ -147,9 +150,9 @@ jobs:
uses: docker/login-action@v3
if: env.XPKG_ACCESS_ID != ''
with:
registry: xpkg.upbound.io
username: ${{ secrets.XPKG_ACCESS_ID }}
password: ${{ secrets.XPKG_TOKEN }}
registry: ghcr.io
username: ${{ env.XPKG_ACCESS_ID }}
password: ${{ secrets.GITHUB_TOKEN }}

# If a version wasn't explicitly passed as a workflow_dispatch input we
# default to version v0.0.0-<git-commit-date>-<git-short-sha>, for example
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@

# Go workspace file
go.work
tmp
27 changes: 17 additions & 10 deletions example/composition.yaml
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: function-template-go
name: logging-composition
spec:
compositeTypeRef:
apiVersion: example.crossplane.io/v1
kind: XR
mode: Pipeline
resources:
- name: Logging
base:
apiVersion: logging.banzaicloud.io/v1beta1
kind: Logging
spec:
controlNamespace: ""
fluentd:
disablePvc: true
compositeTypeRef:
apiVersion: caas.telekom.de/v1alpha1
kind: XLogging
pipeline:
- step: run-the-template
- step: get-labels
functionRef:
name: function-template-go
input:
apiVersion: template.fn.crossplane.io/v1beta1
kind: Input
example: "Hello world"
name: logging-labeler
input: {}

4 changes: 2 additions & 2 deletions example/functions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
apiVersion: pkg.crossplane.io/v1beta1
kind: Function
metadata:
name: function-template-go
name: logging-labeler
annotations:
# This tells crossplane beta render to connect to the function locally.
render.crossplane.io/runtime: Development
spec:
# This is ignored when using the Development runtime.
package: function-template-go
package: logging-labeler
5 changes: 3 additions & 2 deletions example/xr.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Replace this with your XR!
apiVersion: example.crossplane.io/v1
kind: XR
apiVersion: caas.telekom.de/v1alpha1
kind: Logging
metadata:
name: example-xr
namespace: microservices
spec: {}
73 changes: 61 additions & 12 deletions fn.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,85 @@ import (

"github.com/crossplane/crossplane-runtime/pkg/errors"
"github.com/crossplane/crossplane-runtime/pkg/logging"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"

fnv1beta1 "github.com/crossplane/function-sdk-go/proto/v1beta1"
"github.com/crossplane/function-sdk-go/request"
"github.com/crossplane/function-sdk-go/resource"
"github.com/crossplane/function-sdk-go/resource/composed"
"github.com/crossplane/function-sdk-go/response"

"github.com/crossplane/function-template-go/input/v1beta1"
inputv1beta1 "github.com/crossplane/logging-labeler/input/v1beta1"
"github.com/kube-logging/logging-operator/pkg/sdk/logging/api/v1beta1"
)

// Function returns whatever response you ask it to.
type Function struct {
fnv1beta1.UnimplementedFunctionRunnerServiceServer

cs kubernetes.Interface
log logging.Logger
}

// RunFunction runs the Function.
func (f *Function) RunFunction(_ context.Context, req *fnv1beta1.RunFunctionRequest) (*fnv1beta1.RunFunctionResponse, error) {
f.log.Info("Running function", "tag", req.GetMeta().GetTag())

func (f *Function) RunFunction(ctx context.Context, req *fnv1beta1.RunFunctionRequest) (*fnv1beta1.RunFunctionResponse, error) {
rsp := response.To(req, response.DefaultTTL)

in := &v1beta1.Input{}
in := &inputv1beta1.Input{}
if err := request.GetInput(req, in); err != nil {
response.Fatal(rsp, errors.Wrapf(err, "cannot get Function input from %T", req))
response.Fatal(rsp, errors.Wrapf(err, "cannot get input from %T", req))
return rsp, nil
}

xr, err := request.GetObservedCompositeResource(req)
if err != nil {
response.Fatal(rsp, errors.Wrapf(err, "cannot get observed composed resources"))
return rsp, nil
}

desired, err := request.GetDesiredComposedResources(req)
if err != nil {
response.Fatal(rsp, errors.Wrapf(err, "cannot get desired composed resources"))
return rsp, nil
}

if err := v1beta1.AddToScheme(composed.Scheme); err != nil {
response.Fatal(rsp, errors.Wrapf(err, "cannot add to scheme"))
return rsp, nil
}

ns := xr.Resource.GetClaimReference().Namespace

targetns, err := f.cs.CoreV1().Namespaces().Get(ctx, ns, metav1.GetOptions{})
if err != nil {
response.Fatal(rsp, errors.Wrapf(err, "cannot get namespace %s", ns))
return rsp, nil
}

projectid, ok := targetns.GetLabels()[in.NamespaceLabel]
if !ok {
response.Fatal(rsp, errors.New("cannot get project id"))
return rsp, nil
}

l := &v1beta1.Logging{}
l.Spec.ControlNamespace = ns
l.Spec.WatchNamespaceSelector = &metav1.LabelSelector{}
l.Spec.WatchNamespaceSelector.MatchLabels = map[string]string{in.NamespaceLabel: projectid}
l.Spec.FluentdSpec = &v1beta1.FluentdSpec{}

cd, err := composed.From(l)
if err != nil {
response.Fatal(rsp, errors.Wrapf(err, "cannot convert %T to %T", l, &composed.Unstructured{}))
return rsp, nil
}

// TODO: Add your Function logic here!
response.Normalf(rsp, "I was run with input %q!", in.Example)
f.log.Info("I was run!", "input", in.Example)
desired["logging"] = &resource.DesiredComposed{Resource: cd}

f.log.Info("Desired composed resources", "desired", desired)

if err := response.SetDesiredComposedResources(rsp, desired); err != nil {
response.Fatal(rsp, errors.Wrapf(err, "cannot set desired composed resources"))
return rsp, nil
}

return rsp, nil
}
Loading

0 comments on commit 042a302

Please sign in to comment.