talos/internal/app/machined/pkg/system/service_events.go
Andrey Smirnov 9c63f4ed0a feat(init): implement complete API for service lifecycle (start/stop)
It is now possible to `start`/`stop`/`restart` any service via `osctl`
commands.

There are some changes in `ServiceRunner` to support re-use (re-entering
running state). `Services` singleton now tracks service running state to
avoid calling `Start()` on already running `ServiceRunner` instance.
Method `Start()` was renamed to `LoadAndStart()` to break up service
loading (adding to the list of service) and actual service start.

Signed-off-by: Andrey Smirnov <smirnov.andrey@gmail.com>
2019-08-01 11:16:57 -07:00

58 lines
1.3 KiB
Go

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package system
import (
"context"
"fmt"
"github.com/pkg/errors"
"github.com/talos-systems/talos/internal/app/machined/pkg/system/conditions"
)
// StateEvent is a service event (e.g. 'up', 'down')
type StateEvent string
// Service event list
const (
StateEventUp = StateEvent("up")
StateEventDown = StateEvent("down")
)
type serviceCondition struct {
event StateEvent
service string
}
func (sc *serviceCondition) Wait(ctx context.Context) error {
instance.mu.Lock()
svcrunner := instance.state[sc.service]
instance.mu.Unlock()
if svcrunner == nil {
return errors.Errorf("service %q is not registered", sc.service)
}
notifyCh := make(chan struct{}, 1)
svcrunner.Subscribe(sc.event, notifyCh)
defer svcrunner.Unsubscribe(sc.event, notifyCh)
select {
case <-ctx.Done():
return ctx.Err()
case <-notifyCh:
return nil
}
}
func (sc *serviceCondition) String() string {
return fmt.Sprintf("service %q to be %q", sc.service, string(sc.event))
}
// WaitForService waits for service to reach some state event
func WaitForService(event StateEvent, service string) conditions.Condition {
return &serviceCondition{event, service}
}