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

packer: pick protobuf/gob for serialisation #13025

Merged
merged 1 commit into from
Jul 24, 2024

Conversation

lbajolet-hashicorp
Copy link
Contributor

As we're trying to move away from gob for serialising data over the wire, this commit adds the capability for Packer to pick dynamically between gob or protobuf for the serialisation format to communicate with plugins.

As it stands, if all the plugins discovered are compatible with protobuf, and we have not forced gob usage, protobuf will be the serialisation format picked.

If any plugin is not compatible with protobuf, gob will eb used for communicating with all the plugins that will be used over the course of a command.

Note: this will require the SDK to support it, so we need to have the related PR committed, and released before we can pull the plug on this one.

@lbajolet-hashicorp lbajolet-hashicorp added stage/waiting-on-upstream This issue is waiting on an upstream change tech-debt Issues and pull requests related to addressing technical debt or improving the codebase labels Jun 6, 2024
@nywilken
Copy link
Contributor

nywilken commented Jun 10, 2024

Using this thread to capture finding and fixes we need to make.

While testing using docker and shell-local I found a crash because of the protocol mixing. Internal plugin has gob, and external uses protobuf.

Internal plugins don't rely on describe so we would need to set these up to use protobuf by default and gob if we can't use it for all plug-ins.

protobuf                                                                                                                                   
2024/06/10 14:53:57 [DEBUG] - common: receiving ConfigSpec as protobuf                                                                     2024/06/10 14:53:57 [INFO] Starting internal plugin packer-provisioner-shell-local
2024/06/10 14:53:57 Starting plugin: /Users/dev/Development/packer/bin/packer []string{"/Users/dev/Development/packer/bin/packer", "execute
", "packer-provisioner-shell-local"}                                                                                                       2024/06/10 14:53:57 Waiting for RPC address for: /Users/dev/Development/packer/bin/packer
2024/06/10 14:53:57 packer-provisioner-shell-local plugin: [INFO] Packer version: 1.12.0-dev [go1.21.8 darwin arm64]
2024/06/10 14:53:57 packer-provisioner-shell-local plugin: [INFO] PACKER_CONFIG env var not set; checking the default config file path     2024/06/10 14:53:57 packer-provisioner-shell-local plugin: [INFO] PACKER_CONFIG env var set; attempting to open config file: /Users/dev/.pa
ckerconfig                                                                                                                                 
2024/06/10 14:53:57 packer-provisioner-shell-local plugin: [WARN] Config file doesn't exist: /Users/dev/.packerconfig
2024/06/10 14:53:57 packer-provisioner-shell-local plugin: [INFO] Setting cache directory: /Users/dev/.cache/packer
2024/06/10 14:53:57 packer-provisioner-shell-local plugin: Plugin address: unix /var/folders/jd/zhl6kpsn1156cmqdyttt22xm0000gp/T/packer-plu
gin439111653
2024/06/10 14:53:57 Received unix RPC address for /Users/dev/Development/packer/bin/packer: addr is /var/folders/jd/zhl6kpsn1156cmqdyttt22x
m0000gp/T/packer-plugin439111653
2024/06/10 14:53:57 packer-provisioner-shell-local plugin: Waiting for connection...
2024/06/10 14:53:57 packer-provisioner-shell-local plugin: Serving a plugin connection...
2024/06/10 14:53:57 packer-provisioner-shell-local plugin: [DEBUG] - common: sending ConfigSpec as gob
2024/06/10 14:53:57 [DEBUG] - common: receiving ConfigSpec as protobuf
2024/06/10 14:53:57 failed to unmarshal hclspec.Spec from raw protobuf: "proto:\u00a0cannot parse invalid wire-format data"
2024/06/10 14:53:57 waiting for all plugin processes to complete...
2024/06/10 14:53:57 /Users/dev/.config/packer/plugins/github.com/hashicorp/docker/packer-plugin-docker_v1.0.10-dev_x5.0_darwin_arm64: plugi
n process exited
2024/06/10 14:53:57 /Users/dev/Development/packer/bin/packer: plugin process exited
panic: failed to unmarshal hclspec.Spec from raw protobuf: "proto:\u00a0cannot parse invalid wire-format data" [recovered]
        panic: failed to unmarshal hclspec.Spec from raw protobuf: "proto:\u00a0cannot parse invalid wire-format data"

goroutine 1 [running]:
log.Panic({0x14000a2ffc8?, 0x14000880000?, 0x14000184110?})
panic: failed to unmarshal hclspec.Spec from raw protobuf: "proto:\u00a0cannot parse invalid wire-format data" [recovered]
        panic: failed to unmarshal hclspec.Spec from raw protobuf: "proto:\u00a0cannot parse invalid wire-format data"

goroutine 1 [running]:
log.Panic({0x14000a2ffc8?, 0x14000880000?, 0x14000184110?})
        /usr/local/go/src/log/log.go:432 +0x60
github.com/hashicorp/packer/packer.(*cmdProvisioner).checkExit(0x14000904680?, {0x105f9e8c0?, 0x14000184110}, 0x0)
        /Users/dev/Development/packer/packer/cmd_provisioner.go:50 +0x80
github.com/hashicorp/packer/packer.(*cmdProvisioner).ConfigSpec.func1()
        /Users/dev/Development/packer/packer/cmd_provisioner.go:22 +0x40
panic({0x105f9e8c0?, 0x14000184110?})
        /usr/local/go/src/runtime/panic.go:914 +0x218

@lbajolet-hashicorp lbajolet-hashicorp force-pushed the poc_protobuf_and_gob branch 4 times, most recently from 40ebdbe to 72f47be Compare June 14, 2024 18:10
@@ -100,6 +127,10 @@ func (c *ExecuteCommand) Run(args []string) int {
return 1
}

if args.UseProtobuf {
server.UseProto = true
Copy link
Contributor

Choose a reason for hiding this comment

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

Do the builtin plugins always use protobufs if supported? How do we toggle it off for built ins?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So the main Packer process is responsible for that, internal components are still executed much like any binary through packer execute, so if plugins support protobuf, we'll add the flag to the command, and the internal components will run as a server with protobuf.

Also I believe we can do server.UseProto = args.UseProtobuf instead of the if here :)

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay understood. Yeah these plugins are also not plugin.Set right so we have to set server.UseProto = args.UseProtobuf got it now.

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 exactly, plugin.Set is used only for plugins, as they register their components, and we can use the rest of the predefined commands for them.
Since this is internal, there's no concept of describe for example (not even sure the command's called start for an internal component), so Set is not used, but instead we directly create the server with the component requested by name.

return c.Client(pluginPath, "start", "builder", builderName).Builder()
args := []string{"start", "builder"}

if PackerUseProto {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be canProto? It looks like PackerUseProto is always true, which means we will always send --protobuf.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good question; nope :p

We use PackerUseProto as it's global, since this is a function that is lazily evaluated, we cannot access canProto as the value is lost once we leave this function (it's all local).
However if the value of PackerUseProto is changed to false while discovering plugins, when this is executed, it will use the last updated value for this, and correctly pick between protobuf/gob.

@nywilken nywilken changed the base branch from main to feature/protobuf-serialization July 24, 2024 20:41
As we're trying to move away from gob for serialising data over the
wire, this commit adds the capability for Packer to pick dynamically
between gob or protobuf for the serialisation format to communicate with
plugins.

As it stands, if all the plugins discovered are compatible with
protobuf, and we have not forced gob usage, protobuf will be the
serialisation format picked.

If any plugin is not compatible with protobuf, gob will be used for
communicating with all the plugins that will be used over the course of
a command.
@nywilken nywilken force-pushed the poc_protobuf_and_gob branch from 9707101 to cab0eac Compare July 24, 2024 20:48
@nywilken nywilken marked this pull request as ready for review July 24, 2024 20:48
@nywilken nywilken requested a review from a team as a code owner July 24, 2024 20:48
Copy link
Contributor

@nywilken nywilken left a comment

Choose a reason for hiding this comment

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

Approving to merge this into the proper feature branch. In that branch we can continue to iterate. The feature branches have been enable for CI and releases, which will be handy when we are ready to to cut an alpha.

@nywilken nywilken merged commit e4e6702 into feature/protobuf-serialization Jul 24, 2024
11 checks passed
@lbajolet-hashicorp lbajolet-hashicorp deleted the poc_protobuf_and_gob branch July 25, 2024 12:39
lbajolet-hashicorp added a commit that referenced this pull request Aug 6, 2024
As we're trying to move away from gob for serialising data over the
wire, this commit adds the capability for Packer to pick dynamically
between gob or protobuf for the serialisation format to communicate with
plugins.

As it stands, if all the plugins discovered are compatible with
protobuf, and we have not forced gob usage, protobuf will be the
serialisation format picked.

If any plugin is not compatible with protobuf, gob will be used for
communicating with all the plugins that will be used over the course of
a command.
lbajolet-hashicorp added a commit that referenced this pull request Aug 6, 2024
As we're trying to move away from gob for serialising data over the
wire, this commit adds the capability for Packer to pick dynamically
between gob or protobuf for the serialisation format to communicate with
plugins.

As it stands, if all the plugins discovered are compatible with
protobuf, and we have not forced gob usage, protobuf will be the
serialisation format picked.

If any plugin is not compatible with protobuf, gob will be used for
communicating with all the plugins that will be used over the course of
a command.
lbajolet-hashicorp added a commit that referenced this pull request Aug 13, 2024
As we're trying to move away from gob for serialising data over the
wire, this commit adds the capability for Packer to pick dynamically
between gob or protobuf for the serialisation format to communicate with
plugins.

As it stands, if all the plugins discovered are compatible with
protobuf, and we have not forced gob usage, protobuf will be the
serialisation format picked.

If any plugin is not compatible with protobuf, gob will be used for
communicating with all the plugins that will be used over the course of
a command.
Copy link

I'm going to lock this pull request because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 26, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
stage/waiting-on-upstream This issue is waiting on an upstream change tech-debt Issues and pull requests related to addressing technical debt or improving the codebase
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants