Implement global apt preferences opt

  * Misc: fix 'humanname' processing
  * require salt-formula-salt=0.4+201812211629.9b3097a or higer
    - add dep. salt

Prod-relate: PROD-25786 (PROD:25786)

Change-Id: Ie93425d579a44e1a9775a37e9592530c1e0be02c
diff --git a/.kitchen.yml b/.kitchen.yml
index 4df2b13..eb4ed88 100644
--- a/.kitchen.yml
+++ b/.kitchen.yml
@@ -12,6 +12,10 @@
   require_chef: false
   log_level: error
   formula: linux
+  dependencies:
+    - name: salt
+      repo: git
+      source: http://gerrit.mcp.mirantis.com/salt-formulas/salt
   grains:
     noservices: true
   state_top:
diff --git a/README.rst b/README.rst
index ef99718..cdbfeae 100644
--- a/README.rst
+++ b/README.rst
@@ -956,6 +956,27 @@
                priority: 900
                package: '*'
 
+Sometimes better to use one pining rule file, to decrease mistaken
+ordering. You can use those option ``system:apt:preferences``, which would add opts into
+``/etc/apt/preferences`` file:
+
+.. code-block:: yaml
+
+  parameters:
+    linux:
+      system:
+        apt:
+          preferences:
+            enabled: true
+            rules:
+              100:
+                enabled: true
+                name: 'some origin pin'
+                pin: 'release o=Debian'
+                priority: 1100
+                package: '*'
+
+
 If you need to add multiple pin rules for one repo, please use new,ordered definition format
 ('pinning' definition will be in priotity to use):
 
diff --git a/linux/files/preferences_repo b/linux/files/preferences_repo
index 91e9f9b..6b66b4b 100644
--- a/linux/files/preferences_repo
+++ b/linux/files/preferences_repo
@@ -1,19 +1,39 @@
+{# Don't remove newlines between rules!
+Input variables might be: `pin_dict` OR `repo_id`
+For both usage example, see README.md #}
 {%- from "linux/map.jinja" import system with context -%}
-{%- set repo = system.repo[repo_name] -%}
-{%- if repo.pinning is defined  -%}
-  {%- for id,pin in repo.pinning|dictsort -%}
-    {% if pin.get('enabled', False) %}
+{%- if pin_dict is defined %}
+  {%- set pin_dict_inted = salt['sharedlib.call']('misc.cast_dict_keys_to_int', pin_dict ) %}
+  {%- for id,pin in pin_dict_inted|dictsort -%}
+    {%- if pin.get('enabled', False) %}
 
+# Pining rule: {%- if pin.get('name', False) %}{{ pin.name }}{% else %}noname{%- endif %}
 Package: {{ pin.get('package','*') }}
 Pin: {{ pin.pin }}
 Pin-Priority: {{ pin.priority }}
     {%- endif %}
   {%- endfor -%}
-{%- elif repo.pin is defined -%}
-  {%- for pin in repo.pin -%}
-    {%- set package = pin.get('package', '*') %}
+{% elif repo_id is defined  -%}
+  {%- set repo = system.get('repo',{}).get(repo_id, {}) -%}
+  {%- if repo.pinning is defined -%}
+    {%- for id,pin in repo.pinning|dictsort -%}
+      {% if pin.get('enabled', False) %}
+
+Package: {{ pin.get('package','*') }}
+Pin: {{ pin.pin }}
+Pin-Priority: {{ pin.priority }}
+      {%- endif %}
+    {%- endfor -%}
+  {%- elif repo.pin is defined -%}
+    {%- for pin in repo.pin -%}
+      {%- set package = pin.get('package', '*') %}
+
 Package: {{ package }}
 Pin: {{ pin.pin }}
 Pin-Priority: {{ pin.priority }}
-  {%- endfor %}
-{%- endif -%}
+    {%- endfor %}
+  {%- endif -%}
+{% endif -%}
+{#
+# vim: ft=jinja
+#}
diff --git a/linux/system/apt.sls b/linux/system/apt.sls
index 0c3f7a7..3d37a18 100644
--- a/linux/system/apt.sls
+++ b/linux/system/apt.sls
@@ -1,14 +1,27 @@
 {%- from "linux/map.jinja" import system with context %}
 {%- if system.enabled %}
-{%- if grains.os_family == 'Debian' %}
+  {%- if grains.os_family == 'Debian' %}
 
-{%- if system.repo|length > 0 %}
+    {%- if system.get('repo',{})|length > 0 %}
 include:
 - linux.system.repo
-{%- endif %}
+    {%- endif %}
 
-{%- for key, config in system.apt.get('config', {}).items() %}
+    {%- if system.get('apt',{}).get('preferences',{}).get('enabled',{})|default(false)  %}
+linux_apt_preferences:
+  file.managed:
+    - name: /etc/apt/preferences
+    - source: salt://linux/files/preferences_repo
+    - template: jinja
+    - defaults:
+        pin_dict: {{ system.apt.preferences.rules }}
+    {%- else %}
+linux_apt_preferences:
+  file.absent:
+    - name: /etc/apt/preferences
+    {%- endif %}
 
+    {%- for key, config in system.get('apt',{}).get('config', {}).items() %}
 linux_apt_conf_{{ key }}:
   file.managed:
   - name: /etc/apt/apt.conf.d/99{{ key }}-salt
@@ -16,12 +29,11 @@
   - source: salt://linux/files/apt.conf
   - defaults:
       config: {{ config|yaml }}
-  {%- if system.repo|length > 0 %}
+      {% if system.get('pkgs', False) and system.get('repo',{})|length > 0 %}
   - require_in:
     - pkg: linux_repo_prereq_pkgs
+        {%- endif %}
+    {%- endfor %}
+
   {%- endif %}
-
-{%- endfor %}
-
-{%- endif %}
 {%- endif %}
diff --git a/linux/system/repo.sls b/linux/system/repo.sls
index 03bb72d..bd56b5a 100644
--- a/linux/system/repo.sls
+++ b/linux/system/repo.sls
@@ -6,6 +6,11 @@
 {%- set refresh_cmd = 'refresh' %}
 {%- endif %}
 
+{%- if system.apt is defined %}
+include:
+- linux.system.apt
+{%- endif %}
+
   {% if system.pkgs %}
 linux_repo_prereq_pkgs:
   pkg.installed:
@@ -42,7 +47,6 @@
   {%- endif %}
 
   {%- for name, repo in system.repo.items() %}
-    {%- set name=repo.get('name', name) %}
     {%- if grains.os_family == 'Debian' %}
 
 # per repository proxy setup
@@ -62,14 +66,14 @@
   file.absent
       {%- endif %}
 
-      {%- if repo.pin is defined or repo.pinning is defined %}
+      {%- if repo.get('pin',False) or repo.get('pinning', False) %}
 linux_repo_{{ name }}_pin:
   file.managed:
     - name: /etc/apt/preferences.d/{{ name }}
     - source: salt://linux/files/preferences_repo
     - template: jinja
     - defaults:
-        repo_name: {{ name }}
+        repo_id: {{ name }}
       {%- else %}
 linux_repo_{{ name }}_pin:
   file.absent:
@@ -124,7 +128,7 @@
           {%- if repo.ppa is defined %}
   - ppa: {{ repo.ppa }}
           {%- else %}
-  - humanname: {{ name }}
+  - humanname: {{ repo.get('name', name) }}
   - name: {{ repo.source }}
             {%- if repo.architectures is defined %}
   - architectures: {{ repo.architectures }}
diff --git a/tests/pillar/system.sls b/tests/pillar/system.sls
index 3dc183d..636d494 100644
--- a/tests/pillar/system.sls
+++ b/tests/pillar/system.sls
@@ -5,6 +5,22 @@
     fqdn: linux.ci.local
   system:
     enabled: true
+    apt:
+      preferences:
+        enabled: true
+        rules:
+          100:
+            enabled: true
+            name: 'Ubuntu origin'
+            pin: 'release o=Ubuntu'
+            priority: 1100
+            package: '*'
+          5:
+            enabled: true
+            name: 'Ubuntu origin'
+            pin: 'release o=Ubuntu'
+            priority: 1100
+            package: '*'
     at:
       enabled: true
       user:
@@ -223,6 +239,7 @@
       saltstack:
         source: "deb [arch=amd64] http://repo.saltstack.com/apt/ubuntu/16.04/amd64/2017.7/ xenial main"
         key_url: "http://repo.saltstack.com/apt/ubuntu/16.04/amd64/2017.7/SALTSTACK-GPG-KEY.pub"
+        name: 'human readable saltstack reponame'
         architectures: amd64
         clean_file: true
         pinning: