Skip to content

Commit

Permalink
Merge branch 'master' into add-registry-sidecar-support
Browse files Browse the repository at this point in the history
  • Loading branch information
jesusbv committed Apr 17, 2024
1 parent 243d380 commit 77b2928
Show file tree
Hide file tree
Showing 22 changed files with 532 additions and 224 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/ci-testing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: CI-Code-Style

on: [push]

jobs:
unit_tests:
name: Linter checks
runs-on: ubuntu-20.04
strategy:
matrix:
python-version: [3.6]

steps:
- uses: actions/checkout@v3
- name: Python${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install Tox
run: |
python -m pip install --upgrade pip
python -m pip install tox
- name: Run code checks
run: |
tox -e check
tox -e "unit_py${PY_VER/./_}" -- -n auto
env:
PY_VER: ${{ matrix.python-version }}
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Distribution / packaging
*.egg-info

# Unit test / coverage reports
.tox/
.coverage
.cache
**/*/__pycache__/
.pytest_cache
15 changes: 15 additions & 0 deletions .virtualenv.dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
-r .virtualenv.requirements.txt

# python unit testing framework
pytest
pytest-cov
coverage

# Rolling backport of unittest.mock for all Pythons
mock

# Python style guide checker
flake8

# Version-bump your software with a single command!
bumpversion
5 changes: 5 additions & 0 deletions .virtualenv.requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
lxml
requests
dnspython
M2Crypto
toml
3 changes: 2 additions & 1 deletion cloud-regionsrv-client.spec
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#


%define base_version 10.1.6
%define base_version 10.1.8
Name: cloud-regionsrv-client
Version: %{base_version}
Release: 0
Expand Down Expand Up @@ -189,6 +189,7 @@ fi
%dir /var/cache/cloudregister
%{_mandir}/man*/*
%{_sbindir}/cloudguest-repo-service
%{_sbindir}/cloudguestregistryauth
%{_sbindir}/containerbuild-regionsrv
%{_sbindir}/createregioninfo
%{_sbindir}/switchcloudguestservices
Expand Down
3 changes: 2 additions & 1 deletion etc/regionserverclnt.cfg
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
[server]
api = regionInfo
certLocation = /var/lib/regionService/certs
certLocation = /usr/lib/regionService/certs
regionsrv = COMMA_SEP_LIST_OF_CLOUD_SPECIFIC_REGION_SERVER
metadata_server = OPTIONAL_URL_FOR_METADATA_SERVER_SMT_INFO

[instance]
dataProvider = none
instanceArgs = none
httpsOnly = true

[service]
verifyAccess = none
Expand Down
13 changes: 10 additions & 3 deletions integration_test-process.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ After installing the test package with "zypper in"
+ success message on stdout
+ $? is 0
+ zypper lr has repos
- Update server failover
+ ip=`grep susecloud.net /etc/hosts | cut -f1`
+ iptables -A OUTPUT -d $ip -j DROP
+ zypper ref
+ grep -i equivalent /var/log/cloudregister
+ grep susecloud.net /etc/hosts
+ IP addresses in the last two outputs should match

byos - test on SLES4SAP instance
After installing the test package with "zypper in"
Expand All @@ -57,9 +64,9 @@ After installing the test package with "zypper in"
+ no error no message
+ zypper lr has no repos
- SUSEConnect -r XXX
+ registartion successful
+ registration successful
- SUSEConnect -p sle-module-public-cloud/$VERSION/x86_64
+ registartion successful
+ registration successful
- SUSEConnect -d -p sle-module-public-cloud/$VERSION/x86_64
+ module deletion successful
+ Requires SUSEConnect > 0.3.32
Expand All @@ -79,7 +86,7 @@ After installing the test package with "zypper in"
+ $? is 0
+ repos include HA
- SUSEConnect -p sle-module-public-cloud/$VERSION/x86_64
+ registartion successful
+ registration successful
+ Cloud based RMT server is the target
- registercloudguest --clean

Expand Down
2 changes: 1 addition & 1 deletion lib/cloudregister/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
10.1.6
10.1.8
11 changes: 5 additions & 6 deletions lib/cloudregister/amazonec2.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,18 @@ def generateRegionSrvArgs():
for imds_ip in imds_ips:
imds_addr = imds_ip
if ':' in imds_ip:
imds_addr = '[%s]' %imds_ip
imds_addr = '[%s]' % imds_ip
try:
token_resp = requests.put(
token_url %imds_addr,
token_url % imds_addr,
headers=token_header
)
if token_resp.status_code == 200:
zone_req_header = {'X-aws-ec2-metadata-token': token_resp.text}
else:
continue
except requests.exceptions.RequestException:
msg = 'Unable to retrieve IMDSv2 token using %s' %imds_ip
msg = 'Unable to retrieve IMDSv2 token using %s' % imds_ip
logging.info(msg)
continue
break
Expand All @@ -58,8 +58,8 @@ def generateRegionSrvArgs():
for imds_ip in imds_ips:
imds_addr = imds_ip
if ':' in imds_ip and '[' not in imds_ip:
imds_addr = '[%s]' %imds_ip
metadata_url = 'http://%s/latest/meta-data/' %imds_addr
imds_addr = '[%s]' % imds_ip
metadata_url = 'http://%s/latest/meta-data/' % imds_addr
zone_info = 'placement/availability-zone'

try:
Expand Down Expand Up @@ -104,6 +104,5 @@ def generateRegionSrvArgs():
logging.warning('\tMessage: %s' % zone_resp.text)
if imds_ip == imds_ips[-1]:
return
continue

return 'regionHint=' + region
29 changes: 22 additions & 7 deletions lib/cloudregister/registerutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
DOCKER_CONFIG_PATH = '/etc/docker/daemon.json'
REGISTRIES_CONF_PATH = '/etc/containers/registries.conf'


# ----------------------------------------------------------------------------
def add_hosts_entry(smt_server):
"""Add an entry to the /etc/hosts file for the given SMT server"""
Expand Down Expand Up @@ -461,7 +462,10 @@ def get_available_smt_servers():
if not os.path.exists(get_state_dir()):
return available_smt_servers
smt_data_files = glob.glob(
os.path.join(get_state_dir(), AVAILABLE_SMT_SERVER_DATA_FILE_NAME % '*')
os.path.join(
get_state_dir(),
AVAILABLE_SMT_SERVER_DATA_FILE_NAME % '*'
)
)
for smt_data in smt_data_files:
available_smt_servers.append(get_smt_from_store(smt_data))
Expand Down Expand Up @@ -564,6 +568,14 @@ def set_registry_order_search(registry_fqdn):
_set_registry_order_search_docker(registry_fqdn)


def refresh_registry_credentials():
"""Refresh registry credentials."""
# to silence InsecureRequestWarning
# should be fixed on a different PR
requests.packages.urllib3.disable_warnings()
return get_activations()


# ----------------------------------------------------------------------------
def get_credentials_file(update_server, service_name=None):
"""Return the credentials filename.
Expand Down Expand Up @@ -617,9 +629,9 @@ def get_current_smt():
smt_ipv6 = smt.get_ipv6()
smt_fqdn = smt.get_FQDN()
# A bit cumbersome to support Python 3.4
ipv4_search = '%s\s' % smt_ipv4
ipv6_search = '%s\s' % smt_ipv6
fqdn_search = '\s%s\s' % smt_fqdn
ipv4_search = r'%s\s' % smt_ipv4
ipv6_search = r'%s\s' % smt_ipv6
fqdn_search = r'\s%s\s' % smt_fqdn
with open(HOSTSFILE_PATH, 'rb') as hosts_file:
hosts = hosts_file.read()
if (
Expand Down Expand Up @@ -808,6 +820,7 @@ def get_smt(cache_refreshed=None):
# Fetch cert for new target server
import_smt_cert(new_target)
# Verify the new target server has our credentials
replace_hosts_entry(current_smt, new_target)
credentials_file_path = get_credentials_file(new_target)
user, password = get_credentials(credentials_file_path)
if not has_smt_access(
Expand All @@ -824,8 +837,8 @@ def get_smt(cache_refreshed=None):
msg += 'current, %s, target update server.'
msg += 'Try again later.'
logging.error(msg % (new_target_ips, original_smt_ips))
replace_hosts_entry(new_target, current_smt)
return current_smt
replace_hosts_entry(current_smt, new_target)
set_as_current_smt(new_target)
return new_target
else:
Expand Down Expand Up @@ -992,7 +1005,7 @@ def has_region_changed(cfg):
registered_region = json.loads(
framework_file.read()
)
except:
except Exception:
return False

if (
Expand Down Expand Up @@ -1714,7 +1727,9 @@ def _set_registry_order_search_podman(registry_fqdn):
with open(REGISTRIES_CONF_PATH, 'r') as registries_conf_file:
registries_conf = toml.load(registries_conf_file)

if registry_fqdn not in registries_conf['unqualified-search-registries']: # no-qa
missing_registry_fqdn = registry_fqdn not in \
registries_conf['unqualified-search-registries']
if missing_registry_fqdn:
registries_conf['unqualified-search-registries'] = \
["{}".format(registry_fqdn), 'registry.suse.com'] + \
registries_conf['unqualified-search-registries']
Expand Down
6 changes: 3 additions & 3 deletions lib/cloudregister/smt.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ def write_cert(self, target_dir):
# we write here with the known pattern.
for cert_name in certs_to_write:
try:
with open(ca_file_path %cert_name, 'w') as smt_ca_file:
with open(ca_file_path % cert_name, 'w') as smt_ca_file:
smt_ca_file.write(cert)
except IOError:
errMsg = 'Could not store update server certificate'
Expand All @@ -232,8 +232,8 @@ def _form_srv_check_urls(self):
rmt_ip = srv_ip
# Per rfc3986 IPv6 addresses in a URI are enclosed in []
if isinstance(ipaddress.ip_address(rmt_ip), ipaddress.IPv6Address):
rmt_ip = '[%s]' %srv_ip
health_url = 'https://%s/api/health/status' %rmt_ip
rmt_ip = '[%s]' % srv_ip
health_url = 'https://%s/api/health/status' % rmt_ip
cert_url = '%s://%s/' % (self._protocol, rmt_ip)
check_urls[health_url] = cert_url

Expand Down
12 changes: 12 additions & 0 deletions man/man1/cloudguestregistryauth.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.\" Process this file with
.\" groff -man -Tascii cloudguestregstryauth.1
.\"
.TH cloudguestregstryauth.1
.SH NAME
cloudguestregstryauth \- Refresh registry credentials for a registered SUSE Linux Enterprise instance
.SH SYNOPSIS
.B cloudguestregstryauth
.SH DESCRIPTION
.B cloudguestregstryauth
Refresh registry credentials for a registered SUSE Linux Enterprise instance. The client will reach
out to the already configured update server to refresh the existing credentials.
2 changes: 1 addition & 1 deletion tests/data/regionserverclnt.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[server]
api = regionInfo
certLocation = /var/lib/regionService/certs
certLocation = /usr/lib/regionService/certs
regionsrv = COMMA_SEP_LIST_OF_CLOUD_SPECIFIC_REGION_SERVER
metadata_server = OPTIONAL_URL_FOR_METADATA_SERVER_SMT_INFO
2 changes: 1 addition & 1 deletion tests/test_azureplugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

sys.path.insert(0, code_path)

import msftazure as azure
import msftazure as azure # noqa


# ----------------------------------------------------------------------------
Expand Down
92 changes: 92 additions & 0 deletions tests/test_cloudguestregistryauth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import inspect
import os
import sys

from lxml import etree

from importlib.machinery import SourceFileLoader

from pytest import raises
from textwrap import dedent
from unittest.mock import patch

test_path = os.path.abspath(
os.path.dirname(inspect.getfile(inspect.currentframe())))
code_path = os.path.abspath('%s/../lib' % test_path)
data_path = test_path + os.sep + 'data/'

sys.path.insert(0, code_path)

from cloudregister.smt import SMT # noqa


# Hack to get the script without the .py imported for testing
cloudguestregistryauth = SourceFileLoader(
'cloudguestregistryauth',
'./usr/sbin/cloudguestregistryauth'
).load_module()


@patch('cloudguestregistryauth.os.geteuid')
def test_registry_call_as_root(mock_os_geteuid):
mock_os_geteuid.return_value = 1
with raises(SystemExit) as pytest_wrapped_e:
cloudguestregistryauth.main()

assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 'You must be root'


@patch('cloudregister.registerutils.get_activations')
@patch('cloudregister.registerutils.is_registered')
@patch('cloudregister.registerutils.get_current_smt')
@patch('cloudguestregistryauth.os.geteuid')
def test_registry_get_activations_error(
mock_os_geteuid, mock_get_current_smt,
mock_is_registered, mock_get_activations
):
mock_os_geteuid.return_value = 0
mock_is_registered.return_value = True
smt_data_ipv46 = dedent('''\
<smtInfo fingerprint="00:11:22:33"
SMTserverIP="192.168.1.1"
SMTserverIPv6="fc00::1"
SMTserverName="fantasy.example.com"
SMTregistryName="registry-fantasy.example.com"
region="antarctica-1"/>''')
smt_server = SMT(etree.fromstring(smt_data_ipv46))
mock_get_current_smt.return_value = smt_server
mock_get_activations.return_value = {}

with raises(SystemExit) as pytest_wrapped_e:
cloudguestregistryauth.main()

assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 'Could not refresh credentials'


@patch('builtins.print')
@patch('cloudregister.registerutils.get_activations')
@patch('cloudregister.registerutils.is_registered')
@patch('cloudregister.registerutils.get_current_smt')
@patch('cloudguestregistryauth.os.geteuid')
def test_registry_get_activations(
mock_os_geteuid, mock_get_current_smt,
mock_is_registered, mock_get_activations,
mock_print
):
mock_os_geteuid.return_value = 0
mock_is_registered.return_value = True
smt_data_ipv46 = dedent('''\
<smtInfo fingerprint="00:11:22:33"
SMTserverIP="192.168.1.1"
SMTserverIPv6="fc00::1"
SMTserverName="fantasy.example.com"
SMTregistryName="registry-fantasy.example.com"
region="antarctica-1"/>''')
smt_server = SMT(etree.fromstring(smt_data_ipv46))
mock_get_current_smt.return_value = smt_server
mock_get_activations.return_value = {'foo': 'bar'}

cloudguestregistryauth.main()
mock_print.assert_called_once_with('Credentials refreshed')

0 comments on commit 77b2928

Please sign in to comment.