Add some of the pkg and svc autoedge logic
This adds another chunk of it, and makes some other small fixes.
This commit is contained in:
29
examples/autoedges3.yaml
Normal file
29
examples/autoedges3.yaml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
graph: mygraph
|
||||||
|
resources:
|
||||||
|
pkg:
|
||||||
|
- name: drbd-utils
|
||||||
|
meta:
|
||||||
|
autoedge: true
|
||||||
|
state: installed
|
||||||
|
file:
|
||||||
|
- name: file1
|
||||||
|
meta:
|
||||||
|
autoedge: true
|
||||||
|
path: "/etc/drbd.conf"
|
||||||
|
content: |
|
||||||
|
# this is an mgmt test
|
||||||
|
state: exists
|
||||||
|
- name: file2
|
||||||
|
meta:
|
||||||
|
autoedge: true
|
||||||
|
path: "/etc/drbd.d/"
|
||||||
|
content: |
|
||||||
|
i am a directory
|
||||||
|
state: exists
|
||||||
|
svc:
|
||||||
|
- name: drbd
|
||||||
|
meta:
|
||||||
|
autoedge: true
|
||||||
|
state: stopped
|
||||||
|
edges: []
|
||||||
134
misc_test.go
134
misc_test.go
@@ -656,4 +656,138 @@ func TestMiscT11(t *testing.T) {
|
|||||||
if !reflect.DeepEqual(ex9, out9) {
|
if !reflect.DeepEqual(ex9, out9) {
|
||||||
t.Errorf("RemoveCommonFilePrefixes expected: %v; got: %v.", ex9, out9)
|
t.Errorf("RemoveCommonFilePrefixes expected: %v; got: %v.", ex9, out9)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
in10 := []string{
|
||||||
|
"/etc/drbd.conf",
|
||||||
|
"/etc/drbd.d/", // watch me, i'm a dir
|
||||||
|
"/etc/drbd.d/global_common.conf", // and watch me i'm a file!
|
||||||
|
"/lib/drbd/drbd",
|
||||||
|
"/lib/drbd/drbdadm-83",
|
||||||
|
"/lib/drbd/drbdadm-84",
|
||||||
|
"/lib/drbd/drbdsetup-83",
|
||||||
|
"/lib/drbd/drbdsetup-84",
|
||||||
|
"/usr/lib/drbd/crm-fence-peer.sh",
|
||||||
|
"/usr/lib/drbd/crm-unfence-peer.sh",
|
||||||
|
"/usr/lib/drbd/notify-emergency-reboot.sh",
|
||||||
|
"/usr/lib/drbd/notify-emergency-shutdown.sh",
|
||||||
|
"/usr/lib/drbd/notify-io-error.sh",
|
||||||
|
"/usr/lib/drbd/notify-out-of-sync.sh",
|
||||||
|
"/usr/lib/drbd/notify-pri-lost-after-sb.sh",
|
||||||
|
"/usr/lib/drbd/notify-pri-lost.sh",
|
||||||
|
"/usr/lib/drbd/notify-pri-on-incon-degr.sh",
|
||||||
|
"/usr/lib/drbd/notify-split-brain.sh",
|
||||||
|
"/usr/lib/drbd/notify.sh",
|
||||||
|
"/usr/lib/drbd/outdate-peer.sh",
|
||||||
|
"/usr/lib/drbd/rhcs_fence",
|
||||||
|
"/usr/lib/drbd/snapshot-resync-target-lvm.sh",
|
||||||
|
"/usr/lib/drbd/stonith_admin-fence-peer.sh",
|
||||||
|
"/usr/lib/drbd/unsnapshot-resync-target-lvm.sh",
|
||||||
|
"/usr/lib/systemd/system/drbd.service",
|
||||||
|
"/usr/lib/tmpfiles.d/drbd.conf",
|
||||||
|
"/usr/sbin/drbd-overview",
|
||||||
|
"/usr/sbin/drbdadm",
|
||||||
|
"/usr/sbin/drbdmeta",
|
||||||
|
"/usr/sbin/drbdsetup",
|
||||||
|
"/usr/share/doc/drbd-utils/", // watch me, i'm a dir too
|
||||||
|
"/usr/share/doc/drbd-utils/COPYING",
|
||||||
|
"/usr/share/doc/drbd-utils/ChangeLog",
|
||||||
|
"/usr/share/doc/drbd-utils/README",
|
||||||
|
"/usr/share/doc/drbd-utils/drbd.conf.example",
|
||||||
|
"/usr/share/man/man5/drbd.conf-8.3.5.gz",
|
||||||
|
"/usr/share/man/man5/drbd.conf-8.4.5.gz",
|
||||||
|
"/usr/share/man/man5/drbd.conf-9.0.5.gz",
|
||||||
|
"/usr/share/man/man5/drbd.conf.5.gz",
|
||||||
|
"/usr/share/man/man8/drbd-8.3.8.gz",
|
||||||
|
"/usr/share/man/man8/drbd-8.4.8.gz",
|
||||||
|
"/usr/share/man/man8/drbd-9.0.8.gz",
|
||||||
|
"/usr/share/man/man8/drbd-overview-9.0.8.gz",
|
||||||
|
"/usr/share/man/man8/drbd-overview.8.gz",
|
||||||
|
"/usr/share/man/man8/drbd.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdadm-8.3.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdadm-8.4.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdadm-9.0.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdadm.8.gz",
|
||||||
|
"/usr/share/man/man8/drbddisk-8.3.8.gz",
|
||||||
|
"/usr/share/man/man8/drbddisk-8.4.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdmeta-8.3.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdmeta-8.4.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdmeta-9.0.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdmeta.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdsetup-8.3.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdsetup-8.4.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdsetup-9.0.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdsetup.8.gz",
|
||||||
|
"/var/lib/drbd",
|
||||||
|
}
|
||||||
|
ex10 := []string{
|
||||||
|
"/etc/drbd.conf",
|
||||||
|
"/etc/drbd.d/global_common.conf",
|
||||||
|
"/lib/drbd/drbd",
|
||||||
|
"/lib/drbd/drbdadm-83",
|
||||||
|
"/lib/drbd/drbdadm-84",
|
||||||
|
"/lib/drbd/drbdsetup-83",
|
||||||
|
"/lib/drbd/drbdsetup-84",
|
||||||
|
"/usr/lib/drbd/crm-fence-peer.sh",
|
||||||
|
"/usr/lib/drbd/crm-unfence-peer.sh",
|
||||||
|
"/usr/lib/drbd/notify-emergency-reboot.sh",
|
||||||
|
"/usr/lib/drbd/notify-emergency-shutdown.sh",
|
||||||
|
"/usr/lib/drbd/notify-io-error.sh",
|
||||||
|
"/usr/lib/drbd/notify-out-of-sync.sh",
|
||||||
|
"/usr/lib/drbd/notify-pri-lost-after-sb.sh",
|
||||||
|
"/usr/lib/drbd/notify-pri-lost.sh",
|
||||||
|
"/usr/lib/drbd/notify-pri-on-incon-degr.sh",
|
||||||
|
"/usr/lib/drbd/notify-split-brain.sh",
|
||||||
|
"/usr/lib/drbd/notify.sh",
|
||||||
|
"/usr/lib/drbd/outdate-peer.sh",
|
||||||
|
"/usr/lib/drbd/rhcs_fence",
|
||||||
|
"/usr/lib/drbd/snapshot-resync-target-lvm.sh",
|
||||||
|
"/usr/lib/drbd/stonith_admin-fence-peer.sh",
|
||||||
|
"/usr/lib/drbd/unsnapshot-resync-target-lvm.sh",
|
||||||
|
"/usr/lib/systemd/system/drbd.service",
|
||||||
|
"/usr/lib/tmpfiles.d/drbd.conf",
|
||||||
|
"/usr/sbin/drbd-overview",
|
||||||
|
"/usr/sbin/drbdadm",
|
||||||
|
"/usr/sbin/drbdmeta",
|
||||||
|
"/usr/sbin/drbdsetup",
|
||||||
|
"/usr/share/doc/drbd-utils/COPYING",
|
||||||
|
"/usr/share/doc/drbd-utils/ChangeLog",
|
||||||
|
"/usr/share/doc/drbd-utils/README",
|
||||||
|
"/usr/share/doc/drbd-utils/drbd.conf.example",
|
||||||
|
"/usr/share/man/man5/drbd.conf-8.3.5.gz",
|
||||||
|
"/usr/share/man/man5/drbd.conf-8.4.5.gz",
|
||||||
|
"/usr/share/man/man5/drbd.conf-9.0.5.gz",
|
||||||
|
"/usr/share/man/man5/drbd.conf.5.gz",
|
||||||
|
"/usr/share/man/man8/drbd-8.3.8.gz",
|
||||||
|
"/usr/share/man/man8/drbd-8.4.8.gz",
|
||||||
|
"/usr/share/man/man8/drbd-9.0.8.gz",
|
||||||
|
"/usr/share/man/man8/drbd-overview-9.0.8.gz",
|
||||||
|
"/usr/share/man/man8/drbd-overview.8.gz",
|
||||||
|
"/usr/share/man/man8/drbd.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdadm-8.3.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdadm-8.4.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdadm-9.0.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdadm.8.gz",
|
||||||
|
"/usr/share/man/man8/drbddisk-8.3.8.gz",
|
||||||
|
"/usr/share/man/man8/drbddisk-8.4.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdmeta-8.3.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdmeta-8.4.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdmeta-9.0.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdmeta.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdsetup-8.3.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdsetup-8.4.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdsetup-9.0.8.gz",
|
||||||
|
"/usr/share/man/man8/drbdsetup.8.gz",
|
||||||
|
"/var/lib/drbd",
|
||||||
|
}
|
||||||
|
sort.Strings(ex10)
|
||||||
|
out10 := RemoveCommonFilePrefixes(in10)
|
||||||
|
sort.Strings(out10)
|
||||||
|
if !reflect.DeepEqual(ex10, out10) {
|
||||||
|
t.Errorf("RemoveCommonFilePrefixes expected: %v; got: %v.", ex10, out10)
|
||||||
|
for i := 0; i < len(ex10); i++ {
|
||||||
|
if ex10[i] != out10[i] {
|
||||||
|
t.Errorf("# %d: %v <> %v", i, ex10[i], out10[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -196,16 +196,10 @@ func (bus *Conn) matchSignal(ch chan *dbus.Signal, path dbus.ObjectPath, iface s
|
|||||||
if call.Err != nil {
|
if call.Err != nil {
|
||||||
return call.Err
|
return call.Err
|
||||||
}
|
}
|
||||||
if PK_DEBUG {
|
|
||||||
log.Println("PackageKit: matchSignal(): Added!")
|
|
||||||
}
|
|
||||||
// The caller has to make sure that ch is sufficiently buffered; if a
|
// The caller has to make sure that ch is sufficiently buffered; if a
|
||||||
// message arrives when a write to c is not possible, it is discarded!
|
// message arrives when a write to c is not possible, it is discarded!
|
||||||
// This can be disastrous if we're waiting for a "Finished" signal!
|
// This can be disastrous if we're waiting for a "Finished" signal!
|
||||||
bus.GetBus().Signal(ch)
|
bus.GetBus().Signal(ch)
|
||||||
if PK_DEBUG {
|
|
||||||
log.Println("PackageKit: matchSignal(): Success!")
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,11 +405,9 @@ loop:
|
|||||||
// a package was installed...
|
// a package was installed...
|
||||||
// only start the timer once we're here...
|
// only start the timer once we're here...
|
||||||
timeout = PkSignalPackageTimeout
|
timeout = PkSignalPackageTimeout
|
||||||
continue loop
|
|
||||||
} else if signal.Name == FmtTransactionMethod("Finished") {
|
} else if signal.Name == FmtTransactionMethod("Finished") {
|
||||||
finished = true
|
finished = true
|
||||||
timeout = PkSignalDestroyTimeout // wait a bit
|
timeout = PkSignalDestroyTimeout // wait a bit
|
||||||
continue loop
|
|
||||||
} else if signal.Name == FmtTransactionMethod("Destroy") {
|
} else if signal.Name == FmtTransactionMethod("Destroy") {
|
||||||
return nil // success
|
return nil // success
|
||||||
} else {
|
} else {
|
||||||
@@ -508,8 +500,6 @@ loop:
|
|||||||
if signal.Name == FmtTransactionMethod("ErrorCode") {
|
if signal.Name == FmtTransactionMethod("ErrorCode") {
|
||||||
return errors.New(fmt.Sprintf("PackageKit: Error: %v", signal.Body))
|
return errors.New(fmt.Sprintf("PackageKit: Error: %v", signal.Body))
|
||||||
} else if signal.Name == FmtTransactionMethod("Package") {
|
} else if signal.Name == FmtTransactionMethod("Package") {
|
||||||
// a package was installed...
|
|
||||||
continue loop
|
|
||||||
} else if signal.Name == FmtTransactionMethod("Finished") {
|
} else if signal.Name == FmtTransactionMethod("Finished") {
|
||||||
// TODO: should we wait for the Destroy signal?
|
// TODO: should we wait for the Destroy signal?
|
||||||
break loop
|
break loop
|
||||||
@@ -574,8 +564,6 @@ loop:
|
|||||||
continue loop // failed conversion
|
continue loop // failed conversion
|
||||||
}
|
}
|
||||||
files[key] = fileList // build up map
|
files[key] = fileList // build up map
|
||||||
|
|
||||||
continue loop
|
|
||||||
} else if signal.Name == FmtTransactionMethod("Finished") {
|
} else if signal.Name == FmtTransactionMethod("Finished") {
|
||||||
// TODO: should we wait for the Destroy signal?
|
// TODO: should we wait for the Destroy signal?
|
||||||
break loop
|
break loop
|
||||||
@@ -593,6 +581,9 @@ loop:
|
|||||||
|
|
||||||
// get list of packages that are installed and which can be updated, mod filter
|
// get list of packages that are installed and which can be updated, mod filter
|
||||||
func (bus *Conn) GetUpdates(filter uint64) ([]string, error) {
|
func (bus *Conn) GetUpdates(filter uint64) ([]string, error) {
|
||||||
|
if PK_DEBUG {
|
||||||
|
log.Println("PackageKit: GetUpdates()")
|
||||||
|
}
|
||||||
packageIds := []string{}
|
packageIds := []string{}
|
||||||
ch := make(chan *dbus.Signal, PkBufferSize) // we need to buffer :(
|
ch := make(chan *dbus.Signal, PkBufferSize) // we need to buffer :(
|
||||||
interfacePath, err := bus.CreateTransaction()
|
interfacePath, err := bus.CreateTransaction()
|
||||||
@@ -635,7 +626,6 @@ loop:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
packageIds = append(packageIds, packageId)
|
packageIds = append(packageIds, packageId)
|
||||||
|
|
||||||
} else if signal.Name == FmtTransactionMethod("Finished") {
|
} else if signal.Name == FmtTransactionMethod("Finished") {
|
||||||
// TODO: should we wait for the Destroy signal?
|
// TODO: should we wait for the Destroy signal?
|
||||||
break loop
|
break loop
|
||||||
@@ -708,8 +698,9 @@ func (bus *Conn) PackagesToPackageIds(packageMap map[string]string, filter uint6
|
|||||||
return nil, errors.New(fmt.Sprintf("Empty package state for %v", pkg))
|
return nil, errors.New(fmt.Sprintf("Empty package state for %v", pkg))
|
||||||
}
|
}
|
||||||
found[index] = true
|
found[index] = true
|
||||||
|
stateIsVersion := (state != "installed" && state != "uninstalled" && state != "newest") // must be a ver. string
|
||||||
|
|
||||||
if state != "installed" && state != "uninstalled" && state != "newest" { // must be a ver. string
|
if stateIsVersion {
|
||||||
if state == ver && ver != "" { // we match what we want...
|
if state == ver && ver != "" { // we match what we want...
|
||||||
usePackageId[index] = packageId
|
usePackageId[index] = packageId
|
||||||
}
|
}
|
||||||
@@ -718,11 +709,13 @@ func (bus *Conn) PackagesToPackageIds(packageMap map[string]string, filter uint6
|
|||||||
if FlagInData("installed", data) {
|
if FlagInData("installed", data) {
|
||||||
installed[index] = true
|
installed[index] = true
|
||||||
version[index] = ver
|
version[index] = ver
|
||||||
if state == "uninstalled" {
|
// state of "uninstalled" matched during CheckApply, and
|
||||||
|
// states of "installed" and "newest" for fileList
|
||||||
|
if !stateIsVersion {
|
||||||
usePackageId[index] = packageId // save for later
|
usePackageId[index] = packageId // save for later
|
||||||
}
|
}
|
||||||
} else { // not installed...
|
} else { // not installed...
|
||||||
if state == "installed" || state == "newest" {
|
if !stateIsVersion {
|
||||||
// if there is more than one result, eg: there
|
// if there is more than one result, eg: there
|
||||||
// is the old and newest version of a package,
|
// is the old and newest version of a package,
|
||||||
// then this section can run more than once...
|
// then this section can run more than once...
|
||||||
|
|||||||
186
pkg.go
186
pkg.go
@@ -22,15 +22,18 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PkgRes struct {
|
type PkgRes struct {
|
||||||
BaseRes `yaml:",inline"`
|
BaseRes `yaml:",inline"`
|
||||||
State string `yaml:"state"` // state: installed, uninstalled, newest, <version>
|
State string `yaml:"state"` // state: installed, uninstalled, newest, <version>
|
||||||
AllowUntrusted bool `yaml:"allowuntrusted"` // allow untrusted packages to be installed?
|
AllowUntrusted bool `yaml:"allowuntrusted"` // allow untrusted packages to be installed?
|
||||||
AllowNonFree bool `yaml:"allownonfree"` // allow nonfree packages to be found?
|
AllowNonFree bool `yaml:"allownonfree"` // allow nonfree packages to be found?
|
||||||
AllowUnsupported bool `yaml:"allowunsupported"` // allow unsupported packages to be found?
|
AllowUnsupported bool `yaml:"allowunsupported"` // allow unsupported packages to be found?
|
||||||
fileList []string // FIXME: update if pkg changes
|
//bus *Conn // pk bus connection
|
||||||
|
fileList []string // FIXME: update if pkg changes
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper function for creating new pkg resources that calls Init()
|
// helper function for creating new pkg resources that calls Init()
|
||||||
@@ -53,10 +56,35 @@ func NewPkgRes(name, state string, allowuntrusted, allownonfree, allowunsupporte
|
|||||||
func (obj *PkgRes) Init() {
|
func (obj *PkgRes) Init() {
|
||||||
obj.BaseRes.kind = "Pkg"
|
obj.BaseRes.kind = "Pkg"
|
||||||
obj.BaseRes.Init() // call base init, b/c we're overriding
|
obj.BaseRes.Init() // call base init, b/c we're overriding
|
||||||
|
|
||||||
|
bus := NewBus()
|
||||||
|
if bus == nil {
|
||||||
|
log.Fatal("Can't connect to PackageKit bus.")
|
||||||
|
}
|
||||||
|
defer bus.Close()
|
||||||
|
|
||||||
|
data, err := obj.PkgMappingHelper(bus)
|
||||||
|
if err != nil {
|
||||||
|
// FIXME: return error?
|
||||||
|
log.Fatalf("The PkgMappingHelper failed with: %v.", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
packageIds := []string{data.PackageId} // just one for now
|
||||||
|
filesMap, err := bus.GetFilesByPackageId(packageIds)
|
||||||
|
if err != nil {
|
||||||
|
// FIXME: return error?
|
||||||
|
log.Fatalf("Can't run GetFilesByPackageId: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if files, ok := filesMap[data.PackageId]; ok {
|
||||||
|
obj.fileList = DirifyFileList(files, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (obj *PkgRes) Kind() string {
|
// XXX: run this when resource exits
|
||||||
return "Pkg"
|
func (obj *PkgRes) Close() {
|
||||||
|
//obj.bus.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (obj *PkgRes) Validate() bool {
|
func (obj *PkgRes) Validate() bool {
|
||||||
@@ -143,22 +171,7 @@ func (obj *PkgRes) Watch() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (obj *PkgRes) CheckApply(apply bool) (stateok bool, err error) {
|
func (obj *PkgRes) PkgMappingHelper(bus *Conn) (*PkPackageIdActionData, error) {
|
||||||
log.Printf("%v[%v]: CheckApply(%t)", obj.Kind(), obj.GetName(), apply)
|
|
||||||
|
|
||||||
if obj.State == "" { // TODO: Validate() should replace this check!
|
|
||||||
log.Fatalf("%v[%v]: Package state is undefined!", obj.Kind(), obj.GetName())
|
|
||||||
}
|
|
||||||
|
|
||||||
if obj.isStateOK { // cache the state
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
bus := NewBus()
|
|
||||||
if bus == nil {
|
|
||||||
return false, errors.New("Can't connect to PackageKit bus.")
|
|
||||||
}
|
|
||||||
defer bus.Close()
|
|
||||||
|
|
||||||
var packageMap = map[string]string{
|
var packageMap = map[string]string{
|
||||||
obj.Name: obj.State, // key is pkg name, value is pkg state
|
obj.Name: obj.State, // key is pkg name, value is pkg state
|
||||||
@@ -180,16 +193,41 @@ func (obj *PkgRes) CheckApply(apply bool) (stateok bool, err error) {
|
|||||||
}
|
}
|
||||||
result, e := bus.PackagesToPackageIds(packageMap, filter)
|
result, e := bus.PackagesToPackageIds(packageMap, filter)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return false, errors.New(fmt.Sprintf("PackagesToPackageIds error: %v", e))
|
return nil, errors.New(fmt.Sprintf("Can't run PackagesToPackageIds: %v", e))
|
||||||
}
|
}
|
||||||
|
|
||||||
data, ok := result[obj.Name] // lookup single package
|
data, ok := result[obj.Name] // lookup single package
|
||||||
// package doesn't exist, this is an error!
|
// package doesn't exist, this is an error!
|
||||||
if !ok || !data.Found {
|
if !ok || !data.Found {
|
||||||
return false, errors.New(fmt.Sprintf("Can't find package named '%s'.", obj.Name))
|
return nil, errors.New(fmt.Sprintf("Can't find package named '%s'.", obj.Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
//obj.State == "installed" || "uninstalled" || "newest" || "4.2-1.fc23"
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (obj *PkgRes) CheckApply(apply bool) (stateok bool, err error) {
|
||||||
|
log.Printf("%v[%v]: CheckApply(%t)", obj.Kind(), obj.GetName(), apply)
|
||||||
|
|
||||||
|
if obj.State == "" { // TODO: Validate() should replace this check!
|
||||||
|
log.Fatalf("%v[%v]: Package state is undefined!", obj.Kind(), obj.GetName())
|
||||||
|
}
|
||||||
|
|
||||||
|
if obj.isStateOK { // cache the state
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
bus := NewBus()
|
||||||
|
if bus == nil {
|
||||||
|
return false, errors.New("Can't connect to PackageKit bus.")
|
||||||
|
}
|
||||||
|
defer bus.Close()
|
||||||
|
|
||||||
|
data, err := obj.PkgMappingHelper(bus)
|
||||||
|
if err != nil {
|
||||||
|
return false, errors.New(fmt.Sprintf("The PkgMappingHelper failed with: %v.", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// obj.State == "installed" || "uninstalled" || "newest" || "4.2-1.fc23"
|
||||||
switch obj.State {
|
switch obj.State {
|
||||||
case "installed":
|
case "installed":
|
||||||
if data.Installed {
|
if data.Installed {
|
||||||
@@ -248,8 +286,26 @@ func (obj *PkgRes) CheckApply(apply bool) (stateok bool, err error) {
|
|||||||
return false, nil // success
|
return false, nil // success
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PkgUUID struct {
|
||||||
|
BaseUUID
|
||||||
|
name string // pkg name
|
||||||
|
state string // pkg state or "version"
|
||||||
|
}
|
||||||
|
|
||||||
|
// if and only if they are equivalent, return true
|
||||||
|
// if they are not equivalent, return false
|
||||||
|
func (obj *PkgUUID) IFF(uuid ResUUID) bool {
|
||||||
|
res, ok := uuid.(*PkgUUID)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// FIXME: match on obj.state vs. res.state ?
|
||||||
|
return obj.name == res.name
|
||||||
|
}
|
||||||
|
|
||||||
type PkgResAutoEdges struct {
|
type PkgResAutoEdges struct {
|
||||||
fileList []string
|
fileList []string
|
||||||
|
svcUUIDs []ResUUID
|
||||||
testIsNext bool // safety
|
testIsNext bool // safety
|
||||||
name string // saved data from PkgRes obj
|
name string // saved data from PkgRes obj
|
||||||
kind string
|
kind string
|
||||||
@@ -260,8 +316,13 @@ func (obj *PkgResAutoEdges) Next() []ResUUID {
|
|||||||
log.Fatal("Expecting a call to Test()")
|
log.Fatal("Expecting a call to Test()")
|
||||||
}
|
}
|
||||||
obj.testIsNext = true // set after all the errors paths are past
|
obj.testIsNext = true // set after all the errors paths are past
|
||||||
var result []ResUUID
|
|
||||||
|
|
||||||
|
// first return any matching svcUUIDs
|
||||||
|
if x := obj.svcUUIDs; len(x) > 0 {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
var result []ResUUID
|
||||||
// return UUID's for whatever is in obj.fileList
|
// return UUID's for whatever is in obj.fileList
|
||||||
for _, x := range obj.fileList {
|
for _, x := range obj.fileList {
|
||||||
var reversed bool = false // cheat by passing a pointer
|
var reversed bool = false // cheat by passing a pointer
|
||||||
@@ -281,6 +342,17 @@ func (obj *PkgResAutoEdges) Test(input []bool) bool {
|
|||||||
if !obj.testIsNext {
|
if !obj.testIsNext {
|
||||||
log.Fatal("Expecting a call to Next()")
|
log.Fatal("Expecting a call to Next()")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ack the svcUUID's...
|
||||||
|
if x := obj.svcUUIDs; len(x) > 0 {
|
||||||
|
if y := len(x); y != len(input) {
|
||||||
|
log.Fatalf("Expecting %d value(s)!", y)
|
||||||
|
}
|
||||||
|
obj.svcUUIDs = []ResUUID{} // empty
|
||||||
|
obj.testIsNext = false
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
count := len(obj.fileList)
|
count := len(obj.fileList)
|
||||||
if count != len(input) {
|
if count != len(input) {
|
||||||
log.Fatalf("Expecting %d value(s)!", count)
|
log.Fatalf("Expecting %d value(s)!", count)
|
||||||
@@ -316,27 +388,29 @@ func (obj *PkgResAutoEdges) Test(input []bool) bool {
|
|||||||
return true // continue, there are more files!
|
return true // continue, there are more files!
|
||||||
}
|
}
|
||||||
|
|
||||||
type PkgUUID struct {
|
|
||||||
BaseUUID
|
|
||||||
}
|
|
||||||
|
|
||||||
// if and only if they are equivalent, return true
|
|
||||||
// if they are not equivalent, return false
|
|
||||||
func (obj *PkgUUID) IFF(uuid ResUUID) bool {
|
|
||||||
res, ok := uuid.(*PkgUUID)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return obj.name == res.name
|
|
||||||
}
|
|
||||||
|
|
||||||
// produce an object which generates a minimal pkg file optimization sequence
|
// produce an object which generates a minimal pkg file optimization sequence
|
||||||
func (obj *PkgRes) AutoEdges() AutoEdge {
|
func (obj *PkgRes) AutoEdges() AutoEdge {
|
||||||
// in contrast with the FileRes AutoEdges() function which contains
|
// in contrast with the FileRes AutoEdges() function which contains
|
||||||
// more of the mechanics, most of the AutoEdge mechanics for the PkgRes
|
// more of the mechanics, most of the AutoEdge mechanics for the PkgRes
|
||||||
// is contained in the Test() method! This design is completely okay!
|
// is contained in the Test() method! This design is completely okay!
|
||||||
|
|
||||||
|
// add matches for any svc resources found in pkg definition!
|
||||||
|
var svcUUIDs []ResUUID
|
||||||
|
for _, x := range ReturnSvcInFileList(obj.fileList) {
|
||||||
|
var reversed bool = false
|
||||||
|
svcUUIDs = append(svcUUIDs, &SvcUUID{
|
||||||
|
BaseUUID: BaseUUID{
|
||||||
|
name: obj.GetName(),
|
||||||
|
kind: obj.Kind(),
|
||||||
|
reversed: &reversed,
|
||||||
|
},
|
||||||
|
name: x, // the svc name itself in the SvcUUID object!
|
||||||
|
}) // build list
|
||||||
|
}
|
||||||
|
|
||||||
return &PkgResAutoEdges{
|
return &PkgResAutoEdges{
|
||||||
fileList: obj.fileList,
|
fileList: RemoveCommonFilePrefixes(obj.fileList), // clean start!
|
||||||
|
svcUUIDs: svcUUIDs,
|
||||||
testIsNext: false, // start with Next() call
|
testIsNext: false, // start with Next() call
|
||||||
name: obj.GetName(), // save data for PkgResAutoEdges obj
|
name: obj.GetName(), // save data for PkgResAutoEdges obj
|
||||||
kind: obj.Kind(),
|
kind: obj.Kind(),
|
||||||
@@ -347,15 +421,10 @@ func (obj *PkgRes) AutoEdges() AutoEdge {
|
|||||||
func (obj *PkgRes) GetUUIDs() []ResUUID {
|
func (obj *PkgRes) GetUUIDs() []ResUUID {
|
||||||
x := &PkgUUID{
|
x := &PkgUUID{
|
||||||
BaseUUID: BaseUUID{name: obj.GetName(), kind: obj.Kind()},
|
BaseUUID: BaseUUID{name: obj.GetName(), kind: obj.Kind()},
|
||||||
|
name: obj.Name,
|
||||||
|
state: obj.State,
|
||||||
}
|
}
|
||||||
result := []ResUUID{x}
|
result := []ResUUID{x}
|
||||||
for _, path := range obj.fileList {
|
|
||||||
x := &FileUUID{
|
|
||||||
BaseUUID: BaseUUID{name: obj.GetName(), kind: obj.Kind()},
|
|
||||||
path: path,
|
|
||||||
}
|
|
||||||
result = append(result, x)
|
|
||||||
}
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,3 +452,22 @@ func (obj *PkgRes) Compare(res Res) bool {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return a list of svc names for matches like /usr/lib/systemd/system/*.service
|
||||||
|
func ReturnSvcInFileList(fileList []string) []string {
|
||||||
|
result := []string{}
|
||||||
|
for _, x := range fileList {
|
||||||
|
dirname, basename := path.Split(path.Clean(x))
|
||||||
|
// TODO: do we also want to look for /etc/systemd/system/ ?
|
||||||
|
if dirname != "/usr/lib/systemd/system/" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !strings.HasSuffix(basename, ".service") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if s := strings.TrimSuffix(basename, ".service"); !StrInList(s, result) {
|
||||||
|
result = append(result, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ type ResUUID interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type BaseUUID struct {
|
type BaseUUID struct {
|
||||||
name string
|
name string // name and kind are the values of where this is coming from
|
||||||
kind string
|
kind string
|
||||||
|
|
||||||
reversed *bool // piggyback edge information here
|
reversed *bool // piggyback edge information here
|
||||||
@@ -467,6 +467,7 @@ func (obj *NoopRes) CheckApply(apply bool) (stateok bool, err error) {
|
|||||||
|
|
||||||
type NoopUUID struct {
|
type NoopUUID struct {
|
||||||
BaseUUID
|
BaseUUID
|
||||||
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (obj *NoopRes) AutoEdges() AutoEdge {
|
func (obj *NoopRes) AutoEdges() AutoEdge {
|
||||||
@@ -474,10 +475,11 @@ func (obj *NoopRes) AutoEdges() AutoEdge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// include all params to make a unique identification of this object
|
// include all params to make a unique identification of this object
|
||||||
// most resources only return one
|
// most resources only return one, although some resources return multiple
|
||||||
func (obj *NoopRes) GetUUIDs() []ResUUID {
|
func (obj *NoopRes) GetUUIDs() []ResUUID {
|
||||||
x := &NoopUUID{
|
x := &NoopUUID{
|
||||||
BaseUUID: BaseUUID{name: obj.GetName(), kind: obj.Kind()},
|
BaseUUID: BaseUUID{name: obj.GetName(), kind: obj.Kind()},
|
||||||
|
name: obj.Name,
|
||||||
}
|
}
|
||||||
return []ResUUID{x}
|
return []ResUUID{x}
|
||||||
}
|
}
|
||||||
|
|||||||
72
svc.go
72
svc.go
@@ -310,7 +310,12 @@ func (obj *SvcRes) CheckApply(apply bool) (stateok bool, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SvcUUID struct {
|
type SvcUUID struct {
|
||||||
|
// NOTE: there is also a name variable in the BaseUUID struct, this is
|
||||||
|
// information about where this UUID came from, and is unrelated to the
|
||||||
|
// information about the resource we're matching. That data which is
|
||||||
|
// used in the IFF function, is what you see in the struct fields here.
|
||||||
BaseUUID
|
BaseUUID
|
||||||
|
name string // the svc name
|
||||||
}
|
}
|
||||||
|
|
||||||
// if and only if they are equivalent, return true
|
// if and only if they are equivalent, return true
|
||||||
@@ -323,17 +328,74 @@ func (obj *SvcUUID) IFF(uuid ResUUID) bool {
|
|||||||
return obj.name == res.name
|
return obj.name == res.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SvcResAutoEdges struct {
|
||||||
|
data []ResUUID
|
||||||
|
pointer int
|
||||||
|
found bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (obj *SvcResAutoEdges) Next() []ResUUID {
|
||||||
|
if obj.found {
|
||||||
|
log.Fatal("Shouldn't be called anymore!")
|
||||||
|
}
|
||||||
|
if len(obj.data) == 0 { // check length for rare scenarios
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value := obj.data[obj.pointer]
|
||||||
|
obj.pointer += 1
|
||||||
|
return []ResUUID{value} // we return one, even though api supports N
|
||||||
|
}
|
||||||
|
|
||||||
|
// get results of the earlier Next() call, return if we should continue!
|
||||||
|
func (obj *SvcResAutoEdges) Test(input []bool) bool {
|
||||||
|
// if there aren't any more remaining
|
||||||
|
if len(obj.data) <= obj.pointer {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if obj.found { // already found, done!
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(input) != 1 { // in case we get given bad data
|
||||||
|
log.Fatal("Expecting a single value!")
|
||||||
|
}
|
||||||
|
if input[0] { // if a match is found, we're done!
|
||||||
|
obj.found = true // no more to find!
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true // keep going
|
||||||
|
}
|
||||||
|
|
||||||
func (obj *SvcRes) AutoEdges() AutoEdge {
|
func (obj *SvcRes) AutoEdges() AutoEdge {
|
||||||
// TODO: add auto edges to the files that provide the service files,
|
var data []ResUUID
|
||||||
// which might come from a pkg resource perhaps!
|
svcFiles := []string{
|
||||||
return nil
|
fmt.Sprintf("/etc/systemd/system/%s.service", obj.Name), // takes precedence
|
||||||
|
fmt.Sprintf("/usr/lib/systemd/system/%s.service", obj.Name), // pkg default
|
||||||
|
}
|
||||||
|
for _, x := range svcFiles {
|
||||||
|
var reversed bool = true
|
||||||
|
data = append(data, &FileUUID{
|
||||||
|
BaseUUID: BaseUUID{
|
||||||
|
name: obj.GetName(),
|
||||||
|
kind: obj.Kind(),
|
||||||
|
reversed: &reversed,
|
||||||
|
},
|
||||||
|
path: x, // what matters
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return &FileResAutoEdges{
|
||||||
|
data: data,
|
||||||
|
pointer: 0,
|
||||||
|
found: false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// include all params to make a unique identification of this object
|
// include all params to make a unique identification of this object
|
||||||
func (obj *SvcRes) GetUUIDs() []ResUUID {
|
func (obj *SvcRes) GetUUIDs() []ResUUID {
|
||||||
x := &SvcUUID{BaseUUID: BaseUUID{name: obj.GetName(), kind: obj.Kind()}}
|
x := &SvcUUID{
|
||||||
|
BaseUUID: BaseUUID{name: obj.GetName(), kind: obj.Kind()},
|
||||||
|
name: obj.Name, // svc name
|
||||||
|
}
|
||||||
return []ResUUID{x}
|
return []ResUUID{x}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (obj *SvcRes) Compare(res Res) bool {
|
func (obj *SvcRes) Compare(res Res) bool {
|
||||||
|
|||||||
Reference in New Issue
Block a user