Skip to content

Commit

Permalink
feat: add support for multiple resource markers (#62)
Browse files Browse the repository at this point in the history
* feat: add support for multiple resource markers

Signed-off-by: Rich Lander <lander2k2@protonmail.com>

* docs: fix typo in resource marker docs

Signed-off-by: Rich Lander <lander2k2@protonmail.com>

* fix: remove unecessary if statement from definition template

Signed-off-by: Rich Lander <lander2k2@protonmail.com>

Signed-off-by: Rich Lander <lander2k2@protonmail.com>
  • Loading branch information
lander2k2 committed Dec 9, 2022
1 parent 7d19f84 commit 2d12b9c
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 23 deletions.
68 changes: 68 additions & 0 deletions docs/markers.md
Original file line number Diff line number Diff line change
Expand Up @@ -458,3 +458,71 @@ spec:
provider: "azure"
```

### Stacking Resource Markers

You can include multiple resource markers on a particular resource. For example:
```yaml
---
# +operator-builder:resource:field=nginx.include,value=true,include
# +operator-builder:resource:field=nginx.installType,value="deployment",include
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-ingress
...
```

The purpose of the first marker is to include *all* nginx ingress contoller
resources when `spec.nginx.include: true`. The second gives users a choice
to install nginx ingress controller as a deployment or daemonset. When
`spec.nginx.installType: deployment` the deployment resource is included.
Therefore the custom resource will need to look as follows for this deployment
resource to be created:

```yaml
apiVersion: platform.addons.nukleros.io/v1alpha1
kind: IngressComponent
metadata:
name: ingresscomponent-sample
spec:
nginx:
installType: "deployment" # if not "deployment" deployment resource excluded
include: true # if false, no nginx resources are created
image: "nginx/nginx-ingress"
version: "2.3.0"
replicas: 2
```

The resulting source code looks as follows. If either if-statement is evaluated
as true, the function will return without any object - hence the deployment will
not be included.

```go
// CreateDeploymentNamespaceNginxIngress creates the Deployment resource with name nginx-ingress.
func CreateDeploymentNamespaceNginxIngress(
parent *platformv1alpha1.IngressComponent,
collection *setupv1alpha1.SupportServices,
reconciler workload.Reconciler,
req *workload.Request,
) ([]client.Object, error) {
if parent.Spec.Nginx.Include != true {
return []client.Object{}, nil
}
if parent.Spec.Nginx.InstallType != "deployment" {
return []client.Object{}, nil
}
var resourceObj = &unstructured.Unstructured{
Object: map[string]interface{}{
// +operator-builder:resource:field=nginx.include,value=true,include
// +operator-builder:resource:field=nginx.installType,value="deployment",include
"apiVersion": "apps/v1",
"kind": "Deployment",
...
}
return mutate.MutateDeploymentNamespaceNginxIngress(resourceObj, parent, collection, reconciler, req)
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ func {{ .CreateFuncName }} (
req *workload.Request,
) ([]client.Object, error) {
{{- if ne .IncludeCode "" }}{{ .IncludeCode }}{{ end }}
{{ range .IncludeCode }}
{{ . }}
{{ end }}
{{- .SourceCode }}
Expand Down
36 changes: 14 additions & 22 deletions internal/workload/v1/manifests/child_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type ChildResource struct {
Kind string
StaticContent string
SourceCode string
IncludeCode string
IncludeCode []string
MutateFile string
UseStrConv bool
RBAC *rbac.Rules
Expand Down Expand Up @@ -77,33 +77,25 @@ func (resource *ChildResource) ProcessResourceMarkers(markerCollection *markers.
return fmt.Errorf("%w; %s for child resource %s", err, ErrChildResourceResourceMarkerInspect, resource)
}

// ensure we have the expected number of resource markers
// - 0: return immediately as resource markers are not required
// - 1: continue processing normally
// - 2: return an error notifying the user that we only expect 1
// resource marker
// return immediately if no resource markers are present
if len(markerResults) == 0 {
return nil
}

//nolint: godox // depends on https://github.com/vmware-tanzu-labs/operator-builder/issues/271
// TODO: we need to ensure only one marker is found and return an error if we find more than one.
// this becomes difficult as the results are returned as yaml nodes. for now, we just focus on the
// first result and all others are ignored but we should notify the user.
result := markerResults[0]
// process the markers
for _, m := range markerResults {
marker, ok := m.Object.(markers.ResourceMarker)
if !ok {
return ErrChildResourceResourceMarkerProcess
}

// process the marker
marker, ok := result.Object.(markers.ResourceMarker)
if !ok {
return ErrChildResourceResourceMarkerProcess
}

if err := marker.Process(markerCollection); err != nil {
return fmt.Errorf("%w; %s for child resource %s", err, ErrChildResourceResourceMarkerProcess, resource)
}
if err := marker.Process(markerCollection); err != nil {
return fmt.Errorf("%w; %s for child resource %s", err, ErrChildResourceResourceMarkerProcess, resource)
}

if marker.GetIncludeCode() != "" {
resource.IncludeCode = marker.GetIncludeCode()
if marker.GetIncludeCode() != "" {
resource.IncludeCode = append(resource.IncludeCode, marker.GetIncludeCode())
}
}

return nil
Expand Down

0 comments on commit 2d12b9c

Please sign in to comment.