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

Added Kubernetes API types #542

Merged
merged 2 commits into from
Nov 24, 2021
Merged

Conversation

micahhausler
Copy link
Contributor

Signed-off-by: Micah Hausler [email protected]

Description

This is an initial commit to support the Kubernetes resource model from tinkerbell/proposals#46. I'm starting out with just the API schema, and there are a lot of fields on the Hardware type that I do not understand. I'd like to get some consensus on the API shape and fields, but this is iterative, and structures can be modified in later PRs.

After this is merged, I'll have additional follow on PRs for

  • Tink Controller
  • Validating webhook
  • DB/GRPC server changes behind a feature flag
  • Migration tooling from Postgres

How Has This Been Tested?

  • Added CI test for CRD generation

How are existing users impacted? What migration steps/scripts do we need?

No user change required at this point

Checklist:

I have:

  • updated the documentation and/or roadmap (if required)
  • added unit or e2e tests
  • provided instructions on how to upgrade

Copy link
Contributor Author

@micahhausler micahhausler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left reviewer comments

)

replace github.com/stormcat24/protodep => github.com/ackintosh/protodep v0.0.0-20200728152107-abf8eb579d6c
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mmlb You touched this last, but I could not get Tink to build without removing this. Is this OK?

@@ -0,0 +1,36 @@
GO_INSTALL = ./scripts/go_install.sh
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dropped the K8s Make changes in its own file, does anyone have a place they'd rather see this?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like that you compartmentalize this. 📦

//nolint:gochecknoglobals
var (
// GroupVersion is group version used to register these objects.
GroupVersion = schema.GroupVersion{Group: "tinkerbell.org", Version: "v1alpha1"}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@detiber I copied the CAPT API group, so this can't be installed side-by-side with CAPT. Is that OK for now? I think CAPT could migrate to these types once API functionality is in place

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@micahhausler IMO this is fine, because I would image CAPT to be part of the kube-native Tinkerbell.

}

// HardwareSpec defines the desired state of Hardware.
type HardwareSpec struct {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I largely copied the Spec from the existing Hardware Protobuf and injected the Packet Metadata proto structure into the Metadata field.

The Metadata structure seemed necessary to get Boots to play nice. It seems to duplicate some of the top level hardware spec fields. Is this just a carryover from internal Packet/Equanix code? How much of that do we really need? If the easiest answer is just "include it all for now and refactor later" I'm fine with that, but I'd appreciate someone weighing in

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@micahhausler I like that you kept it rather open and my humble opinion is that for this PR it is fine. Later we might want to look at how to enforce hardware data that is compatible with rootio.

One possible point of friction that I see between Kubernetes and Tinkerbell is the overlap between the word metadata. Maybe it could be sensible to consider the entire hardware definition metadata and thus adjust the schema described here in our Tinkerbell docs in the future?

But I think I am sidetracking big time. I can set up a proposal if anyone seconds this.

// +kubebuilder:storageversion

// Workflow is the Schema for the Workflows API.
type WorkflowData struct {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type is meant to replicate the behavior of the WorkflowData RPCs.

TemplateRef string `json:"templateRef,omitempty"`

// A mapping of template devices to hadware mac addresses
HardwareMap map[string]string `json:"hardwareMap,omitempty"`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same gyration about naming here. The type is kind of implied, any strong opinions on the current name vs hardware?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am thinking that maybe HardwareBinding is more semantic? map tickles me in that it is very close to Go lingo.

// WorkflowStatus defines the observed state of Workflow.
type WorkflowStatus struct {
// State is the state of the workflow in Tinkerbell.
State string `json:"state,omitempty"`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can add a WorkflowState type here with values for the State Protobuf enum later.

State string `json:"state,omitempty"`

// Data is the populated Workflow Data in Tinkerbell.
Data string `json:"data,omitempty"`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we drop this? Its just the evaluated, interpolated template with the hardware mappings. This is all encoded and strongly typed in the Tasks Task[] field below

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would second the idea of dropping this as this feels like noise to me.

GlobalTimeout int64 `json:"globalTimeout,omitempty"`

// Tasks are the tasks to be completed
Tasks []Task `json:"tasks,omitempty"`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found it was easiest to translate the interpolated template steps by just using the same structure of Tasks[].Actions[]. This is a little bit of a departure from the data model used in Postgres, but since we're normalizing everything on the Workflow, this structure was the easiest to reason about for rewriting the worker APIs.

Volumes []string `json:"volumes,omitempty"`
Pid string `json:"pid,omitempty"`
Environment map[string]string `json:"environment,omitempty"`
Status string `json:"status,omitempty"`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This field could also be transitioned to the WorkflowStatus enums

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand the concept of actions correctly, I'd second your suggestion of moving it into the WorkflowStatus. The risk I see is otherwise that spec (desired state) and status (current state) get mixed, which I feel goes against Kubernetes' declarative nature.

@thebsdbox
Copy link
Contributor

Woah! This looks excellent!

@codecov
Copy link

codecov bot commented Oct 4, 2021

Codecov Report

Merging #542 (3121ba6) into main (187a3c7) will not change coverage.
The diff coverage is n/a.

❗ Current head 3121ba6 differs from pull request most recent head fbfa9b3. Consider uploading reports for the commit fbfa9b3 to get more accurate results
Impacted file tree graph

@@           Coverage Diff           @@
##             main     #542   +/-   ##
=======================================
  Coverage   34.76%   34.76%           
=======================================
  Files          44       44           
  Lines        3348     3348           
=======================================
  Hits         1164     1164           
  Misses       2085     2085           
  Partials       99       99           

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 187a3c7...fbfa9b3. Read the comment docs.

@micahhausler micahhausler force-pushed the k8s-api branch 2 times, most recently from b30ec79 to 77314c4 Compare October 5, 2021 13:49
@jacobweinstock
Copy link
Member

Hey @tstromberg and @detiber, would either of you be able to help with this PR? It's big and I wanted to make sure it got some good eyes on it.

}

// HardwareSpec defines the desired state of Hardware.
type HardwareSpec struct {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@micahhausler I like that you kept it rather open and my humble opinion is that for this PR it is fine. Later we might want to look at how to enforce hardware data that is compatible with rootio.

One possible point of friction that I see between Kubernetes and Tinkerbell is the overlap between the word metadata. Maybe it could be sensible to consider the entire hardware definition metadata and thus adjust the schema described here in our Tinkerbell docs in the future?

But I think I am sidetracking big time. I can set up a proposal if anyone seconds this.

//nolint:gochecknoglobals
var (
// GroupVersion is group version used to register these objects.
GroupVersion = schema.GroupVersion{Group: "tinkerbell.org", Version: "v1alpha1"}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@micahhausler IMO this is fine, because I would image CAPT to be part of the kube-native Tinkerbell.

TemplateRef string `json:"templateRef,omitempty"`

// A mapping of template devices to hadware mac addresses
HardwareMap map[string]string `json:"hardwareMap,omitempty"`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am thinking that maybe HardwareBinding is more semantic? map tickles me in that it is very close to Go lingo.

State string `json:"state,omitempty"`

// Data is the populated Workflow Data in Tinkerbell.
Data string `json:"data,omitempty"`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would second the idea of dropping this as this feels like noise to me.

Volumes []string `json:"volumes,omitempty"`
Pid string `json:"pid,omitempty"`
Environment map[string]string `json:"environment,omitempty"`
Status string `json:"status,omitempty"`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand the concept of actions correctly, I'd second your suggestion of moving it into the WorkflowStatus. The risk I see is otherwise that spec (desired state) and status (current state) get mixed, which I feel goes against Kubernetes' declarative nature.

@@ -0,0 +1,36 @@
GO_INSTALL = ./scripts/go_install.sh

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like that you compartmentalize this. 📦

jacobweinstock
jacobweinstock previously approved these changes Nov 2, 2021
@@ -26,6 +26,8 @@ jobs:
uses: actions/setup-go@v2
with:
go-version: "1.14.6"
- name: Generate
run: make generate
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the idea there that we just validate that the generate works? Will we need this to run below so that this is available in crosscompile? maybe I just don't understand how github actions work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we want to make sure that our generation tooling works, and the checked-in generated code is up-to-date. It runs before ci-checks.md, so that any differences in generated code are marked as a CI failure.

@jacobweinstock
Copy link
Member

Approved on my end. Looks like there are just a few conflicts to address.

Signed-off-by: Micah Hausler <[email protected]>
Signed-off-by: Micah Hausler <[email protected]>
@micahhausler
Copy link
Contributor Author

@jacobweinstock Addressed comments, and fixed conflicts.

@thebsdbox
Copy link
Contributor

Are we good to pull the trigger on this one?

@jacobweinstock jacobweinstock merged commit 4900279 into tinkerbell:main Nov 24, 2021
@micahhausler micahhausler mentioned this pull request Dec 2, 2021
3 tasks
mergify bot added a commit that referenced this pull request Jan 19, 2022
Signed-off-by: Micah Hausler <[email protected]>

## Description

This PR adds a new Kubernetes controller binary for the types merged in #542.

* Adds a new `cmd/tink-controller` package with a Dockerfile and a `main.go`
* Removes the `status.data` field  on Workflows. This was just a string of the interpolated template, and was redundant given the strongly typed template actions already on the `.status` of Workflows.
* Adds tests to the methods on the workflow API structure 
* Adds a new `pkg/controllers` package. This introduces a `Manager` abstraction that wraps `sigs.k8s.io/controller-runtime`'s [`Reconciler`](https://pkg.go.dev/sigs.k8s.io/[email protected]/pkg/reconcile?utm_source=gopls#Reconciler) type
  * Controllers for individual types (workflows, templates, hardware) will reside in individual sub-packages
  * Controllers patch incoming objects even in the event of an error: this is intentional as a controller in the [Kubernetes Resource Model](https://github.com/kubernetes/design-proposals-archive/blob/main/architecture/resource-management.md) attempts to converge on desired state
* Adds a new `pkg/conversion` package for converting protobuf types to Kubernetes CRD types and vice versa
* Adds an internal `pkg/internal/tests` package with internal testing utilities. 
  * The first utility added is a `FrozenTime` interface with Before/After connivence methods for `time.Time`, as well as protobuf and K8s metav1 package time formats. 


## How Has This Been Tested?

* I added unit tests for nearly all new branching logic
* I added a CI target for building the tink-controller 

## How are existing users impacted? What migration steps/scripts do we need?

There is no impact to existing users. Nothing form this change is called in any existing code path.

## Checklist:

I have:

- [ ] ~~updated the documentation and/or roadmap (if required)~~
- [x] added unit or e2e tests
- [ ] ~~provided instructions on how to upgrade~~
@displague displague added this to the 0.7.0 milestone Aug 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants