pkiadm/cmd/pkiadmd/location.go
Gibheer bc84bc4a28 add location support
This commit adds basic support for adding, deleting, ... locations. This
needed a bit of rework for the ResourceName, as it was kind of stupid to
have different implementations server internally and in the lib.

There is still some need for cleanup, but it works basically.
2017-05-31 21:03:51 +02:00

203 lines
4.8 KiB
Go

package main
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"github.com/gibheer/pkiadm"
)
const (
ENoPathGiven = Error("no path given")
)
type (
Location struct {
ID string
PreCommand string
PostCommand string
Path string
Dependencies []pkiadm.ResourceName
}
)
func NewLocation(id, path, preCom, postCom string, res []pkiadm.ResourceName) (*Location, error) {
if id == "" {
return nil, ENoIDGiven
}
if path == "" {
return nil, ENoPathGiven
}
l := &Location{
ID: id,
Path: path,
Dependencies: res,
}
return l, nil
}
func (l *Location) Name() pkiadm.ResourceName {
return pkiadm.ResourceName{l.ID, pkiadm.RTLocation}
}
// Refresh writes all resources into the single file.
func (l *Location) Refresh(lookup *Storage) error {
raw := []byte{}
for _, rn := range l.DependsOn() {
r, err := lookup.Get(rn)
if err != nil {
return err
}
output, err := r.Pem()
if err != nil {
return err
}
raw = append(raw, output...)
}
if l.PreCommand != "" {
cmd := exec.Command(l.PreCommand, l.Path)
if err := cmd.Run(); err != nil {
return err
}
}
if err := ioutil.WriteFile(l.Path, raw, 0600); err != nil {
return err
}
if l.PostCommand != "" {
cmd := exec.Command(l.PostCommand, l.Path)
if err := cmd.Run(); err != nil {
return err
}
}
return nil
}
func (l *Location) DependsOn() []pkiadm.ResourceName { return l.Dependencies }
// Pem is not used by location, as it does not contain any data.
func (l *Location) Pem() ([]byte, error) { return []byte{}, nil }
// Checksum is not used by Location, as it does not contain any data.
func (l *Location) Checksum() []byte { return []byte{} }
func (s *Server) CreateLocation(inLoc pkiadm.Location, res *pkiadm.Result) error {
s.lock()
defer s.unlock()
deps := []pkiadm.ResourceName{}
for _, dep := range inLoc.Dependencies {
deps = append(deps, pkiadm.ResourceName{ID: dep.ID, Type: dep.Type})
}
loc, err := NewLocation(inLoc.ID, inLoc.Path, inLoc.PreCommand, inLoc.PostCommand, deps)
if err != nil {
res.SetError(err, "Could not create location '%s'", inLoc.ID)
return nil
}
if err := s.storage.AddLocation(loc); err != nil {
res.SetError(err, "Could not add location '%s'", inLoc.ID)
return nil
}
return s.store(res)
}
func (s *Server) SetLocation(changeset pkiadm.LocationChange, res *pkiadm.Result) error {
s.lock()
defer s.unlock()
changed := changeset.Location
locName := pkiadm.ResourceName{changed.ID, pkiadm.RTLocation}
loc, err := s.storage.GetLocation(locName)
if err != nil {
res.SetError(err, "could not find location '%s'", changeset.Location.ID)
return nil
}
for _, field := range changeset.FieldList {
switch field {
case "path":
// TODO remove old file?
loc.Path = changed.Path
case "pre-cmd":
loc.PreCommand = changed.PreCommand
case "post-cmd":
loc.PostCommand = changed.PostCommand
case "resources":
loc.Dependencies = changed.Dependencies
default:
res.SetError(fmt.Errorf("unknown field"), "unknown field '%s'", field)
return nil
}
}
if err := s.storage.Update(locName); err != nil {
res.SetError(err, "Could not update location '%s'", loc.ID)
return nil
}
return s.store(res)
}
func (s *Server) DeleteLocation(inLoc pkiadm.Location, res *pkiadm.Result) error {
s.lock()
defer s.unlock()
loc, err := s.storage.GetLocation(pkiadm.ResourceName{inLoc.ID, pkiadm.RTLocation})
if err != nil {
res.SetError(err, "could not find location '%s'", inLoc.ID)
return nil
}
if err := os.Remove(loc.Path); err != nil {
res.SetError(err, "Could not remove file '%s' for location '%s'", loc.Path, loc.ID)
return nil
}
if err := s.storage.Remove(loc); err != nil {
res.SetError(err, "Could not remove location '%s'", loc.ID)
return nil
}
if loc.PostCommand != "" {
cmd := exec.Command(loc.PostCommand, loc.Path)
if err := cmd.Run(); err != nil {
res.SetError(err, "Could not run post command after deleting '%s'", loc.ID)
return nil
}
}
return s.store(res)
}
func (s *Server) ShowLocation(inLoc pkiadm.PrivateKey, res *pkiadm.ResultLocations) error {
s.lock()
defer s.unlock()
loc, err := s.storage.GetLocation(pkiadm.ResourceName{inLoc.ID, pkiadm.RTLocation})
if err != nil {
res.Result.SetError(err, "Could not find location '%s'", inLoc.ID)
return nil
}
res.Locations = []pkiadm.Location{pkiadm.Location{
ID: loc.ID,
Path: loc.Path,
PreCommand: loc.PreCommand,
PostCommand: loc.PostCommand,
Dependencies: loc.Dependencies,
}}
return nil
}
func (s *Server) ListLocation(filter pkiadm.Filter, res *pkiadm.ResultLocations) error {
s.lock()
defer s.unlock()
for _, loc := range s.storage.Locations {
res.Locations = append(res.Locations, pkiadm.Location{
ID: loc.ID,
Path: loc.Path,
PreCommand: loc.PreCommand,
PostCommand: loc.PostCommand,
Dependencies: loc.Dependencies,
})
}
return nil
}