asteris-llc/converge

View on GitHub
resource/systemd/unit/preparer.go

Summary

Maintainability
A
0 mins
Test Coverage
// Copyright © 2016 Asteris, LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package unit

import (
    "github.com/asteris-llc/converge/load/registry"
    "github.com/asteris-llc/converge/resource"
    "golang.org/x/net/context"
)

// Preparer for UnitState
//
// UnitState configures loaded systemd units, allowing you to start, stop, or
// restart them, reload configuration files, and send unix signals.
type Preparer struct {
    // The name of the unit.  This may optionally include the unit type,
    // e.g. "foo.service" and "foo" are both valid.
    Name string `hcl:"unit" required:"true"`

    // The desired state of the unit.  This will affect the current unit job.  Use
    // `systemd.unit.file` to enable and disable jobs, or `systemd.unit.config` to
    // set options.
    State string `hcl:"state" valid_values:"running,stopped,restarted"`

    // If reload is true then the service will be instructed to reload it's
    // configuration as if the user had run `systemctl reload`.  This will reload
    // the actual confguration file for the service, not the systemd unit file
    // configuration. See `systemctl(1)` for more information.
    Reload bool `hcl:"reload"`

    // Sends a signal to the process, using it's name.  The signal may be in upper
    // or lower case (the `SIG` prefix) is optional.  For example, to send user
    // defined signal 1 to the process you may write any of: usr1, USR1, SIGUSR1,
    // or sigusr1
    //
    // see `signal(3)` on BSD/Darwin, or `signal(7)` on GNU Linux systems for more
    // information on signals
    SignalName string `hcl:"signal_name" mutually_exclusive:"signal_name,signal_num"`

    // Sends a signal to the process, using it's signal number.  The value must be
    // an unsigned integer value between 1 and 31 inclusive.
    SignalNumber uint `hcl:"signal_number" mutually_exclusive:"signal_name,signal_num"`

    executor SystemdExecutor
}

// Prepare a new task
func (p *Preparer) Prepare(ctx context.Context, render resource.Renderer) (resource.Task, error) {
    var signal *Signal
    if p.SignalName != "" {
        num, err := ParseSignalByName(p.SignalName)
        if err != nil {
            return nil, err
        }
        signal = &num
    } else if p.SignalNumber != 0 {
        name, err := ParseSignalByNumber(p.SignalNumber)
        if err != nil {
            return nil, err
        }
        signal = &name
    }

    if p.executor == nil {
        executor, err := realExecutor()
        if err != nil {
            return nil, err
        }
        p.executor = executor
    }

    r := &Resource{
        Reload:          p.Reload,
        Name:            p.Name,
        State:           p.State,
        systemdExecutor: p.executor,
    }

    if signal != nil {
        r.SignalName = signal.String()
        r.SignalNumber = uint(*signal)
        r.sendSignal = true
    }

    return r, nil
}

func init() {
    registry.Register("systemd.unit.state", (*Preparer)(nil), (*Resource)(nil))
}