mgmt
mgmt copied to clipboard
Using a version string for package state does not work
Versions:
-
mgmt version (eg:
mgmt --version):mgmt version 0.0.17-36-gb449be8 -
operating system/distribution (eg:
uname -a):Linux ubuntu-bionic 4.15.0-45-generic #48-Ubuntu SMP Tue Jan 29 16:28:13 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux -
golang version (eg:
go version):go version go1.10.4 linux/amd64
Description:
Attempting to use a version string for the pkg state doesn't work, at least not on the Ubuntu (Xenial & Bionic) systems I've tried it on. For example:
# Any one of:
#
# 2.4.29-1ubuntu4.5
# 2.4.29-1ubuntu4.4
# 2.4.29-1ubuntu4
$apache_version = "2.4.29-1ubuntu4"
pkg "apache2" {
state => $apache_version,
}
$ sudo ./mgmt run --tmp-prefix lang --lang ./package.mcl
2019-02-06 16:16:51.223986 I | cli: lang: lexing/parsing...
2019-02-06 16:16:51.227637 I | cli: lang: init...
2019-02-06 16:16:51.227664 I | cli: lang: interpolating...
2019-02-06 16:16:51.227694 I | cli: lang: building scope...
2019-02-06 16:16:51.227706 I | cli: lang: running type unification...
2019-02-06 16:16:51.227807 I | cli: lang: input: ./package.mcl
2019-02-06 16:16:51.227825 I | cli: lang: tree:
.
├── metadata.yaml
└── package.mcl
16:16:51 hello.go:49: this is: mgmt, version: 0.0.17-36-gb449be8
16:16:51 hello.go:50: main: start: 1549469811227840515
...
16:16:53 main.go:492: gapi: lang: loop...
16:16:53 main.go:492: gapi: lang: funcs: func `str(2.4.29-1ubuntu4)` started
16:16:53 main.go:492: gapi: lang: funcs: func `str(2.4.29-1ubuntu4)` changed
16:16:53 main.go:492: gapi: lang: funcs: func `str(2.4.29-1ubuntu4)` stopped
16:16:53 main.go:492: gapi: lang: funcs: func `str(apache2)` started
16:16:53 main.go:492: gapi: lang: funcs: func `str(apache2)` changed
16:16:53 main.go:492: gapi: lang: funcs: func `str(apache2)` stopped
16:16:53 main.go:492: gapi: lang: funcs: func `var(apache_version)` started
16:16:53 main.go:492: gapi: lang: funcs: func `var(apache_version)` changed
16:16:53 main.go:492: gapi: lang: funcs: func `var(apache_version)` stopped
16:16:53 main.go:492: gapi: generating new graph...
16:16:53 main.go:492: gapi: lang: running interpret...
16:16:53 main.go:410: engine: autoedge: adding autoedges...
16:16:54 main.go:191: main: error running auto edges: 1 error occurred:
* error populating file list for automatic edges: empty PackageID found for 'apache2'
the auto edges had errors
github.com/purpleidea/mgmt/engine/graph/autoedge.AutoEdge
/home/vagrant/gopath/src/github.com/purpleidea/mgmt/engine/graph/autoedge/autoedge.go:62
github.com/purpleidea/mgmt/engine/graph.(*Engine).AutoEdge
/home/vagrant/gopath/src/github.com/purpleidea/mgmt/engine/graph/autoedge.go:29
github.com/purpleidea/mgmt/lib.(*Main).Run.func10
/home/vagrant/gopath/src/github.com/purpleidea/mgmt/lib/main.go:599
runtime.goexit
/usr/lib/go-1.10/src/runtime/asm_amd64.s:2361
16:16:54 main.go:191: main: waiting...
I've been trying to hack around this today but there's a whole bunch of places in both pkg.go & packagekit.go that seem to deal with package states, and I clearly don't understand the code well enough to make this work: I've got as far as a version that runs but doesn't install the correct package version (It just installs the latest available) I'll attach my terrible ugly diff for that to this issue, complete with my debugging output and some additional changes.
index 2ec3dfc..53f9174 100644
--- a/engine/resources/packagekit/packagekit.go
+++ b/engine/resources/packagekit/packagekit.go
@@ -171,8 +171,13 @@ func NewBus() *Conn {
if err != nil {
return nil
}
+ logf := func(format string, v ...interface{}) {
+ fmt.Printf(format+"\n", v...)
+ }
return &Conn{
conn: bus,
+ Debug: true,
+ Logf: logf,
}
}
@@ -311,9 +316,11 @@ func (obj *Conn) ResolvePackages(packages []string, filter uint64) ([]string, er
defer removeSignals()
if obj.Debug {
obj.Logf("ResolvePackages(): Object(%s, %v)", PkIface, interfacePath)
+ obj.Logf("ResolvePackages(): %d", filter)
}
bus := obj.GetBus().Object(PkIface, interfacePath) // pass in found transaction path
- call := bus.Call(FmtTransactionMethod("Resolve"), 0, filter, packages)
+ //call := bus.Call(FmtTransactionMethod("Resolve"), 0, filter, packages)
+ call := bus.Call(FmtTransactionMethod("Resolve"), 0, uint64(0), packages)
if obj.Debug {
obj.Logf("ResolvePackages(): Call: Success!")
}
@@ -591,6 +598,7 @@ func (obj *Conn) GetFilesByPackageID(packageIDs []string) (files map[string][]st
return
}
files = make(map[string][]string)
+ fmt.Println(files)
loop:
for {
// FIXME: add a timeout option to error in case signals are dropped!
@@ -713,9 +721,9 @@ func (obj *Conn) PackagesToPackageIDs(packageMap map[string]string, filter uint6
count++
}
- if !(filter&PkFilterEnumArch == PkFilterEnumArch) {
- filter += PkFilterEnumArch // always search in our arch
- }
+ //if !(filter&PkFilterEnumArch == PkFilterEnumArch) {
+ // filter += PkFilterEnumArch // always search in our arch
+ //}
if obj.Debug {
obj.Logf("PackagesToPackageIDs(): %s", strings.Join(packages, ", "))
@@ -724,7 +732,9 @@ func (obj *Conn) PackagesToPackageIDs(packageMap map[string]string, filter uint6
if e != nil {
return nil, fmt.Errorf("Resolve error: %v", e)
}
-
+ if obj.Debug {
+ obj.Logf("PackagesToPackageIDs(): %s", resolved)
+ }
found := make([]bool, count) // default false
installed := make([]bool, count)
version := make([]string, count)
@@ -737,7 +747,7 @@ func (obj *Conn) PackagesToPackageIDs(packageMap map[string]string, filter uint6
for _, packageID := range resolved {
index = -1
- //obj.Logf("* %v", packageID)
+ obj.Logf("* %v", packageID)
// format is: name;version;arch;data
s := strings.Split(packageID, ";")
//if len(s) != 4 { continue } // this would be a bug!
@@ -764,10 +774,16 @@ func (obj *Conn) PackagesToPackageIDs(packageMap map[string]string, filter uint6
}
found[index] = true
stateIsVersion := (state != "installed" && state != "uninstalled" && state != "newest") // must be a ver. string
-
+ fmt.Printf("stateIsVersion=%t (%s)\n", stateIsVersion, state)
if stateIsVersion {
+ fmt.Printf("state=%s ver=%s\n", state, ver)
if state == ver && ver != "" { // we match what we want...
usePackageID[index] = packageID
+ fmt.Printf("Matched version (%s)\n", ver)
+ } else {
+ usePackageID[index] = packageID
+ version[index] = state
+ installed[index] = false
}
}
@@ -818,6 +834,7 @@ func (obj *Conn) PackagesToPackageIDs(packageMap map[string]string, filter uint6
}
}
}
+ fmt.Printf("usePackageID=%v\n", usePackageID)
// skip if the "newest" filter was used, otherwise we might need fixing
// this check is for packages that need to verify their "newest" status
@@ -873,6 +890,8 @@ func (obj *Conn) PackagesToPackageIDs(packageMap map[string]string, filter uint6
Newest: newest[index],
}
}
+ fmt.Printf("pkg(%s)\n", pkg)
+ fmt.Printf("%+v\n", result[pkg])
}
return result, nil
@@ -885,7 +904,7 @@ func FilterPackageIDs(m map[string]*PkPackageIDActionData, packages []string) ([
p, ok := m[k] // lookup single package
// package doesn't exist, this is an error!
if !ok || !p.Found || p.PackageID == "" {
- return nil, fmt.Errorf("can't find package named '%s'", k)
+ return nil, fmt.Errorf("FilterPackageIDs: can't find package named '%s'", k)
}
result = append(result, p.PackageID)
}
@@ -900,7 +919,7 @@ func FilterState(m map[string]*PkPackageIDActionData, packages []string, state s
p, ok := m[k] // lookup single package
// package doesn't exist, this is an error!
if !ok || !p.Found {
- return nil, fmt.Errorf("can't find package named '%s'", k)
+ return nil, fmt.Errorf("FilterState: can't find package named '%s'", k)
}
var b bool
if state == "installed" {
@@ -929,7 +948,7 @@ func FilterPackageState(m map[string]*PkPackageIDActionData, packages []string,
p, ok := m[k] // lookup single package
// package doesn't exist, this is an error!
if !ok || !p.Found {
- return nil, fmt.Errorf("can't find package named '%s'", k)
+ return nil, fmt.Errorf("FilterPackageState: can't find package named '%s'", k)
}
b := false
if state == "installed" && p.Installed {
diff --git a/engine/resources/pkg.go b/engine/resources/pkg.go
index 33a8726..30819f6 100644
--- a/engine/resources/pkg.go
+++ b/engine/resources/pkg.go
@@ -222,7 +222,8 @@ func (obj *PkgRes) pkgMappingHelper(bus *packagekit.Conn) (map[string]*packageki
if !obj.AllowUnsupported {
filter += packagekit.PkFilterEnumSupported
}
- result, err := bus.PackagesToPackageIDs(packageMap, filter)
+ //result, err := bus.PackagesToPackageIDs(packageMap, filter)
+ result, err := bus.PackagesToPackageIDs(packageMap, uint64(0))
if err != nil {
return nil, errwrap.Wrapf(err, "can't run PackagesToPackageIDs")
}
@@ -253,7 +254,7 @@ func (obj *PkgRes) populateFileList() error {
data, ok := result[obj.Name()] // lookup single package (init does just one)
// package doesn't exist, this is an error!
if !ok || !data.Found {
- return fmt.Errorf("can't find package named '%s'", obj.Name())
+ return fmt.Errorf("pkg: can't find package named '%s'", obj.Name())
}
if data.PackageID == "" {
// this can happen if you specify a bad version like "latest"
@@ -298,14 +299,7 @@ func (obj *PkgRes) CheckApply(apply bool) (checkOK bool, err error) {
//stateList := []string{obj.State}
//stateList = append(stateList, util.StrMapValues(packageMap)...)
- // TODO: at the moment, all the states are the same, but
- // eventually we might be able to drop this constraint!
- states, err := packagekit.FilterState(result, packageList, obj.State)
- if err != nil {
- return false, errwrap.Wrapf(err, "the FilterState method failed")
- }
data, _ := result[obj.Name()] // if above didn't error, we won't either!
- validState := util.BoolMapTrue(util.BoolMapValues(states))
// obj.State == PkgStateInstalled || PkgStateUninstalled || PkgStateNewest || "4.2-1.fc23"
switch obj.State {
@@ -314,6 +308,14 @@ func (obj *PkgRes) CheckApply(apply bool) (checkOK bool, err error) {
case PkgStateUninstalled:
fallthrough
case PkgStateNewest:
+ // TODO: at the moment, all the states are the same, but
+ // eventually we might be able to drop this constraint!
+ states, err := packagekit.FilterState(result, packageList, obj.State)
+ if err != nil {
+ return false, errwrap.Wrapf(err, "the FilterState method failed for State %s", obj.State)
+ }
+ validState := util.BoolMapTrue(util.BoolMapValues(states))
+
if validState {
return true, nil // state is correct, exit!
}
@@ -332,6 +334,7 @@ func (obj *PkgRes) CheckApply(apply bool) (checkOK bool, err error) {
obj.init.Logf("Apply: %s", obj.fmtNames(obj.getNames()))
readyPackages, err := packagekit.FilterPackageState(result, packageList, obj.State)
if err != nil {
+ obj.init.Logf("Apply: FilterPackageState failed")
return false, err // fail
}
// these are the packages that actually need their states applied!
@@ -356,7 +359,8 @@ func (obj *PkgRes) CheckApply(apply bool) (checkOK bool, err error) {
case PkgStateInstalled:
fallthrough // same method as for "set specific version", below
default: // version string
- err = bus.InstallPackages(packageIDs, transactionFlags)
+ //err = bus.InstallPackages(packageIDs, transactionFlags)
+ err = bus.InstallPackages(packageIDs, uint64(0))
}
if err != nil {
return false, err // fail```
There was another casual report that showed some recent issues with pkg on Ubuntu... I am wondering if something changed in packagekit which broke this for you?
@Vanders Can you please try adding this line:
allowunsupported => true,
Inside the pkg resource and tell me if it fixes the problem?
Can you also confirm which repo the apache2 package is in?
Eg:
$apache_version = "2.4.29-1ubuntu4"
pkg "apache2" {
state => $apache_version,
allowunsupported => true,
}
Apparently on Ubuntu anything that's not in the main repo is considered "unsupported" by packagekit, so we need to tell it to allow other repos. We can consider making this the default if need be, or at least making the error message more clear, if this confirms the problem.
This looks like it's a different issue
Apache2 is in main on ubuntu:
Beschikbaar apache2-2.4.38-2ubuntu2.amd64 (ubuntu-disco-main) Apache HTTP Server
The error coming out of packagekit is also different: it's complaining about a missing packageID, while it is complaining about a missing package if you try to install an unsupported package without that option.