add support for node affinity, pod affinity/anti_affinity

Change-Id: I142f63687fe1e4ccd6c5836b88a18e92476eed6c
diff --git a/README.rst b/README.rst
index c81b3d7..3c72d92 100644
--- a/README.rst
+++ b/README.rst
@@ -516,6 +516,77 @@
             - name: config
               mount: /test
 
+Affinity
+--------
+
+podAffinity
+===========
+
+Example pillar:
+
+.. code-block:: bash
+
+    kubernetes:
+      control:
+      service:
+        memcached:
+          affinity:
+            pod_affinity:
+              name: podAffinity
+              expression:
+                label_selector:
+                  name: labelSelector
+                  selectors:
+                  - key: app
+                    value: memcached
+              topology_key: kubernetes.io/hostname
+
+podAntiAffinity
+===============
+
+Example pillar:
+
+.. code-block:: bash
+
+    kubernetes:
+      control:
+      service:
+        memcached:
+          affinity:
+            anti_affinity:
+              name: podAntiAffinity
+              expression:
+                label_selector:
+                  name: labelSelector
+                  selectors:
+                  - key: app
+                    value: opencontrail-control
+              topology_key: kubernetes.io/hostname
+
+nodeAffinity
+===============
+
+Example pillar:
+
+.. code-block:: bash
+
+    kubernetes:
+      control:
+      service:
+        memcached:
+          affinity:
+            node_affinity:
+              name: nodeAffinity
+              expression:
+                match_expressions:
+                  name: matchExpressions
+                  selectors:
+                  - key: key
+                    operator: In
+                    values:
+                    - value1
+                    - value2
+
 Volumes
 -------
 
diff --git a/kubernetes/files/job.yml b/kubernetes/files/job.yml
index 48cc47a..95103b9 100644
--- a/kubernetes/files/job.yml
+++ b/kubernetes/files/job.yml
@@ -77,7 +77,7 @@
       {%- endfor %}
       {%- endif %}
       restartPolicy: {{ job.restart_policy }}
-      {%- if job.nodeSelector is defined %}
+      {%- if job.node_selector is defined %}
       nodeSelector:
         {%- for selector in job.node_selector %}
         {{ selector.key }}: {{ selector.value }}
diff --git a/kubernetes/files/rc.yml b/kubernetes/files/rc.yml
index 3d5f61b..0e80393 100644
--- a/kubernetes/files/rc.yml
+++ b/kubernetes/files/rc.yml
@@ -44,6 +44,50 @@
         {%- if not loop.last %},{% endif %}{% endfor %}
         ]'
       {%- endif %}
+      {%- if service.affinity is defined %}
+        scheduler.alpha.kubernetes.io/affinity: >
+          {
+          {%- for affinity_name, affinity in service.affinity.iteritems() %}
+            "{{ affinity.name }}": {
+              {%- for expression_name, expression in affinity.expression.iteritems() %}
+              {%- if expression.name ==  'matchExpressions' %}
+              "{{ affinity.get('type','required') }}DuringSchedulingIgnoredDuringExecution": {
+                "nodeSelectorTerms": [
+                  {
+                    "matchExpressions": [
+                    {%- for selector in expression.selectors %}
+                      {
+                        "key": "{{ selector.key }}",
+                        "operator": "{{ selector.operator }}",
+                        "values": [{%- for value in selector['values'] %}"{{ value }}"{%- if not loop.last %},{% endif %}{%- endfor %}]
+                      }{%- if not loop.last %},{% endif %}
+                    {% endfor %}
+                    ]
+                  }
+                ]
+              }
+              {%- elif expression.name == 'labelSelector'  %}
+              "{{ affinity.get('type','required') }}DuringSchedulingIgnoredDuringExecution": [
+                {
+                  "labelSelector": {
+                    "matchLabels": {
+                      {%- for selector in expression.selectors %}
+                      "{{ selector.key }}": "{{ selector.value }}"
+                    {%- if not loop.last %},{% endif %}{%- endfor %}
+                    }
+                  },
+                  {%- if affinity.name == 'podAntiAffinity' or affinity.name == 'podAffinity' %}
+                  "topologyKey": "{{ affinity.topology_key }}"
+                  {%- endif %}
+                }
+              ]
+              {%- endif %}
+              {%- endfor %}
+          {%- if not loop.last %}},{% endif %}
+          {%- endfor %}
+            }
+          }
+      {%- endif %}
     spec:
       {%- if service.hostNetwork is defined %}
       hostNetwork: True