mayadata-io / mayadata-io/d-operators

design resource mapped by versions & feature flags

Open
#27 3 comments 1 reaction 1 assignee View on GitHub

@AmitKumarDas is already working on this.

Since Apr 6, 2020.

dao design feature flag metac use case version
Dominant language
Go
Stars
10
Forks
6
PR merge metrics
No merged PRs in 30d

Description

In this issue I propose a design to build desired k8s resources that can be selected by their versions &/or feature flags.

NOTE: Let us take the case of k8s resource with kind Foo
NOTE: In real world, Foo can be replaced by k8s resource e.g. Deployment, ClusterRole, etc

// the folder structure might look like this
projectroot
|_ controller
  |_ my-cool-controller/
    |_ reconciler.go
    |_ reconciler_test.go
|_ common
  |_ selector/
    |_ selector.go
|_ resources
   |_ foo
     |_ foo.go
     |_ foo_test.go
|_ types
  |_ foo.go
  |_ foo_test.go
// in common/selector/selector.go
type TagOperator string

const (
  TagOperatorOR TagOperator = "OR"

  TagOperatorAND TagOperator = "AND"
)

type Tag struct {
  Keys []string
  Operator TagOperator
}

type Selection struct {
  Version string
  FeatureFlag string
  Tag Tag
}

type Terms struct {
  Versions map[string]bool
  FeatureFlags map[string]bool
  Tags map[string]bool
}

func (s Selection) IsMatch(terms Terms) bool {
  // ...
}
// in resources/foo/foo.go

import (
  "project/common/selector"
)

type Config struct {
  Selector selector.Selection
  DesiredName string
  DesiredNamespace string
  DesiredLabels map[string]string
  DesiredAnnotations map[string]string
}

type Foo struct {
  selector selector.Selection
}

func New(config Config) *Foo {
  return &Foo {selector: config.Selector}
}

func (f *Foo) IsSelectionMatch(terms selector.Terms) bool {
 return f.selector.IsMatch(terms)
}

func (f *Foo) GetDesired() (*unstructured.Unstructured, error) {
  fns := []func() (*unstructured.Unstructured, bool) {
    f.getDesiredTypeA,
  }
  for _, fn := range fns {
    desired, ok := fn()
    if ok {
      return desired, nil
    }
  }
  return nil, errors.Errorf("Can't find desired Foo with conf %+v", f.conf)
}

func (f *Foo) getDesiredTypeA() (*unstructured.Unstructured, bool) {
  supportedVersions := map[string]bool{
    "1.9", true,
  }
  supportedFeatureFlags := map[string]bool{
    "alpha": true,
    "beta": true,
    "production": true,
  }
  supportedTags := map[string]bool {
    "linux": true,
    "ubuntu-18.04": true,
  }
  terms := selector.Terms{
    Versions: supportedVersions,
    FeatureFlags: supportedFlags,
    Tags: supportedTags,
  }
  if !f.IsSelectionMatch(terms) {
    return nil, false
  }
  return &unstructured.Unstructured{
    Object: map[string]interface{}{
      "kind": Foo,
      "apiVersion": "example.io/v1alpha1",
    },
  }, nil
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.