Skip to content
This repository has been archived by the owner on May 24, 2023. It is now read-only.

Commit

Permalink
Allow setting annotations on CSV
Browse files Browse the repository at this point in the history
* OSBS-8538

Signed-off-by: Luiz Carvalho <[email protected]>
  • Loading branch information
lcarva committed Jan 29, 2020
1 parent fab0bef commit 6d6d39b
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 4 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,24 @@ Example configuration:
"package_name_suffix": "-suffix"
```

#### Adding annotations to ClusterServiceVersion

An organization can be configured to automatically set annotations on the ClusterServiceVersion
objects. Templating is supported to include the package name in the value.
Example configuration:
```
"csv_annotations": [
{
"name": "simple.annotation",
"value": "simple.value",
},
{
"name": "annotation.with.package_name",
"value": "value.{package_name}",
},
]
```

### Greenwave integration

This is optional. When `GREENWAVE` settings are missing in config file checks
Expand Down
36 changes: 36 additions & 0 deletions omps/api/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import logging
import os

from ruamel.yaml import YAML

from omps.errors import OMPSAuthorizationHeaderRequired


Expand Down Expand Up @@ -47,6 +49,40 @@ def replace_registries(quay_org, dir_path):
f.flush()


def adjust_csv_annotations(quay_org, dir_path, context):
"""Annotates ClusterServiceVersion objects based on org config
Iterate through all the YAML files in search of the
ClusterServiceVersion objects then set the annotations
defined in the organization configuration.
:param quay_org: QuayOrganization
:param dir_path: str, path to directory with metadata files
:param context: dict, mapping to dynamic annotation values
:rtype: None
"""
if not quay_org.csv_annotations:
return

yaml = YAML()
# for filename in sorted(os.listdir(dir_path)):
for filename in _yield_yaml_files(dir_path):
with open(filename, 'r+') as f:
contents = yaml.load(f.read())
if contents.get('kind') != 'ClusterServiceVersion':
continue
logger.info('Found ClusterServiceVersion in %s', filename)
csv_annotations = (
contents.setdefault('metadata', {}).setdefault('annotations', {}))
for annotation in quay_org.csv_annotations:
value = annotation['value'].format(**context)
csv_annotations[annotation['name']] = value

f.seek(0)
yaml.dump(contents, f)
f.truncate()


def _yield_yaml_files(dir_path):
"""Helper function to iterate only through yaml files"""
for root, _, files in os.walk(dir_path):
Expand Down
3 changes: 2 additions & 1 deletion omps/api/v1/push.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from ruamel.yaml import YAML

from . import API
from omps.api.common import extract_auth_token, replace_registries
from omps.api.common import extract_auth_token, replace_registries, adjust_csv_annotations
from omps.constants import (
ALLOWED_EXTENSIONS,
DEFAULT_ZIPFILE_MAX_UNCOMPRESSED_SIZE,
Expand Down Expand Up @@ -246,6 +246,7 @@ def _zip_flow(*, organization, repo, version, extract_manifest_func,
logger.info("Using release version: %s", version)

replace_registries(quay_org, tmpdir)
adjust_csv_annotations(quay_org, tmpdir, {'package_name': package_name})

quay_org.push_operator_manifest(repo, version, tmpdir)

Expand Down
35 changes: 33 additions & 2 deletions omps/quay.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,28 @@ class OrgManager:
"package_name_suffix": {
"description": "suffix to append to package name",
"type": "string"
},
"csv_annotations": {
"description": ("annotations to add to each ClusterServiceVersion"
" object"),
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "name of the annotation"
},
"value": {
"type": "string",
"description": (
"value of the annotation, use python string"
" format syntax for dynamic values")

},
},
"required": ["name", "value"]
}
}
},
},
Expand Down Expand Up @@ -184,12 +206,14 @@ def initialize(self, config):
for org_name, org_conf in self._organizations.items():
logger.info(
'Organization "%s" configured: public=%s, oauth_access=%s, '
'replacing_registry_enabled=%s, package_name_suffix=%s',
'replacing_registry_enabled=%s, package_name_suffix=%s, '
'csv_annotations=%s',
org_name,
org_conf.get('public', False),
bool(org_conf.get('oauth_token')),
bool(org_conf.get('replace_registry')),
org_conf.get('package_name_suffix'),
bool(org_conf.get('csv_annotations')),
)

def get_org(self, organization, cnr_token):
Expand All @@ -202,6 +226,7 @@ def get_org(self, organization, cnr_token):
timeout=self._timeout,
replace_registry_conf=org_config.get('replace_registry'),
package_name_suffix=org_config.get('package_name_suffix'),
csv_annotations=org_config.get('csv_annotations'),
)


Expand All @@ -210,7 +235,8 @@ class QuayOrganization:

def __init__(
self, organization, cnr_token, oauth_token=None, public=False,
timeout=None, replace_registry_conf=None, package_name_suffix=None
timeout=None, replace_registry_conf=None, package_name_suffix=None,
csv_annotations=None,
):
"""
:param organization: organization name
Expand All @@ -229,6 +255,7 @@ def __init__(
self._timeout = timeout
self._replace_registry_conf = replace_registry_conf
self._package_name_suffix = package_name_suffix
self._csv_annotations = csv_annotations

@property
def public(self):
Expand All @@ -246,6 +273,10 @@ def organization(self):
def package_name_suffix(self):
return self._package_name_suffix

@property
def csv_annotations(self):
return self._csv_annotations

@property
def registry_replacing_enabled(self):
return bool(self._replace_registry_conf)
Expand Down
37 changes: 36 additions & 1 deletion tests/api/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@

import os

from omps.api.common import replace_registries, _yield_yaml_files
from ruamel.yaml import YAML

from omps.api.common import replace_registries, adjust_csv_annotations, _yield_yaml_files
from omps.quay import QuayOrganization


Expand All @@ -32,3 +34,36 @@ def test_replace_registries(datadir):
text = f.read()
assert new in text
assert old not in text


def test_adjust_csv_annotations(datadir):
"""Test if annotations are applied in ClusterServiceVersion"""
dir_path = os.path.join(datadir, 'etcd_op_nested')
csv_annotations = [
{'name': 'simple', 'value': 'simple-value'},
{'name': 'complex', 'value': 'value-{package_name}'},
]
expected_annotations = {
'simple': 'simple-value',
'complex': 'value-etcd',
}
quay_org = QuayOrganization(
'testorg', 'random token', csv_annotations=csv_annotations)

should_have_annotations = set()
for fpath in _yield_yaml_files(dir_path):
with open(fpath, 'r') as f:
text = f.read()
if 'ClusterServiceVersion' in text:
should_have_annotations.add(fpath)

assert should_have_annotations, 'Insufficient test data'

adjust_csv_annotations(quay_org, dir_path, {'package_name': 'etcd'})

yaml = YAML()
for fpath in should_have_annotations:
with open(fpath, 'r') as f:
contents = yaml.load(f.read())
for name, value in expected_annotations.items():
assert contents['metadata']['annotations'][name] == value
Binary file added tests/data/marketplace-op-flag.tar.gz
Binary file not shown.
Binary file added tests/data/marketplace-op-flag.zip
Binary file not shown.
12 changes: 12 additions & 0 deletions tests/test_quay.py
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,12 @@ class ConfClass:
'org_with_package_name_suffix': {
'package_name_suffix': '-suffix',
},
'org_with_csv_annotations': {
'csv_annotations': [
{'name': 'spam', 'value': 'maps'},
{'name': 'eggs', 'value': 'sgge'},
],
},
}

conf = Config(ConfClass)
Expand Down Expand Up @@ -572,6 +578,12 @@ class ConfClass:
'cnr_token')
assert org_with_package_name_suffix.package_name_suffix == '-suffix'

org_with_csv_annotations = om.get_org('org_with_csv_annotations', 'cnr_token')
assert org_with_csv_annotations.csv_annotations == [
{'name': 'spam', 'value': 'maps'},
{'name': 'eggs', 'value': 'sgge'},
]

def test_getting_unconfigured_org(self):
"""Test of getting organization instance whne org is not configured in
settings"""
Expand Down

0 comments on commit 6d6d39b

Please sign in to comment.