-
Notifications
You must be signed in to change notification settings - Fork 248
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
Status Report for Packet Instance #566
Status Report for Packet Instance #566
Conversation
Can one of the admins verify this patch? |
On a Packet Instance, run To supply the instance with an ignition config file, use The Timeline will an error message if the config is invalid. But will not show any messages if no config was given or was correctly booted with. Unless that is desired, but as far as my discussions went with Derek, only show the message on the Timeline if there is an error i.e. when ignition fails, all else remains the same. |
e07d915
to
69d0703
Compare
internal/oem/oem.go
Outdated
// r := report.Report{ | ||
// Entries: []Entry{ | ||
// { | ||
// Message: "Ignition Failed", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ajeddeloh Is it necessary to use report.Report?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, the report is just for config validation. We should send the actual error to the cloud though (which might be from a report.Report{}, but might not be as well)
Link to blog about metadata.packet.net : https://help.packet.net/technical/hacking/user-state |
9e76179
to
ed97ed5
Compare
9a5c914
to
f59dbcd
Compare
@ajeddeloh I've added a more detailed error/status message that posts to the Packet timeline (to the user). After looking at Kola, it looks like it's using an external package from Packet to form an instance, it's not a simple rest api call if I understand correctly. So let me know how you would like me to tell Packet that ignition failed, right now its a simple |
internal/exec/engine.go
Outdated
@@ -53,10 +53,10 @@ type Engine struct { | |||
|
|||
// Run executes the stage of the given name. It returns true if the stage | |||
// successfully ran and false if there were any errors. | |||
func (e Engine) Run(stageName string) bool { | |||
func (e Engine) Run(stageName string) (bool, string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should just return an error
. It should have from the start.
internal/exec/engine.go
Outdated
} | ||
|
||
e.Logger.PushPrefix(stageName) | ||
defer e.Logger.PopPrefix() | ||
|
||
return stages.Get(stageName).Create(e.Logger, e.Root, *e.Fetcher).Run(config.Append(baseConfig, config.Append(systemBaseConfig, cfg))) | ||
return stages.Get(stageName).Create(e.Logger, e.Root, *e.Fetcher).Run(config.Append(baseConfig, config.Append(systemBaseConfig, cfg))), "Valid Ignition Config" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The stages should also return an error (this is some long overdue refactoring)
internal/main.go
Outdated
if !engine.Run(flags.stage.String()) { | ||
if !ignSuccess { | ||
// ignition fails | ||
logger.Info("Ignition Fails") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: s/Fails/Failed
internal/main.go
Outdated
os.Exit(1) | ||
} else { | ||
logger.Info("Ignition Passes") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need to log sucess, but I'm not that opinionated. If you do want to, maybe "Ignition finished successfully".
internal/resource/http.go
Outdated
@@ -199,6 +199,7 @@ func (f *Fetcher) newHttpClient() { | |||
// code, a cancel function for the result's context, and error (if any). By | |||
// default, User-Agent is added to the header but this can be overridden. | |||
func (c HttpClient) getReaderWithHeader(url string, header http.Header) (io.ReadCloser, int, context.CancelFunc, error) { | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spurious newline
internal/providers/packet/packet.go
Outdated
Message: "Ignition: valid config", | ||
} | ||
|
||
// Marshall Message |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this part is common to both branches of the if and can be broken out
internal/oem/oem.go
Outdated
@@ -61,6 +62,21 @@ func (c Config) NewFetcherFunc() providers.FuncNewFetcher { | |||
} | |||
} | |||
|
|||
// Status takes b as whether ignition passes (true) or fails | |||
// msg is the error or success message | |||
func (c Config) Status(b bool, msg string) providers.FuncStatusFetcher { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there shouldn't be packet specific stuff in oem/oem
. Instead the packet version should be registered below.
internal/oem/oem.go
Outdated
@@ -40,6 +40,7 @@ type Config struct { | |||
name string | |||
fetch providers.FuncFetchConfig | |||
newFetcher providers.FuncNewFetcher | |||
status providers.FuncStatusFetcher |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe statusFunc
?
internal/resource/url.go
Outdated
@@ -219,9 +219,13 @@ func (f *Fetcher) FetchFromTFTP(u url.URL, dest *os.File, opts FetchOptions) err | |||
// FetchFromHTTP fetches a resource from u via HTTP(S) into dest, returning an | |||
// error if one is encountered. | |||
func (f *Fetcher) FetchFromHTTP(u url.URL, dest *os.File, opts FetchOptions) error { | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spurious newline
internal/resource/url.go
Outdated
if f.client == nil { | ||
logger := log.New(true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why this addition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
f enters FetchfromHTTP as nil, for Looger and client
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than instantiating the logger here would it work to change the Fetcher instantiation here to call rf, err := c.NewFetcherFunc()(log.New(true)
?
internal/providers/packet/packet.go
Outdated
fmt.Println("Error: ", err) | ||
} | ||
|
||
type Metadata struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
Rather than declaring this type, which is only used once inline, can you not just do this when assinging the metadata
variable:
metadata := struct {
PhoneHomeURL string `json:"phone_home_url"`
}{}
If you do want to keep the type I think it should be moved outside of the function.
internal/providers/packet/packet.go
Outdated
fmt.Println("Error: ", err) | ||
} | ||
postReq.Header.Set("Content-Type", "application/json") | ||
client := &http.Client{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ajeddeloh: would it make sense to make a GetHttpClient
function of the Fetcher
object and/or make a Post
call? That way we can get clients with the correct Transport
& http.Client
customizations easier?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmmm actually I don't think so. Ignition could have failed because of wonky timeouts/CAs. We shouldn't need those customizations here, especially since this is packet specific.
internal/providers/packet/packet.go
Outdated
} | ||
|
||
if err != nil { | ||
fmt.Println("Error: ", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Drop fmt
calls. If you need to log a message use log
b730e32
to
e1b840a
Compare
internal/distro/distro.go
Outdated
@@ -59,7 +59,7 @@ func DiskByPartUUIDDir() string { return diskByPartUUIDDir } | |||
func OEMDevicePath() string { return fromEnv("OEM_DEVICE", oemDevicePath) } | |||
|
|||
func KernelCmdlinePath() string { return kernelCmdlinePath } | |||
func SystemConfigDir() string { return fromEnv("SYSTEM_CONFIG_DIR", systemConfigDir) } | |||
func SystemConfigDir() string { return fromEnv("SYSTEM_CONFIG_DIR", "/home/core") } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this being changed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When running ignition and setting -oem
as packet
, ignition doesn't seem to take the exported env SYSTEM_CONFIG_DIR
so I hard coded the path for the mean time.
internal/exec/engine.go
Outdated
if e.Fetcher == nil || e.Logger == nil { | ||
fmt.Fprintf(os.Stderr, "engine incorrectly configured\n") | ||
return false | ||
err := errors.ErrEngineConfiguration | ||
return false, err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can just directly return errors.ErrEngineConfiguration
rather than using a temporary variable.
internal/exec/engine.go
Outdated
} | ||
|
||
e.Logger.PushPrefix(stageName) | ||
defer e.Logger.PopPrefix() | ||
|
||
return stages.Get(stageName).Create(e.Logger, e.Root, *e.Fetcher).Run(config.Append(baseConfig, config.Append(systemBaseConfig, cfg))) | ||
return stages.Get(stageName).Create(e.Logger, e.Root, *e.Fetcher).Run(config.Append(baseConfig, config.Append(systemBaseConfig, cfg))), err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you tested this change in a situation where you'd receive a ErrNoProvider
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In internal/providers/system/system.go
(line 55) when a config is not given at the default path as specified by $SYSTEM_CONFIG_DIR
, ErrNoProvider will be called for example, and will show: Ignition error: config provider was not online
internal/oem/oem.go
Outdated
// Status takes b as whether ignition passes (true) or fails | ||
// msg is the error or success message | ||
func (c Config) Status(f resource.Fetcher, status error) error { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like your editor is sneaking in a lot of random newlines.
internal/providers/packet/packet.go
Outdated
@@ -18,7 +18,12 @@ | |||
package packet | |||
|
|||
import ( | |||
"bytes" | |||
"encoding/json" | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Drop this extra newline
internal/providers/packet/packet.go
Outdated
data, err := f.FetchToBuffer(metadataUrl, resource.FetchOptions{ | ||
Headers: nil, | ||
}) | ||
if data == nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a possible case where a nil
is returned for both data
& err
? If so then this function will appear to pass despite not working. Also this check should probably be combined with the err != nil
check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Data | Err | return value |
---|---|---|
!nil |
!nil |
err |
!nil |
nil |
do nothing |
nil |
!nil |
err |
nil |
nil |
ErrValidFetchEmptyData |
for this:
if err != nil {
return err
}
if data == nil {
return errors.ErrValidFetchEmptyData
}
internal/providers/packet/packet.go ( line 72 )
internal/resource/url.go
Outdated
if f.client == nil { | ||
f.newHttpClient() | ||
} | ||
// loging := log.New(true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Drop the commented code.
053bc11
to
70c3c0e
Compare
Here's my .sh file to build and test ignition Packet changes on the SDK if anyone wants this. Also please ^ critique ! 😄 |
internal/exec/engine.go
Outdated
@@ -53,10 +53,10 @@ type Engine struct { | |||
|
|||
// Run executes the stage of the given name. It returns true if the stage | |||
// successfully ran and false if there were any errors. | |||
func (e Engine) Run(stageName string) bool { | |||
func (e Engine) Run(stageName string) (bool, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The bool here is redundant and can be dropped completely. It's always true when the error is nil and false when the error is non-nil.
internal/exec/engine.go
Outdated
} | ||
|
||
e.Logger.PushPrefix(stageName) | ||
defer e.Logger.PopPrefix() | ||
|
||
return stages.Get(stageName).Create(e.Logger, e.Root, *e.Fetcher).Run(config.Append(baseConfig, config.Append(systemBaseConfig, cfg))) | ||
return stages.Get(stageName).Create(e.Logger, e.Root, *e.Fetcher).Run(config.Append(baseConfig, config.Append(systemBaseConfig, cfg))), err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The stage should be changed to return an error instead of a bool and that should be returned here.
internal/main.go
Outdated
} else { | ||
logger.Info("ERRORRRRR IS NIL") | ||
} | ||
statusErr := engine.OEMConfig.Status(*engine.Fetcher, err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor nit: these twoi lines can be combined into something like:
if statusErr := engine.OEM... ; statusErr != nil {
internal/oem/oem.go
Outdated
// msg is the error or success message | ||
func (c Config) Status(f resource.Fetcher, statusErr error) error { | ||
if c.status != nil { | ||
err := c.status(f, statusErr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can just return this here and let the caller log it.
internal/resource/url.go
Outdated
@@ -241,7 +246,6 @@ func (f *Fetcher) FetchFromHTTP(u url.URL, dest *os.File, opts FetchOptions) err | |||
default: | |||
return ErrFailed | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dropped this
internal/providers/packet/packet.go
Outdated
State: "failed", | ||
Message: message, | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extra newline
internal/providers/packet/packet.go
Outdated
|
||
} else { | ||
|
||
err = postMessage(errMsg, f, "Ignition: valid config", postMessageURL) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/Ignition: valid config/Ignition stage exited successful
You can have a valid config and still fail.
internal/providers/packet/packet.go
Outdated
postMessageURL := phonehomeURL + "/events" | ||
if errMsg != nil { | ||
|
||
err = postMessage(errMsg, f, "Ignition error: "+errMsg.Error(), postMessageURL) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably want to include the stage (e.g. files/disks)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the stage name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah
7dd8d61
to
849c30c
Compare
The script that terminates Packet instances running for more than a day doesn't seem to be working. @ajeddeloh I believe you've mentioned of such script before. |
@Bubblemelon are you referring to the |
internal/distro/distro.go
Outdated
@@ -59,7 +59,7 @@ func DiskByPartUUIDDir() string { return diskByPartUUIDDir } | |||
func OEMDevicePath() string { return fromEnv("OEM_DEVICE", oemDevicePath) } | |||
|
|||
func KernelCmdlinePath() string { return kernelCmdlinePath } | |||
func SystemConfigDir() string { return fromEnv("SYSTEM_CONFIG_DIR", systemConfigDir) } | |||
func SystemConfigDir() string { return fromEnv("SYSTEM_CONFIG_DIR", "/home/core/") } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be changed back before merging
internal/exec/engine.go
Outdated
@@ -16,6 +16,7 @@ package exec | |||
|
|||
import ( | |||
"encoding/json" | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove extra newline
internal/exec/engine.go
Outdated
} | ||
|
||
e.Logger.PushPrefix(stageName) | ||
defer e.Logger.PopPrefix() | ||
|
||
return stages.Get(stageName).Create(e.Logger, e.Root, *e.Fetcher).Run(config.Append(baseConfig, config.Append(systemBaseConfig, cfg))) | ||
if err = stages.Get(stageName).Create(e.Logger, e.Root, *e.Fetcher).Run(config.Append(baseConfig, config.Append(systemBaseConfig, cfg))); err != nil { | ||
e.Logger.Crit("%s did not pass", stageName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would actually use fmt.Fprintf(os.Stderr, ...
since one of the failure modes is that Logger could be nil.
nit: "Stage %s failed" instead of "%s did not pass".
internal/main.go
Outdated
if !engine.Run(flags.stage.String()) { | ||
if err = engine.Run(flags.stage.String()); err != nil { | ||
logger.Crit("Ignition failed") | ||
if err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is always true
internal/main.go
Outdated
if err != nil { | ||
logger.Err(err.Error()) | ||
} | ||
if statusErr := engine.OEMConfig.Status(flags.stage.String(), *engine.Fetcher, err); statusErr != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would be good to break this common code out of the if.
internal/exec/stages/disks/disks.go
Outdated
@@ -163,3 +165,8 @@ func (s stage) waitOnDevicesAndCreateAliases(devs []string, ctxt string) error { | |||
|
|||
return nil | |||
} | |||
|
|||
func newDiskStageError(msg string, err error) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would just use fmt.Errorf
in the call sites.
internal/providers/packet/packet.go
Outdated
// POST Message to phonehome IP | ||
postMessageURL := phonehomeURL + "/events" | ||
|
||
err = postMessage(stageName, errMsg, f, postMessageURL) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just return postMessage(...)
internal/providers/packet/packet.go
Outdated
} | ||
|
||
// postMessage makes a post request with the supplied message to the url | ||
func postMessage(stageName string, e error, f resource.Fetcher, url string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think f
is unused.
17210d0
to
f6a5001
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly lgtm, except a few nits. Can you rework the commits to have something like:
- rework run to return an error
- add the framework for reporting statues
- add the packet implementation
internal/exec/engine.go
Outdated
return err | ||
} | ||
e.Logger.Info("passed") | ||
return err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: return nil here (since err must be nil) to make it clear that this is the sucessful case
internal/main.go
Outdated
os.Exit(1) | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Don't need the else
since the other branch exits
internal/providers/packet/packet.go
Outdated
err = json.Unmarshal(data, &metadata) | ||
if err != nil { | ||
return err | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: extra newline
777cb1c
to
e066080
Compare
4895b7a
to
b7856d2
Compare
Covered suggested/requested items and had gone over them with Andrew.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two minor nits: some wording in a message and an extra newline, other than that LGTM
internal/exec/engine.go
Outdated
fmt.Fprintf(os.Stderr, "%s failed", stageName) | ||
return err | ||
} | ||
e.Logger.Info("passed") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add stage name here like in the failed message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
internal/providers/packet/packet.go
Outdated
fmt.Println("Error: ", err) | ||
} | ||
postReq.Header.Set("Content-Type", "application/json") | ||
client := &http.Client{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmmm actually I don't think so. Ignition could have failed because of wonky timeouts/CAs. We shouldn't need those customizations here, especially since this is packet specific.
Run() returns an error instead of a bool.
main.go checks if stage Run() is successful. oem.go implements the a Status() function that calls the oem specific fucntion to report the ignition status. FetchFromHTTP in url.go will check if f.client is nill.
packet.go POST igntion status messages to Packet.net via Packet's api url.
b7856d2
to
d604cd9
Compare
This references issue #2444.
The ./ignition build works when it is sent to a Packet instance.
However, has trouble logging via ssh when an image with the changes in igntion is booted onto an instance. I roughly know what is causing this problem.
The commits in the PR are numerous but I will eventually squash it into one commit after removing the debug prints some from logger.Info() and fmt.Println(). So I'm ignoring the tailor check for now, until I
have one squashed commit.