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

Upgrade template out from extension of Definition Spec #976

Closed
wonderflow opened this issue Feb 1, 2021 · 8 comments · Fixed by #1014 or #1117
Closed

Upgrade template out from extension of Definition Spec #976

wonderflow opened this issue Feb 1, 2021 · 8 comments · Fixed by #1014 or #1117
Assignees
Milestone

Comments

@wonderflow
Copy link
Collaborator

wonderflow commented Feb 1, 2021

Before:

apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
metadata:
  name: worker
  annotations:
    definition.oam.dev/description: "Long-running scalable backend worker without network endpoint"
spec:
  definitionRef:
    name: deployments.apps
  extension:
    healthPolicy: |
        healthy: isHealth: output.status.replicas == output.status.readyReplicas
    customStatus: |
        output: "type: "+ context.outputs.service.spec.type +",\t clusterIP:"+ context.outputs.service.spec.clusterIP+",\t ports:"+ context.outputs.service.spec.ports[0].port+"/"+context.outputs.service.spec.ports[0].protocal+",\t domain"+context.outputs.ingress.rules[0].host
    template: |
      output: {
        apiVersion: "apps/v1"
        kind:       "Deployment"
        spec: {
          selector: matchLabels: {
            "app.oam.dev/component": context.name
          }
          template: {
            metadata: labels: {
              "app.oam.dev/component": context.name
            }
            spec: {
              containers: [{
                name:  context.name
                image: parameter.image
                if parameter["cmd"] != _|_ {
                  command: parameter.cmd
                }
              }]
            }
          }
          selector:
            matchLabels:
              "app.oam.dev/component": context.name
        }
      }
      parameter: {
        // +usage=Which image would you like to use for your service
        // +short=i
        image: string
        cmd?: [...string]
      }

After:

apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
metadata:
  name: worker
  annotations:
    definition.oam.dev/description: "Long-running scalable backend worker without network endpoint"
spec:
  definitionRef:
    name: deployments.apps
  template: |
      output: {
        apiVersion: "apps/v1"
        kind:       "Deployment"
        spec: {
          selector: matchLabels: {
            "app.oam.dev/component": context.name
          }
          template: {
            metadata: labels: {
              "app.oam.dev/component": context.name
            }
            spec: {
              containers: [{
                name:  context.name
                image: parameter.image
                if parameter["cmd"] != _|_ {
                  command: parameter.cmd
                }
              }]
            }
          }
          selector:
            matchLabels:
              "app.oam.dev/component": context.name
        }
      }
      parameter: {
        // +usage=Which image would you like to use for your service
        // +short=i
        image: string
        cmd?: [...string]
      }
  status:
    healthPolicy: |
        healthy: isHealth: output.status.replicas == output.status.readyReplicas
    message: |
        output: "type: "+ context.outputs.service.spec.type +",\t clusterIP:"+ context.outputs.service.spec.clusterIP+",\t ports:"+ context.outputs.service.spec.ports[0].port+"/"+context.outputs.service.spec.ports[0].protocal+",\t domain"+context.outputs.ingress.rules[0].host
    
@resouer
Copy link
Collaborator

resouer commented Feb 10, 2021

@wonderflow still have several issues, for example, there will be more module types soon, your design should be extensible enough to avoid breaking change in the future.

One option:

apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
metadata:
  name: worker
  annotations:
    definition.oam.dev/description: "Long-running scalable backend worker without network endpoint"
spec:
  definitionRef: # this also means you can directly use CRD as a "module"
    apiVersion: apps/v1
    kind: Deployment
  module:
    cue:
      template: |
        output: {
          apiVersion: "apps/v1"
          kind:       "Deployment"
          spec: {
            selector: matchLabels: {
              "app.oam.dev/component": context.name
            }
            template: {
              metadata: labels: {
                "app.oam.dev/component": context.name
              }
              spec: {
                containers: [{
                  name:  context.name
                  image: parameter.image
                  if parameter["cmd"] != _|_ {
                    command: parameter.cmd
                  }
                }]
              }
            }
            selector:
              matchLabels:
                "app.oam.dev/component": context.name
          }
        }
        parameter: {
          // +usage=Which image would you like to use for your service
          // +short=i
          image: string
          cmd?: [...string]
        }
    helm:
      # helm specific fields
    terraform:
      # terraform hcl specific fields
    json-schema:
      # plain json-schema
    raw-resource:
      # old school cr template + parameter

@wonderflow
Copy link
Collaborator Author

wonderflow commented Feb 14, 2021

@resouer helm , terraform and json-schema can have new field with template, for example:

apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
metadata:
  name: worker
  annotations:
    definition.oam.dev/description: "Long-running scalable backend worker without network endpoint"
spec:
  definitionRef: # this also means you can directly use CRD as a "module"
    apiVersion: apps/v1
    kind: Deployment
  templateType: cue
  template: |
        output: {
          apiVersion: "apps/v1"
          kind:       "Deployment"
          spec: {
            selector: matchLabels: {
              "app.oam.dev/component": context.name
            }
            template: {
              metadata: labels: {
                "app.oam.dev/component": context.name
              }
              spec: {
                containers: [{
                  name:  context.name
                  image: parameter.image
                  if parameter["cmd"] != _|_ {
                    command: parameter.cmd
                  }
                }]
              }
            }
            selector:
              matchLabels:
                "app.oam.dev/component": context.name
          }
        }
        parameter: {
          // +usage=Which image would you like to use for your service
          // +short=i
          image: string
          cmd?: [...string]
        }
  helm:
      # helm specific fields
  terraform:
      # terraform hcl specific fields
  json-schema:
      # plain json-schema

@resouer
Copy link
Collaborator

resouer commented Feb 14, 2021

@wonderflow it doesn't make sense to me ... what is the type of template field then?

Also, cue, helm chart, terraform etc are modules rather than templates. It's a good timing to fix this name.

@wonderflow
Copy link
Collaborator Author

wonderflow commented Feb 19, 2021

Split current WorkloadDefinition into two parts:

apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
metadata:
  name: deployments.apps
  annotations:
    definition.oam.dev/description: "Long-running scalable backend worker without network endpoint"
spec:
  definitionRef:
    apiVersion: apps/v1
    kind: Deployment

and

apiVersion: core.oam.dev/v1alpha2
kind: ComponentDefinition
metadata:
  name: worker
  annotations:
    definition.oam.dev/description: "Long-running scalable backend worker without network endpoint"
spec:
  workloadType: deployments.apps
  module:
    cue:
      template: |
        output: {
          apiVersion: "apps/v1"
          kind:       "Deployment"
          spec: {
            selector: matchLabels: {
              "app.oam.dev/component": context.name
            }
            template: {
              metadata: labels: {
                "app.oam.dev/component": context.name
              }
              spec: {
                containers: [{
                  name:  context.name
                  image: parameter.image
                  if parameter["cmd"] != _|_ {
                    command: parameter.cmd
                  }
                }]
              }
            }
            selector:
              matchLabels:
                "app.oam.dev/component": context.name
          }
        }
        parameter: {
          // +usage=Which image would you like to use for your service
          // +short=i
          image: string
          cmd?: [...string]
        }
    helm:
      # helm specific fields
    terraform:
      # terraform hcl specific fields
    json-schema:
      # plain json-schema
    raw-resource:
      # old school cr template + parameter

@resouer
Copy link
Collaborator

resouer commented Feb 19, 2021

@wonderflow, I am in favor of having ComponentDefinition. But we also need to make sure users (i.e. component providers) author ComponentDefinition only, otherwise two objects to define one component is too verbose to me.

We can generate WorkloadDefinition from ComponentDefinition. Considering workload template also need revisioning (see: #1064), we can actually do 1: N mapping (mutable -> immutable mapping).

For example:

# mutable
apiVersion: core.oam.dev/v1alpha2
kind: ComponentDefinition
metadata:
  name: worker
  annotations:
    definition.oam.dev/description: "Long-running scalable backend worker without network endpoint"
spec:
  definitionRef:
    apiVersion: apps/v1
    kind: Deployment
  module:
    cue:
      # template data
  # other per ComponentDefinition fields ...
status:
  currentWorkloadDefRevision: deployments.apps

It will generate immutable WorkloadDefinition, note that in implementation we should ensure the latest workload def always have a fixed name (e.g. deployments.apps), this is the key for workload type discovery. It's totally OK to rename WorkloadDefinition objects which only carry discovery information.

# latest immutable workload type object
apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
metadata:
  name: deployments.apps # this name is generated from ComponentDefinition.definitionRef
spec:
  definitionRef:
    apiVersion: apps/v1
    kind: Deployment
  module:
    cue:
      # template data of latest revision
---
# history immutable workload type object
apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
metadata:
  name: deployments.apps-v1-{timestamp} # this name is generated from ComponentDefinition.definitionRef
spec:
  definitionRef:
    apiVersion: apps/v1
    kind: Deployment
  module:
    cue:
      # template data of {timestamp} revision

/cc @ryanzhang-oss, please review if this solves your request for #1064

Similar pattern: https://github.com/mattmoor/boo-maps

@wonderflow
Copy link
Collaborator Author

@wonderflow, I am in favor of having ComponentDefinition. But we also need to make sure users (i.e. component providers) author ComponentDefinition only, otherwise two objects to define one component is too verbose to me.

We can generate WorkloadDefinition from ComponentDefinition. Considering workload template also need revisioning (see: #1064), we can actually do 1: N mapping (mutable -> immutable mapping).

For example:

# mutable object
apiVersion: core.oam.dev/v1alpha2
kind: ComponentDefinition
metadata:
  name: worker
  annotations:
    definition.oam.dev/description: "Long-running scalable backend worker without network endpoint"
spec:
  definitionRef:
    apiVersion: apps/v1
    kind: Deployment
  module:
    cue:
      # template data
  # other per ComponentDefinition fields ...

---
# immutable objects
apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
metadata:
  name: deployments.apps-v1-{revision number} # this name is generated from ComponentDefinition.definitionRef
spec:
  definitionRef:
    apiVersion: apps/v1
    kind: Deployment
  module:
    cue:
      # template data of {revision number}

/cc @ryanzhang-oss, please review if this solves your request for #1064

Similar pattern: https://github.com/mattmoor/boo-maps

I love this idea

@resouer
Copy link
Collaborator

resouer commented Feb 21, 2021

@wonderflow I updated the design a bit, because I think in implementation we should ensure the latest workload def always have a fixed name (e.g. deployments.apps), this is the key for workload type discovery.

@wonderflow
Copy link
Collaborator Author

will align with oam-dev/spec#443

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants