Skip to content
This repository has been archived by the owner on Feb 14, 2024. It is now read-only.

update implementation #1

Merged
merged 7 commits into from
Jun 22, 2017
Merged

update implementation #1

merged 7 commits into from
Jun 22, 2017

Conversation

murphybytes
Copy link
Contributor

This is still a work in progress. I just wanted to give people a preview of the approach and get feedback.

Copy link
Contributor

@zwass zwass left a comment

Choose a reason for hiding this comment

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

Where do we check the validity of the package signatures?

restart.go Outdated

package updater

// Fork process that inherites listening sockets
Copy link
Contributor

Choose a reason for hiding this comment

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

inherits

updater.go Outdated
// New creates a new updater. By default the updater will check for updates every hour
// but this may be changed by passing Frequency as an option. The minimum
// frequency is 10 minutes. Anything less than that will cause an error.
// Supply the WantNotfications option to get data on the state up update operations for
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo in last sentence of this comment? I am a bit confused by this.

updater.go Outdated
}

// WantNotfications pass a function that will collect information about updates.
func WantNotfications(hnd NotificationHandler) func() interface{} {
Copy link
Contributor

Choose a reason for hiding this comment

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

WantNotifications

updater.go Outdated
}

func updater(settings tuf.Settings, ticker <-chan time.Time, notifications NotificationHandler) {
for _ = range ticker {
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 need some mechanism for exiting this loop?

Copy link
Contributor Author

@murphybytes murphybytes Jun 14, 2017

Choose a reason for hiding this comment

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

No, this loop reads from a channel, when the channel is closed, the loop exits which is the desired behavior.

Copy link
Contributor

Choose a reason for hiding this comment

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

Where is the channel closed? I see that Stop() is called on the ticker, but according to the docs that does not close the channel.

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 catch, and I can't close the channel myself because of the direction of the channel which seems like an oversight imho. I'll create something different so we can handle graceful shutdown.

Copy link
Contributor

Choose a reason for hiding this comment

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

You don't need to close the channel, and would probably cause a panic if you do.
Calling Stop should be enough to not get any more ticks.

Copy link
Contributor

Choose a reason for hiding this comment

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

It is possible that leaving this loop hanging is a reasonable enough strategy, but we should make a conscious decision of whether we need a graceful shutdown here or not.

updater.go Outdated
var ErrCheckFrequency = fmt.Errorf("Frequency value must be %q or greater", minimumCheckFrequency)

// ErrPackageDoesNotExit the package file does not exist
var ErrPackageDoesNotExit = fmt.Errorf("package file does not exist")
Copy link
Contributor

Choose a reason for hiding this comment

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

ErrPackageDoesNotExist

updater.go Outdated
if os.IsNotExist(err) {
return ErrPackageDoesNotExit
}
cmd := exec.Command(updatePackagePath, "-rollback")
Copy link
Contributor

Choose a reason for hiding this comment

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

Will it be possible in the general case for each update package to know how to roll back to the previous version? It seems to me we may want to encode some state checkpointing/rollback into the updater itself, and then each package does not need to consider this.

updater.go Outdated
return ErrPackageDoesNotExit
}
if err != nil {
return errors.Wrap(err, "checking for package existance")
Copy link
Contributor

Choose a reason for hiding this comment

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

existence

updater.go Outdated
// Start begins checking for updates.
func (u *Updater) Start() {
u.ticker = time.NewTicker(u.checkFrequency)
go updater(u.settings, u.ticker.C, u.notificationHandler)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it would be cleaner if you put the ticker inside the updater function, and pass in a done chan struct{} to start/stop the go-routine.

the updater func would select between the ticker and the done channel, and when it receives done the go-routine can exit cleanly.

Copy link
Contributor

Choose a reason for hiding this comment

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

I made a simple example just in case: https://play.golang.org/p/U6apw-52tB

Copy link
Contributor

@marpaia marpaia left a comment

Choose a reason for hiding this comment

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

there's a lot of code here and it looks good / well tested, but I'd really like to sit down together and get a better understanding of how this all works and the general control flow in the happy path, etc.

if err != nil {
return errors.Wrap(err, "opening role file for writing")
}
defer f.Close()
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 above the error handling?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No. If OpenFile returns an error the file has not been opened, in addition, by convention if an error is returned there is no guarantee that 'f' will not be null so calling f.Close() could create a panic.

}

func (r *localRepo) getRole(name role, val interface{}) error {
err := validateRole(name)
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: a lot of these blocks could be made more succinct by doing:

if err := validateRole(name); err != nil {
  return err
}

@murphybytes murphybytes changed the title Start of async update groroutine update implementation Jun 20, 2017
@murphybytes murphybytes merged commit 176cff9 into kolide:master Jun 22, 2017
@murphybytes murphybytes deleted the tuf_impl branch June 22, 2017 15:45
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants