On Tue, Oct 18, 2016 at 07:58:00AM +0200, Patrik Lundin wrote:
> On Tue, Oct 18, 2016 at 06:30:41AM +0200, Jasper Lievisse Adriaanse wrote:
> >
> > I was hoping that 2.2.0.0 would be released soon, but it seems upstream 
> > enjoys
> > many a rc over a lengthy period of time. So perhaps syncing the openbsd_pkg
> > provider with master would be the way to go.
> > 
> 
> This would be my personal preference. This also means the local addition
> of -z comes into question as the upstream changes replace "pkg_info -e"
> with "pkg_info -Iq" for looking up package state, which does not handle
> name lookups in the same way.
> 
> I believe landry@ should be involved in this decision because from what I
> recall he is one of the people who wanted the addition (and might be depending
> on it).
> 
> I'll repeat my original thoughts about this from when I added the branch
> support:
> ===
> I should add that I think the -z addition may actually work worse on the
> latest code, because i switched the usage of "pkg_info -e" to "pkg_info
> -Iq inst:name" for finding out the state of a requested package. While
> -e manages to find a package without the patchlevel version attached
> (which i believe was a benefit that -z added), this does not
> seem to be true for "-Iq inst:".
> 
> This could mean that the module will always think that the package
> needs to be installed because it can't tell there is a package with the
> supplied name (plus patchlevel) already installed.
> ===
> 
> -- 
> Patrik Lundin
I think part of the reason why -z was added was precisely to "workaround" the
problem that was resolved with the support for branch notation. So this diff
below is a sync with upstream devel as of right now, which is due to be
released as part of ansible 2.2.0.0, and thus drops our local -z patch.

Index: Makefile
===================================================================
RCS file: /cvs/ports/sysutils/ansible/Makefile,v
retrieving revision 1.62
diff -u -p -r1.62 Makefile
--- Makefile    15 Oct 2016 09:04:36 -0000      1.62
+++ Makefile    18 Oct 2016 18:11:05 -0000
@@ -4,7 +4,7 @@ COMMENT =               ssh based config management f
 
 MODPY_EGG_VERSION =    2.1.2.0
 DISTNAME =             ansible-${MODPY_EGG_VERSION}
-REVISION =             3
+REVISION =             4
 
 CATEGORIES =           sysutils
 
Index: patches/patch-lib_ansible_modules_extras_packaging_os_openbsd_pkg_py
===================================================================
RCS file: 
/cvs/ports/sysutils/ansible/patches/patch-lib_ansible_modules_extras_packaging_os_openbsd_pkg_py,v
retrieving revision 1.5
diff -u -p -r1.5 patch-lib_ansible_modules_extras_packaging_os_openbsd_pkg_py
--- patches/patch-lib_ansible_modules_extras_packaging_os_openbsd_pkg_py        
15 Oct 2016 08:33:52 -0000      1.5
+++ patches/patch-lib_ansible_modules_extras_packaging_os_openbsd_pkg_py        
18 Oct 2016 18:11:05 -0000
@@ -1,32 +1,107 @@
 $OpenBSD: patch-lib_ansible_modules_extras_packaging_os_openbsd_pkg_py,v 1.5 
2016/10/15 08:33:52 jasper Exp $
 
-Hunks 3+4:
-From 2001172027e339037adaa290e77a7700c818ad57 Mon Sep 17 00:00:00 2001
-From: Patrik Lundin <pat...@sigterm.se>
-Date: Wed, 12 Oct 2016 20:51:22 +0200
-Subject: [PATCH 1/2] openbsd_pkg: Use correct part of name in match.
+sync with upstream revision 16b8128
 
---- lib/ansible/modules/extras/packaging/os/openbsd_pkg.py.orig        Fri Oct 
14 14:30:50 2016
-+++ lib/ansible/modules/extras/packaging/os/openbsd_pkg.py     Fri Oct 14 
14:30:40 2016
-@@ -144,7 +144,7 @@ def package_present(name, installed_state, pkg_spec, m
-     build = module.params['build']
- 
-     if module.check_mode:
--        install_cmd = 'pkg_add -Imn'
-+        install_cmd = 'pkg_add -Imnz'
-     else:
-         if build is True:
-             port_dir = "%s/%s" % (module.params['ports_dir'], 
get_package_source_path(name, pkg_spec, module))
-@@ -159,7 +159,7 @@ def package_present(name, installed_state, pkg_spec, m
-             else:
-                 module.fail_json(msg="the port source directory %s does not 
exist" % (port_dir))
-         else:
--            install_cmd = 'pkg_add -Im'
-+            install_cmd = 'pkg_add -Imz'
+--- lib/ansible/modules/extras/packaging/os/openbsd_pkg.py.orig        Thu Sep 
29 17:01:33 2016
++++ lib/ansible/modules/extras/packaging/os/openbsd_pkg.py     Tue Oct 18 
20:09:30 2016
+@@ -19,10 +19,13 @@
+ # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
+ 
+ import os
++import platform
+ import re
+ import shlex
+ import sqlite3
+ 
++from distutils.version import StrictVersion
++
+ DOCUMENTATION = '''
+ ---
+ module: openbsd_pkg
+@@ -82,6 +85,9 @@ EXAMPLES = '''
+ # Specify the default flavour to avoid ambiguity errors
+ - openbsd_pkg: name=vim-- state=present
+ 
++# Specify a package branch (requires at least OpenBSD 6.0)
++- openbsd_pkg: name=python%3.5 state=present
++
+ # Update all packages on the system
+ - openbsd_pkg: name=* state=latest
+ '''
+@@ -94,47 +100,22 @@ def execute_command(cmd, module):
+     cmd_args = shlex.split(cmd)
+     return module.run_command(cmd_args)
+ 
+-# Function used for getting the name of a currently installed package.
+-def get_current_name(name, pkg_spec, module):
+-    info_cmd = 'pkg_info'
+-    (rc, stdout, stderr) = execute_command("%s" % (info_cmd), module)
+-    if rc != 0:
+-        return (rc, stdout, stderr)
+-
+-    if pkg_spec['version']:
+-        pattern = "^%s" % name
+-    elif pkg_spec['flavor']:
+-        pattern = "^%s-.*-%s\s" % (pkg_spec['stem'], pkg_spec['flavor'])
+-    else:
+-        pattern = "^%s-" % pkg_spec['stem']
+-
+-    module.debug("get_current_name(): pattern = %s" % pattern)
+-
+-    for line in stdout.splitlines():
+-        module.debug("get_current_name: line = %s" % line)
+-        match = re.search(pattern, line)
+-        if match:
+-            current_name = line.split()[0]
+-
+-    return current_name
+-
+ # Function used to find out if a package is currently installed.
+ def get_package_state(name, pkg_spec, module):
+-    info_cmd = 'pkg_info -e'
++    info_cmd = 'pkg_info -Iq'
+ 
+-    if pkg_spec['version']:
+-        command = "%s %s" % (info_cmd, name)
+-    elif pkg_spec['flavor']:
+-        command = "%s %s-*-%s" % (info_cmd, pkg_spec['stem'], 
pkg_spec['flavor'])
+-    else:
+-        command = "%s %s-*" % (info_cmd, pkg_spec['stem'])
++    command = "%s inst:%s" % (info_cmd, name)
  
-     if installed_state is False:
+     rc, stdout, stderr = execute_command(command, module)
  
-@@ -189,11 +189,14 @@ def package_present(name, installed_state, pkg_spec, m
+-    if (stderr):
++    if stderr:
+         module.fail_json(msg="failed in get_package_state(): " + stderr)
+ 
+-    if rc == 0:
++    if stdout:
++        # If the requested package name is just a stem, like "python", we may
++        # find multiple packages with that name.
++        pkg_spec['installed_names'] = [name for name in stdout.splitlines()]
++        module.debug("get_package_state(): installed_names = %s" % 
pkg_spec['installed_names'])
+         return True
+     else:
+         return False
+@@ -173,8 +154,14 @@ def package_present(name, installed_state, pkg_spec, m
+         # specific version is supplied or not.
+         #
+         # When a specific version is supplied the return code will be 0 when
+-        # a package is found and 1 when it is not, if a version is not
+-        # supplied the tool will exit 0 in both cases:
++        # a package is found and 1 when it is not. If a version is not
++        # supplied the tool will exit 0 in both cases.
++        #
++        # It is important to note that "version" relates to the
++        # packages-specs(7) notion of a version. If using the branch syntax
++        # (like "python%3.5") the version number is considered part of the
++        # stem, and the pkg_add behavior behaves the same as if the name did
++        # not contain a version (which it strictly speaking does not).
+         if pkg_spec['version'] or build is True:
+             # Depend on the return code.
+             module.debug("package_present(): depending on return code")
+@@ -189,11 +176,14 @@ def package_present(name, installed_state, pkg_spec, m
                  # "file:/local/package/directory/ is empty" message on stderr
                  # while still installing the package, so we need to look for
                  # for a message like "packagename-1.0: ok" just in case.
@@ -44,14 +119,167 @@ Subject: [PATCH 1/2] openbsd_pkg: Use co
                  else:
                      # We really did fail, fake the return code.
                      module.debug("package_present(): we really did fail")
-@@ -349,6 +352,10 @@ def parse_package_name(name, pkg_spec, module):
+@@ -231,25 +221,23 @@ def package_latest(name, installed_state, pkg_spec, mo
+ 
+     if installed_state is True:
+ 
+-        # Fetch name of currently installed package.
+-        pre_upgrade_name = get_current_name(name, pkg_spec, module)
+-
+-        module.debug("package_latest(): pre_upgrade_name = %s" % 
pre_upgrade_name)
+-
+         # Attempt to upgrade the package.
+         (rc, stdout, stderr) = execute_command("%s %s" % (upgrade_cmd, name), 
module)
+ 
+         # Look for output looking something like "nmap-6.01->6.25: ok" to see 
if
+         # something changed (or would have changed). Use \W to delimit the 
match
+         # from progress meter output.
+-        match = re.search("\W%s->.+: ok\W" % pre_upgrade_name, stdout)
+-        if match:
+-            if module.check_mode:
+-                module.exit_json(changed=True)
++        changed = False
++        for installed_name in pkg_spec['installed_names']:
++            module.debug("package_latest(): checking for pre-upgrade package 
name: %s" % installed_name)
++            match = re.search("\W%s->.+: ok\W" % installed_name, stdout)
++            if match:
++                module.debug("package_latest(): pre-upgrade package name 
match: %s" % installed_name)
++                if module.check_mode:
++                    module.exit_json(changed=True)
+ 
+-            changed = True
+-        else:
+-            changed = False
++                changed = True
++                break
+ 
+         # FIXME: This part is problematic. Based on the issues mentioned (and
+         # handled) in package_present() it is not safe to blindly trust stderr
+@@ -301,7 +289,12 @@ def package_absent(name, installed_state, module):
+ 
+ # Function used to parse the package name based on packages-specs(7).
+ # The general name structure is "stem-version[-flavors]".
++#
++# Names containing "%" are a special variation not part of the
++# packages-specs(7) syntax. See pkg_add(1) on OpenBSD 6.0 or later for a
++# description.
+ def parse_package_name(name, pkg_spec, module):
++    module.debug("parse_package_name(): parsing name: %s" % name)
+     # Do some initial matches so we can base the more advanced regex on that.
+     version_match = re.search("-[0-9]", name)
+     versionless_match = re.search("--", name)
+@@ -309,7 +302,7 @@ def parse_package_name(name, pkg_spec, module):
+     # Stop if someone is giving us a name that both has a version and is
+     # version-less at the same time.
+     if version_match and versionless_match:
+-        module.fail_json(msg="Package name both has a version and is 
version-less: " + name)
++        module.fail_json(msg="package name both has a version and is 
version-less: " + name)
+ 
+     # If name includes a version.
+     if version_match:
+@@ -322,7 +315,7 @@ def parse_package_name(name, pkg_spec, module):
+             pkg_spec['flavor']            = match.group('flavor')
+             pkg_spec['style']             = 'version'
+         else:
+-            module.fail_json(msg="Unable to parse package name at 
version_match: " + name)
++            module.fail_json(msg="unable to parse package name at 
version_match: " + name)
+ 
+     # If name includes no version but is version-less ("--").
+     elif versionless_match:
+@@ -335,7 +328,7 @@ def parse_package_name(name, pkg_spec, module):
+             pkg_spec['flavor']            = match.group('flavor')
+             pkg_spec['style']             = 'versionless'
+         else:
+-            module.fail_json(msg="Unable to parse package name at 
versionless_match: " + name)
++            module.fail_json(msg="unable to parse package name at 
versionless_match: " + name)
+ 
+     # If name includes no version, and is not version-less, it is all a stem.
+     else:
+@@ -348,14 +341,31 @@ def parse_package_name(name, pkg_spec, module):
+             pkg_spec['flavor']            = None
              pkg_spec['style']             = 'stem'
          else:
-             module.fail_json(msg="Unable to parse package name at else: " + 
name)
+-            module.fail_json(msg="Unable to parse package name at else: " + 
name)
++            module.fail_json(msg="unable to parse package name at else: " + 
name)
+ 
++    # If the stem contains an "%" then it needs special treatment.
++    branch_match = re.search("%", pkg_spec['stem'])
++    if branch_match:
++
++        branch_release = "6.0"
++
++        if version_match or versionless_match:
++            module.fail_json(msg="package name using 'branch' syntax also has 
a version or is version-less: " + name)
++        if StrictVersion(platform.release()) < StrictVersion(branch_release):
++            module.fail_json(msg="package name using 'branch' syntax requires 
at least OpenBSD %s: %s" % (branch_release, name))
++
++        pkg_spec['style'] = 'branch'
 +
 +        # Key names from description in pkg_add(1).
 +        pkg_spec['pkgname'] = pkg_spec['stem'].split('%')[0]
 +        pkg_spec['branch'] = pkg_spec['stem'].split('%')[1]
- 
++
      # Sanity check that there are no trailing dashes in flavor.
      # Try to stop strange stuff early so we can be strict later.
+     if pkg_spec['flavor']:
+         match = re.search("-$", pkg_spec['flavor'])
+         if match:
+-            module.fail_json(msg="Trailing dash in flavor: " + 
pkg_spec['flavor'])
++            module.fail_json(msg="trailing dash in flavor: " + 
pkg_spec['flavor'])
+ 
+ # Function used for figuring out the port path.
+ def get_package_source_path(name, pkg_spec, module):
+@@ -364,9 +374,14 @@ def get_package_source_path(name, pkg_spec, module):
+         return 'databases/sqlports'
+     else:
+         # try for an exact match first
+-        conn = sqlite3.connect('/usr/local/share/sqlports')
++        sqlports_db_file = '/usr/local/share/sqlports'
++        if not os.path.isfile(sqlports_db_file):
++            module.fail_json(msg="sqlports file '%s' is missing" % 
sqlports_db_file)
++
++        conn = sqlite3.connect(sqlports_db_file)
+         first_part_of_query = 'SELECT fullpkgpath, fullpkgname FROM ports 
WHERE fullpkgname'
+         query = first_part_of_query + ' = ?'
++        module.debug("package_package_source_path(): exact query: %s" % query)
+         cursor = conn.execute(query, (name,))
+         results = cursor.fetchall()
+ 
+@@ -376,11 +391,14 @@ def get_package_source_path(name, pkg_spec, module):
+             query = first_part_of_query + ' LIKE ?'
+             if pkg_spec['flavor']:
+                 looking_for += pkg_spec['flavor_separator'] + 
pkg_spec['flavor']
++                module.debug("package_package_source_path(): fuzzy flavor 
query: %s" % query)
+                 cursor = conn.execute(query, (looking_for,))
+             elif pkg_spec['style'] == 'versionless':
+                 query += ' AND fullpkgname NOT LIKE ?'
++                module.debug("package_package_source_path(): fuzzy 
versionless query: %s" % query)
+                 cursor = conn.execute(query, (looking_for, "%s-%%" % 
looking_for,))
+             else:
++                module.debug("package_package_source_path(): fuzzy query: %s" 
% query)
+                 cursor = conn.execute(query, (looking_for,))
+             results = cursor.fetchall()
+ 
+@@ -464,8 +482,9 @@ def main():
+         # build sqlports if its not installed yet
+         pkg_spec = {}
+         parse_package_name('sqlports', pkg_spec, module)
+-        installed_state = get_package_state(name, pkg_spec, module)
++        installed_state = get_package_state('sqlports', pkg_spec, module)
+         if not installed_state:
++            module.debug("main(): installing 'sqlports' because build=%s" % 
module.params['build'])
+             package_present('sqlports', installed_state, pkg_spec, module)
+ 
+     if name == '*':
+@@ -478,6 +497,11 @@ def main():
+         # Parse package name and put results in the pkg_spec dictionary.
+         pkg_spec = {}
+         parse_package_name(name, pkg_spec, module)
++
++        # Not sure how the branch syntax is supposed to play together
++        # with build mode. Disable it for now.
++        if pkg_spec['style'] == 'branch' and module.params['build'] is True:
++            module.fail_json(msg="the combination of 'branch' syntax and 
build=%s is not supported: %s" % (module.params['build'], name))
+ 
+         # Get package state.
+         installed_state = get_package_state(name, pkg_spec, module)


-- 
jasper

Reply via email to