Skip to content

add endpoints for crud operations & update hardware data model #64

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

Merged
merged 31 commits into from
Jun 22, 2020

Conversation

kqdeng
Copy link
Contributor

@kqdeng kqdeng commented Apr 14, 2020

Changes:

  • Added endpoints for the following operations (unofficial api):
    • tink hardware push/all/mac/ip/id
    • tink template create/get/list/delete
    • tink workflow create/get/list/delete/state/events
  • Added basic auth to above endpoints
    • Added two new envvars TINK_AUTH_USERNAME and TINK_AUTH_PASSWORD to set basic auth username and password
  • Changed the data field in WorkflowTemplate to be a string instead of bytes (in template proto)
  • Updated Hardware struct to new data model
  • Updated docker-compose.yml to reflect additions of new envvars across all three prs

TODO:

  • update setup.sh and docker-compose.yml to account for new envvars
    • setup.sh
    • docker-compose.yml

Related PRs:
boots: tinkerbell/smee#27
hegel: tinkerbell/hegel#13

@gauravgahlot
Copy link
Contributor

@kdeng3849 Can you please rebase the branch?

@kqdeng kqdeng force-pushed the add-endpoints branch 2 times, most recently from 2f9e9fd to 2630172 Compare April 27, 2020 15:42
@@ -34,7 +34,13 @@ var pushCmd = &cobra.Command{
},
Run: func(cmd *cobra.Command, args []string) {
for _, j := range args {
if _, err := client.HardwareClient.Push(context.Background(), &hardware.PushRequest{Data: j}); err != nil {
fmt.Println(j)
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we really need this?

@kqdeng kqdeng force-pushed the add-endpoints branch 2 times, most recently from e3c814a to b4ec49c Compare April 27, 2020 16:33
@@ -62,7 +62,7 @@ func readTemplateData() []byte {
}

func createTemplate(c *cobra.Command, args []string) {
req := template.WorkflowTemplate{Name: templateName, Data: readTemplateData()}
req := template.WorkflowTemplate{Name: templateName, Data: string(readTemplateData())}
Copy link
Contributor

Choose a reason for hiding this comment

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

Since the returned value of readTemplateData is converted to string in most of the places, I think it would make sense to change the return type to string from []byte.

@alexellis
Copy link
Contributor

Looks like another rebase is required on this PR @kdeng3849

@kqdeng kqdeng force-pushed the add-endpoints branch 3 times, most recently from 9fb0d30 to 11965b0 Compare May 27, 2020 15:52
@nathangoulding nathangoulding requested review from mikemrm and mmlb May 29, 2020 17:42
@kqdeng kqdeng changed the title added endpoints for crud operations add endpoints for crud operations & update hardware data model Jun 2, 2020
@@ -28,11 +29,15 @@ var ipCmd = &cobra.Command{
},
Run: func(cmd *cobra.Command, args []string) {
for _, ip := range args {
hw, err := client.HardwareClient.ByIP(context.Background(), &hardware.GetRequest{IP: ip})
hw, err := client.HardwareClient.ByIP(context.Background(), &hardware.GetRequest{Ip: ip})
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a way for the generated code to influence the name for the generated struct fields? Looking at Ip -> IP and Mac -> MAC and maybe others?

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 didn't really look into it too much since it seemed to work fine with boots without any issue. Is there a reason/necessity for the names to be capitalized? I could change them back to uppercase in the proto if needed

Copy link
Contributor

Choose a reason for hiding this comment

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

its a code nit, but acronyms should be in all caps. It also matches the types in the stdlib so not being an oddball would be good.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

okay, I'll change it back then

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 remember why I decided on all lowercase, it's because there are problems when the message name is the same as the field name. For example:

message RAID {
	string name = 1;
	string level = 2;
	repeated string devices = 3;
	int64 spare = 4;
}

repeated RAID RAID = 5;

this is giving me the error:

Generating hardware.pb.go...
hardware/hardware.proto:164:41: "RAID" is already defined in "github.com.tinkerbell.tink.protos.hardware.Hardware.Metadata.Instance.Storage".
hardware/hardware.proto:175:42: "RAID" is not defined.

So I decided on all lowercase for the field name (which is also the convention for protobuf).
I could still rename the message name to something like "Raid", so I guess it all boils down to which convention to follow (go's or protobuf's). Which one should I go with?

Copy link
Contributor

Choose a reason for hiding this comment

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

ah ok, sigh. lets go with protobuf then. I'm curious is there an equivalent of json:"SomeKeyName" metadata we can add so we can both?

Copy link
Contributor

Choose a reason for hiding this comment

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

looks like no. golang/protobuf#555. In that case lets stay with protobuf norms. Transforming protoc generated structs into human readable/meaningful structs is something that I think always makes sense and we could address then.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

okay, gotcha

@kqdeng kqdeng requested a review from yetang-equinix June 10, 2020 19:09
fmt.Println(hw.JSON)
b, err := json.Marshal(hw)
if err != nil {
log.Fatal(err)

Choose a reason for hiding this comment

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

This is just to retrieve hardware info, may be one hardware data cannot be converted to json properly, we can just log an error and go on for next. Why do we have to log fatal, which will crash the cli agent and make it harder to debug.

metrics.CacheTotals.With(labels).Inc()
metrics.CacheErrors.With(labels).Inc()
err = errors.Wrap(err, "unmarshal json")
err := errors.New("id must be set to a UUID")

Choose a reason for hiding this comment

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

We can indicate that current hw.Id is nil string in this case (add hw.Id to error log). This will give extra info for debugging.

default:
metrics.WatchMissTotal.Inc()
logger.With("id", h.ID).Info("skipping blocked watcher")
logger.With("id", hw.Id ).Info("skipping blocked watcher")
}
}
s.watchLock.RUnlock()
Copy link

@yetang-equinix yetang-equinix Jun 10, 2020

Choose a reason for hiding this comment

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

Logging is slow, it should not be done between watch lock/unlock. Critical logging for error case is fine. But for information logging, we should do it after unlock.
This comment is for all places in this file that has info logging inside locked sections

)

var (
gitRev = "unknown"
gitRevJSON []byte
grpcListenAddr = "localhost:42113"

Choose a reason for hiding this comment

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

this port number should be in a config file, not hard coded here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How should the config file look like? Would it suffice if I just have the port be read from an environment variable and set a default port for when the variable unset?

Choose a reason for hiding this comment

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

Yes, there shall be a default value if there is no configured value. If we have quite some values, a file will be easy to manage.

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 think the closest to the config file you were referring to is the docker-compose.yml that is currently used to run all of the services.
I have added two new environment variables to allow the user to specify their own ports.

Please refer to this commit here: aee3b9f

@@ -128,32 +131,6 @@ services:
volumes:
- ./state/webroot:/usr/share/nginx/html/

cacher:

Choose a reason for hiding this comment

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

So we totally get ride of cacher from tinkerbell deployment. But do we still deploy cacher from other place? I can still see Hegel still interact with cacher in the other PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah, cacher is still used in other places, just not in tinkerbell

@kqdeng kqdeng merged commit 5e66098 into tinkerbell:master Jun 22, 2020
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.

6 participants