Implement openstack-images-sync on k8s
Change-Id: Ie9a6559762a1180657f06307674daf4eba559a0f
This commit is contained in:
parent
52706b1332
commit
f0adcefc64
34
charms/openstack-images-sync-k8s/CONTRIBUTING.md
Normal file
34
charms/openstack-images-sync-k8s/CONTRIBUTING.md
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# Contributing
|
||||||
|
|
||||||
|
To make contributions to this charm, you'll need a working [development setup](https://juju.is/docs/sdk/dev-setup).
|
||||||
|
|
||||||
|
You can create an environment for development with `tox`:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
tox devenv -e integration
|
||||||
|
source venv/bin/activate
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
This project uses `tox` for managing test environments. There are some pre-configured environments
|
||||||
|
that can be used for linting and formatting code when you're preparing contributions to the charm:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
tox run -e format # update your code according to linting rules
|
||||||
|
tox run -e lint # code style
|
||||||
|
tox run -e static # static type checking
|
||||||
|
tox run -e unit # unit tests
|
||||||
|
tox run -e integration # integration tests
|
||||||
|
tox # runs 'format', 'lint', 'static', and 'unit' environments
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build the charm
|
||||||
|
|
||||||
|
Build the charm in this git repository using:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
charmcraft pack
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- You may want to include any contribution/style guidelines in this document>
|
202
charms/openstack-images-sync-k8s/LICENSE
Normal file
202
charms/openstack-images-sync-k8s/LICENSE
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright 2024 Canonical Ltd.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
66
charms/openstack-images-sync-k8s/README.md
Normal file
66
charms/openstack-images-sync-k8s/README.md
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# openstack-images-sync-k8s
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
openstack-images-sync-k8s is an operator to manage openstack images sync on a Kubernetes based environment.
|
||||||
|
Openstack Images Sync is a tool to sync images from a Simplestreams source to an Openstack cloud.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Deployment
|
||||||
|
|
||||||
|
openstack-images-sync-k8s is deployed using below command:
|
||||||
|
|
||||||
|
juju deploy openstack-images-sync-k8s openstack-images-sync
|
||||||
|
|
||||||
|
Now connect the openstack images sync operator to existing ingress,
|
||||||
|
and keystone identity operators:
|
||||||
|
|
||||||
|
juju relate keystone:identity-service openstack-images-sync:identity-service
|
||||||
|
juju relate traefik-public:ingress openstack-images-sync:ingress-public
|
||||||
|
juju relate traefik-internal:ingress openstack-images-sync:ingress-internal
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
This section covers common and/or important configuration options. See file
|
||||||
|
`charmcraft.yaml` for the full list of options, along with their descriptions and
|
||||||
|
default values. See the [Juju documentation][juju-docs-config-apps] for details
|
||||||
|
on configuring applications.
|
||||||
|
|
||||||
|
### Actions
|
||||||
|
|
||||||
|
This section covers Juju [actions][juju-docs-actions] supported by the charm.
|
||||||
|
Actions allow specific operations to be performed on a per-unit basis. To
|
||||||
|
display action descriptions run `juju actions openstack-images-sync`. If the charm is not
|
||||||
|
deployed then see file `charmcraft.yaml`.
|
||||||
|
|
||||||
|
## Relations
|
||||||
|
|
||||||
|
openstack-images-sync-k8s requires the following relations:
|
||||||
|
|
||||||
|
`identity-service`: To register endpoints in Keystone
|
||||||
|
`ingress-internal`: To expose service on underlying internal network
|
||||||
|
`ingress-public`: To expose service on public network
|
||||||
|
|
||||||
|
## OCI Images
|
||||||
|
|
||||||
|
The charm by default uses following images:
|
||||||
|
|
||||||
|
`ghcr.io/canonical/openstack-images-sync:2024.1`
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Please see the [Juju SDK docs](https://juju.is/docs/sdk) for guidelines
|
||||||
|
on enhancements to this charm following best practice guidelines, and
|
||||||
|
[CONTRIBUTING.md](contributors-guide) for developer guidance.
|
||||||
|
|
||||||
|
## Bugs
|
||||||
|
|
||||||
|
Please report bugs on [Launchpad][lp-bugs-charm-ois-k8s].
|
||||||
|
|
||||||
|
<!-- LINKS -->
|
||||||
|
|
||||||
|
[contributors-guide]: https://opendev.org/openstack/sunbeam-charms/src/branch/main/charms/openstack-images-sync-k8s/CONTRIBUTING.md
|
||||||
|
[juju-docs-actions]: https://jaas.ai/docs/actions
|
||||||
|
[juju-docs-config-apps]: https://juju.is/docs/configuring-applications
|
||||||
|
[lp-bugs-charm-ois-k8s]: https://bugs.launchpad.net/sunbeam-charms/+filebug
|
93
charms/openstack-images-sync-k8s/charmcraft.yaml
Normal file
93
charms/openstack-images-sync-k8s/charmcraft.yaml
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
name: openstack-images-sync-k8s
|
||||||
|
|
||||||
|
type: charm
|
||||||
|
|
||||||
|
title: OpenStack Images Sync K8S
|
||||||
|
|
||||||
|
summary: Keep OpenStack images in sync with the latest versions
|
||||||
|
|
||||||
|
description: |
|
||||||
|
Openstack Images Sync operator allows synchronization from a SimpleStreams source to an OpenStack cloud.
|
||||||
|
|
||||||
|
bases:
|
||||||
|
- build-on:
|
||||||
|
- name: ubuntu
|
||||||
|
channel: "22.04"
|
||||||
|
run-on:
|
||||||
|
- name: ubuntu
|
||||||
|
channel: "22.04"
|
||||||
|
|
||||||
|
config:
|
||||||
|
options:
|
||||||
|
debug:
|
||||||
|
default: False
|
||||||
|
type: boolean
|
||||||
|
frequency:
|
||||||
|
default: hourly
|
||||||
|
description: |
|
||||||
|
The frequency at which the charm should check for new images.
|
||||||
|
Valid values are hourly, daily, weekly.
|
||||||
|
type: string
|
||||||
|
architecture:
|
||||||
|
default: amd64
|
||||||
|
description: |
|
||||||
|
The architectures to sync images for. Space delimited list of architectures.
|
||||||
|
type: string
|
||||||
|
release:
|
||||||
|
default: focal jammy
|
||||||
|
description: |
|
||||||
|
The releases to sync images for. Space delimited list of releases.
|
||||||
|
type: string
|
||||||
|
cloud-name:
|
||||||
|
default: simplestreams-glance-sync
|
||||||
|
description: |
|
||||||
|
The name of the cloud to sync images for.
|
||||||
|
type: string
|
||||||
|
max-items:
|
||||||
|
default: 1
|
||||||
|
description: |
|
||||||
|
The maximum number of images to keep in sync per version.
|
||||||
|
type: int
|
||||||
|
os-admin-hostname:
|
||||||
|
default: openstack-images-sync.juju
|
||||||
|
description: |
|
||||||
|
The hostname or address of the admin endpoints that should be advertised
|
||||||
|
in the openstack image sync.
|
||||||
|
type: string
|
||||||
|
os-internal-hostname:
|
||||||
|
default: openstack-images-sync.juju
|
||||||
|
description: |
|
||||||
|
The hostname or address of the internal endpoints that should be advertised
|
||||||
|
in the openstack image sync.
|
||||||
|
type: string
|
||||||
|
os-public-hostname:
|
||||||
|
default: openstack-images-sync.juju
|
||||||
|
description: |
|
||||||
|
The hostname or address of the internal endpoints that should be advertised
|
||||||
|
in the openstack image sync.
|
||||||
|
type: string
|
||||||
|
region:
|
||||||
|
default: RegionOne
|
||||||
|
description: Space delimited list of OpenStack regions
|
||||||
|
type: string
|
||||||
|
|
||||||
|
containers:
|
||||||
|
openstack-images-sync:
|
||||||
|
resource: openstack-images-sync-image
|
||||||
|
|
||||||
|
resources:
|
||||||
|
openstack-images-sync-image:
|
||||||
|
type: oci-image
|
||||||
|
description: OCI image for OpenStack Images Sync
|
||||||
|
upstream-source: ghcr.io/canonical/openstack-images-sync:2024.1
|
||||||
|
|
||||||
|
requires:
|
||||||
|
ingress-internal:
|
||||||
|
interface: ingress
|
||||||
|
limit: 1
|
||||||
|
optional: true
|
||||||
|
ingress-public:
|
||||||
|
interface: ingress
|
||||||
|
limit: 1
|
||||||
|
identity-service:
|
||||||
|
interface: keystone
|
3
charms/openstack-images-sync-k8s/rebuild
Normal file
3
charms/openstack-images-sync-k8s/rebuild
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# This file is used to trigger a build.
|
||||||
|
# Change uuid to trigger a new build.
|
||||||
|
886a46db-8f02-4271-a825-91153f83c579
|
6
charms/openstack-images-sync-k8s/requirements.txt
Normal file
6
charms/openstack-images-sync-k8s/requirements.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
ops
|
||||||
|
jinja2
|
||||||
|
lightkube
|
||||||
|
lightkube-models
|
||||||
|
|
||||||
|
tenacity
|
267
charms/openstack-images-sync-k8s/src/charm.py
Executable file
267
charms/openstack-images-sync-k8s/src/charm.py
Executable file
@ -0,0 +1,267 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright 2024 Canonical Ltd.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
"""Openstack Images Sync Operator.
|
||||||
|
|
||||||
|
This charm deploys the openstack images sync service on Kubernetes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
from typing import (
|
||||||
|
TYPE_CHECKING,
|
||||||
|
)
|
||||||
|
|
||||||
|
import ops
|
||||||
|
import ops_sunbeam.charm as sunbeam_charm
|
||||||
|
import ops_sunbeam.config_contexts as sunbeam_config_contexts
|
||||||
|
import ops_sunbeam.container_handlers as sunbeam_chandlers
|
||||||
|
import ops_sunbeam.core as sunbeam_core
|
||||||
|
from charms.keystone_k8s.v1.identity_service import (
|
||||||
|
IdentityServiceRequires,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def _frequency_to_seconds(frequency: str) -> int:
|
||||||
|
"""Convert given frequency word to seconds.
|
||||||
|
|
||||||
|
test-do-not-use is for testing purposes only.
|
||||||
|
"""
|
||||||
|
match frequency:
|
||||||
|
case "hourly":
|
||||||
|
return 3600
|
||||||
|
case "daily":
|
||||||
|
return 86400
|
||||||
|
case "weekly":
|
||||||
|
return 604800
|
||||||
|
case "test-do-not-use":
|
||||||
|
return 30
|
||||||
|
case _:
|
||||||
|
raise ValueError(f"Unknown frequency {frequency!r}")
|
||||||
|
|
||||||
|
|
||||||
|
class SyncCharmConfigContext(sunbeam_config_contexts.CharmConfigContext):
|
||||||
|
"""Configure context for templates."""
|
||||||
|
|
||||||
|
def context(self) -> dict:
|
||||||
|
"""Return context for template rendering."""
|
||||||
|
return {
|
||||||
|
**self.charm.config,
|
||||||
|
"architecture": "|".join(
|
||||||
|
self.charm.config["architecture"].split()
|
||||||
|
),
|
||||||
|
"release": "|".join(self.charm.config["release"].split()),
|
||||||
|
"region": ", ".join(self.charm.config["region"].split()),
|
||||||
|
"frequency": _frequency_to_seconds(self.charm.config["frequency"]),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class HttpSyncConfigContext(sunbeam_config_contexts.ConfigContext):
|
||||||
|
"""Configuration context for the http sync service."""
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
charm: "OpenstackImagesSyncK8SCharm"
|
||||||
|
|
||||||
|
def context(self) -> dict:
|
||||||
|
"""Httpd configuration options."""
|
||||||
|
return {
|
||||||
|
"name": self.charm.service_name,
|
||||||
|
"public_port": self.charm.default_public_ingress_port,
|
||||||
|
"error_log": "/dev/stdout",
|
||||||
|
"custom_log": "/dev/stdout",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class OpenstackImagesSyncPebbleHandler(sunbeam_chandlers.ServicePebbleHandler):
|
||||||
|
"""Handler for openstack images sync container."""
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
charm: "OpenstackImagesSyncK8SCharm"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def directories(self) -> list[sunbeam_chandlers.ContainerDir]:
|
||||||
|
"""List of directories to create in container."""
|
||||||
|
return [
|
||||||
|
sunbeam_chandlers.ContainerDir(
|
||||||
|
"/var/www/html/simplestreams",
|
||||||
|
self.charm.service_user,
|
||||||
|
self.charm.service_group,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_layer(self) -> dict:
|
||||||
|
"""Openstack Images Sync service pebble layer.
|
||||||
|
|
||||||
|
:returns: pebble layer configuration for openstack images sync service
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
"summary": f"{self.service_name} layer",
|
||||||
|
"description": f"pebble config layer for {self.service_name}",
|
||||||
|
"services": {
|
||||||
|
"images-sync": {
|
||||||
|
"override": "replace",
|
||||||
|
"summary": self.service_name,
|
||||||
|
"command": (
|
||||||
|
"/usr/bin/openstack-images-sync sync"
|
||||||
|
" --config /etc/openstack-images-sync/config.yaml"
|
||||||
|
),
|
||||||
|
"user": "_daemon_",
|
||||||
|
"group": "_daemon_",
|
||||||
|
"environment": {
|
||||||
|
**self.charm.keystone_auth(),
|
||||||
|
**self.charm.proxy_env(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"http-mirror": {
|
||||||
|
"override": "replace",
|
||||||
|
"summary": "apache",
|
||||||
|
"command": "/usr/sbin/apache2ctl -DFOREGROUND",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
def init_service(self, context: sunbeam_core.OPSCharmContexts) -> None:
|
||||||
|
"""Initialise service ready for use.
|
||||||
|
|
||||||
|
Write configuration files to the container and record
|
||||||
|
that service is ready for us. Enable apache modules.
|
||||||
|
"""
|
||||||
|
self.execute(["a2dissite", "000-default"], exception_on_error=True)
|
||||||
|
return super().init_service(context)
|
||||||
|
|
||||||
|
|
||||||
|
class OpenstackImagesSyncK8SCharm(sunbeam_charm.OSBaseOperatorAPICharm):
|
||||||
|
"""Charm the application."""
|
||||||
|
|
||||||
|
service_name = "openstack-images-sync"
|
||||||
|
mandatory_relations = {
|
||||||
|
"identity-service",
|
||||||
|
"ingress-public",
|
||||||
|
}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def service_conf(self) -> str:
|
||||||
|
"""Service default configuration file."""
|
||||||
|
return "/etc/openstack-images-sync/config.yaml"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def service_user(self) -> str:
|
||||||
|
"""Service user file and directory ownership."""
|
||||||
|
return "_daemon_"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def service_group(self) -> str:
|
||||||
|
"""Service group file and directory ownership."""
|
||||||
|
return "_daemon_"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def default_public_ingress_port(self) -> int:
|
||||||
|
"""Default ingress port."""
|
||||||
|
return 80
|
||||||
|
|
||||||
|
@property
|
||||||
|
def service_endpoints(self):
|
||||||
|
"""Describe the openstack images sync service endpoint."""
|
||||||
|
slash_region = "/" + self.config["region"].split()[0]
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"service_name": "image-stream",
|
||||||
|
"type": "product-streams",
|
||||||
|
"description": "Image stream service",
|
||||||
|
"internal_url": self.internal_url + slash_region,
|
||||||
|
"public_url": self.public_url + slash_region,
|
||||||
|
"admin_url": self.admin_url + slash_region,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def config_contexts(self) -> list[sunbeam_config_contexts.ConfigContext]:
|
||||||
|
"""Generate list of configuration adapters for the charm."""
|
||||||
|
return [
|
||||||
|
SyncCharmConfigContext(self, "options"),
|
||||||
|
# don't use wsgi-context here
|
||||||
|
HttpSyncConfigContext(self, "httpd_config"),
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_pebble_handlers(self) -> list[sunbeam_chandlers.PebbleHandler]:
|
||||||
|
"""Pebble handlers for the service."""
|
||||||
|
return [
|
||||||
|
OpenstackImagesSyncPebbleHandler(
|
||||||
|
self,
|
||||||
|
self.service_name,
|
||||||
|
self.service_name,
|
||||||
|
self.container_configs,
|
||||||
|
self.template_dir,
|
||||||
|
self.configure_charm,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def container_configs(self) -> list[sunbeam_core.ContainerConfigFile]:
|
||||||
|
"""Container configurations for the operator."""
|
||||||
|
_cconfigs = [
|
||||||
|
sunbeam_core.ContainerConfigFile(
|
||||||
|
self.service_conf,
|
||||||
|
self.service_user,
|
||||||
|
self.service_group,
|
||||||
|
0o640,
|
||||||
|
),
|
||||||
|
sunbeam_core.ContainerConfigFile(
|
||||||
|
"/etc/apache2/sites-enabled/http-sync.conf",
|
||||||
|
"root",
|
||||||
|
"root",
|
||||||
|
0o640,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
return _cconfigs
|
||||||
|
|
||||||
|
def keystone_auth(self) -> dict[str, str]:
|
||||||
|
"""Keystone authentication."""
|
||||||
|
if self.id_svc.ready:
|
||||||
|
interface: IdentityServiceRequires = self.id_svc.interface # type: ignore
|
||||||
|
return {
|
||||||
|
# Using public auth url because openstack-images-sync will output an index.json
|
||||||
|
# referencing this auth url. Later on, client will want to match the clouds and
|
||||||
|
# will use a combo of auth_url + region.
|
||||||
|
"OS_AUTH_URL": interface.public_auth_url,
|
||||||
|
"OS_IDENTITY_API_VERSION": "3",
|
||||||
|
"OS_USERNAME": interface.service_user_name,
|
||||||
|
"OS_PASSWORD": interface.service_password,
|
||||||
|
"OS_PROJECT_NAME": interface.service_project_name,
|
||||||
|
"OS_USER_DOMAIN_NAME": interface.service_domain_name,
|
||||||
|
"OS_PROJECT_DOMAIN_NAME": interface.service_domain_name,
|
||||||
|
}
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def proxy_env(self) -> dict[str, str]:
|
||||||
|
"""Get proxy settings from environment."""
|
||||||
|
juju_proxy_vars = [
|
||||||
|
"JUJU_CHARM_HTTP_PROXY",
|
||||||
|
"JUJU_CHARM_HTTPS_PROXY",
|
||||||
|
"JUJU_CHARM_NO_PROXY",
|
||||||
|
]
|
||||||
|
return {
|
||||||
|
proxy_var.removeprefix("JUJU_CHARM_"): value
|
||||||
|
for proxy_var in juju_proxy_vars
|
||||||
|
if (value := os.environ.get(proxy_var))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__": # pragma: nocover
|
||||||
|
ops.main(OpenstackImagesSyncK8SCharm) # type: ignore
|
@ -0,0 +1,20 @@
|
|||||||
|
cloud_name: {{ options.cloud_name}}
|
||||||
|
frequency: {{ options.frequency }}
|
||||||
|
mirrors:
|
||||||
|
- content_id: '%(region)s' # Content ID choice
|
||||||
|
custom_properties: {}
|
||||||
|
hypervisor_mapping: false
|
||||||
|
image_conversion: false
|
||||||
|
item_filters:
|
||||||
|
- release~({{ options.release }})
|
||||||
|
- arch~({{ options.architecture }})
|
||||||
|
- ftype~(disk1.img|disk.img)
|
||||||
|
keep_items: false
|
||||||
|
latest_property: false
|
||||||
|
max_items: {{ options.max_items }}
|
||||||
|
url: http://cloud-images.ubuntu.com/releases
|
||||||
|
path: streams/v1/index.sjson
|
||||||
|
regions: [{{ options.region }}]
|
||||||
|
visibility: public
|
||||||
|
name_prefix: auto-sync/
|
||||||
|
output_directory: /var/www/html/simplestreams
|
@ -0,0 +1,18 @@
|
|||||||
|
Listen {{ httpd_config.public_port }}
|
||||||
|
|
||||||
|
<VirtualHost *:{{ httpd_config.public_port }}>
|
||||||
|
DocumentRoot "/var/www/html/simplestreams"
|
||||||
|
|
||||||
|
{% if ingress_public and ingress_public.ingress_path %}
|
||||||
|
Alias {{ ingress_public.ingress_path }} "/var/www/html/simplestreams"
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<Directory "/var/www/html/simplestreams">
|
||||||
|
Options Indexes
|
||||||
|
AllowOverride None
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
ErrorLog {{ httpd_config.error_log }}
|
||||||
|
CustomLog {{ httpd_config.custom_log }} combined
|
||||||
|
</VirtualHost>
|
15
charms/openstack-images-sync-k8s/tests/unit/__init__.py
Normal file
15
charms/openstack-images-sync-k8s/tests/unit/__init__.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Copyright 2024 Canonical Ltd.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
"""Unit tests for charm."""
|
125
charms/openstack-images-sync-k8s/tests/unit/test_charm.py
Normal file
125
charms/openstack-images-sync-k8s/tests/unit/test_charm.py
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright 2024 Canonical Ltd.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
"""Tests for openstack images sync charm."""
|
||||||
|
import pathlib
|
||||||
|
|
||||||
|
import charm
|
||||||
|
import ops_sunbeam.test_utils as test_utils
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
charmcraft = (
|
||||||
|
pathlib.Path(__file__).parents[2] / "charmcraft.yaml"
|
||||||
|
).read_text()
|
||||||
|
config = yaml.dump(yaml.safe_load(charmcraft)["config"])
|
||||||
|
|
||||||
|
|
||||||
|
class _OISOperatorCharm(charm.OpenstackImagesSyncK8SCharm):
|
||||||
|
"""Openstack Images Sync test charm."""
|
||||||
|
|
||||||
|
def __init__(self, framework):
|
||||||
|
"""Setup event logging."""
|
||||||
|
self.seen_events = []
|
||||||
|
super().__init__(framework)
|
||||||
|
|
||||||
|
def _log_event(self, event):
|
||||||
|
"""Log events."""
|
||||||
|
self.seen_events.append(type(event).__name__)
|
||||||
|
|
||||||
|
def configure_charm(self, event):
|
||||||
|
"""Log configure charm call."""
|
||||||
|
super().configure_charm(event)
|
||||||
|
self._log_event(event)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def public_ingress_address(self):
|
||||||
|
"""Ingress address for charm."""
|
||||||
|
return "openstack-images-sync.juju"
|
||||||
|
|
||||||
|
|
||||||
|
class TestOISOperatorCharm(test_utils.CharmTestCase):
|
||||||
|
"""Classes for testing openstack images sync charms."""
|
||||||
|
|
||||||
|
PATCHES = []
|
||||||
|
maxDiff = None
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""Setup openstack images sync tests."""
|
||||||
|
super().setUp(charm, self.PATCHES)
|
||||||
|
self.harness = test_utils.get_harness(
|
||||||
|
_OISOperatorCharm,
|
||||||
|
charm_metadata=charmcraft,
|
||||||
|
container_calls=self.container_calls,
|
||||||
|
charm_config=config,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.addCleanup(self.harness.cleanup)
|
||||||
|
self.harness.begin()
|
||||||
|
|
||||||
|
def test_pebble_ready_handler(self):
|
||||||
|
"""Test Pebble ready event is captured."""
|
||||||
|
self.assertEqual(self.harness.charm.seen_events, [])
|
||||||
|
test_utils.set_all_pebbles_ready(self.harness)
|
||||||
|
self.assertEqual(self.harness.charm.seen_events, ["PebbleReadyEvent"])
|
||||||
|
|
||||||
|
def test_all_relations(self):
|
||||||
|
"""Test all the charms relations."""
|
||||||
|
self.harness.set_leader()
|
||||||
|
test_utils.set_all_pebbles_ready(self.harness)
|
||||||
|
test_utils.add_all_relations(self.harness)
|
||||||
|
id_svc_rel = self.harness.model.get_relation("identity-service")
|
||||||
|
self.harness.update_relation_data(
|
||||||
|
id_svc_rel.id, "keystone", {"service-domain-id": "svcdomid"}
|
||||||
|
)
|
||||||
|
test_utils.add_complete_ingress_relation(self.harness)
|
||||||
|
|
||||||
|
setup_cmds = [
|
||||||
|
["a2dissite", "000-default"],
|
||||||
|
]
|
||||||
|
for cmd in setup_cmds:
|
||||||
|
self.assertIn(
|
||||||
|
cmd,
|
||||||
|
self.container_calls.execute[self.harness.charm.service_name],
|
||||||
|
)
|
||||||
|
self.check_file(
|
||||||
|
self.harness.charm.service_name,
|
||||||
|
"/etc/apache2/sites-enabled/http-sync.conf",
|
||||||
|
)
|
||||||
|
expect_entries = """cloud_name: simplestreams-glance-sync
|
||||||
|
frequency: 3600
|
||||||
|
mirrors:
|
||||||
|
- content_id: '%(region)s' # Content ID choice
|
||||||
|
custom_properties: {}
|
||||||
|
hypervisor_mapping: false
|
||||||
|
image_conversion: false
|
||||||
|
item_filters:
|
||||||
|
- release~(focal|jammy)
|
||||||
|
- arch~(amd64)
|
||||||
|
- ftype~(disk1.img|disk.img)
|
||||||
|
keep_items: false
|
||||||
|
latest_property: false
|
||||||
|
max_items: 1
|
||||||
|
url: http://cloud-images.ubuntu.com/releases
|
||||||
|
path: streams/v1/index.sjson
|
||||||
|
regions: [RegionOne]
|
||||||
|
visibility: public
|
||||||
|
name_prefix: auto-sync/
|
||||||
|
output_directory: /var/www/html/simplestreams"""
|
||||||
|
self.check_file(
|
||||||
|
self.harness.charm.service_name,
|
||||||
|
"/etc/openstack-images-sync/config.yaml",
|
||||||
|
contents=expect_entries,
|
||||||
|
)
|
11
common.sh
11
common.sh
@ -70,6 +70,10 @@ INTERNAL_OPENSTACK_HYPERVISOR_LIBS=(
|
|||||||
"nova_k8s"
|
"nova_k8s"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
INTERNAL_OPENSTACK_IMAGES_SYNC_LIBS=(
|
||||||
|
"keystone_k8s"
|
||||||
|
)
|
||||||
|
|
||||||
INTERNAL_OVN_CENTRAL_LIBS=(
|
INTERNAL_OVN_CENTRAL_LIBS=(
|
||||||
"ovn_central_k8s"
|
"ovn_central_k8s"
|
||||||
)
|
)
|
||||||
@ -145,6 +149,10 @@ EXTERNAL_OPENSTACK_HYPERVISOR_LIBS=(
|
|||||||
"certificate_transfer_interface"
|
"certificate_transfer_interface"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
EXTERNAL_OPENSTACK_IMAGES_SYNC_LIBS=(
|
||||||
|
"traefik_k8s"
|
||||||
|
)
|
||||||
|
|
||||||
EXTERNAL_SUNBEAM_CLUSTERD_LIBS=(
|
EXTERNAL_SUNBEAM_CLUSTERD_LIBS=(
|
||||||
"operator_libs_linux"
|
"operator_libs_linux"
|
||||||
)
|
)
|
||||||
@ -321,6 +329,7 @@ declare -A INTERNAL_LIBS=(
|
|||||||
[octavia-k8s]=${INTERNAL_NEUTRON_LIBS[@]}
|
[octavia-k8s]=${INTERNAL_NEUTRON_LIBS[@]}
|
||||||
[openstack-exporter-k8s]=${INTERNAL_KEYSTONE_LIBS[@]}
|
[openstack-exporter-k8s]=${INTERNAL_KEYSTONE_LIBS[@]}
|
||||||
[openstack-hypervisor]=${INTERNAL_OPENSTACK_HYPERVISOR_LIBS[@]}
|
[openstack-hypervisor]=${INTERNAL_OPENSTACK_HYPERVISOR_LIBS[@]}
|
||||||
|
[openstack-images-sync-k8s]=${INTERNAL_OPENSTACK_IMAGES_SYNC_LIBS[@]}
|
||||||
[sunbeam-clusterd]=${NULL_ARRAY[@]}
|
[sunbeam-clusterd]=${NULL_ARRAY[@]}
|
||||||
[sunbeam-machine]=${NULL_ARRAY[@]}
|
[sunbeam-machine]=${NULL_ARRAY[@]}
|
||||||
[ovn-central-k8s]=${INTERNAL_OVN_CENTRAL_LIBS[@]}
|
[ovn-central-k8s]=${INTERNAL_OVN_CENTRAL_LIBS[@]}
|
||||||
@ -349,6 +358,7 @@ declare -A EXTERNAL_LIBS=(
|
|||||||
[octavia-k8s]=${EXTERNAL_OCTAVIA_LIBS[@]}
|
[octavia-k8s]=${EXTERNAL_OCTAVIA_LIBS[@]}
|
||||||
[openstack-exporter-k8s]=${EXTERNAL_OPENSTACK_EXPORTER_LIBS[@]}
|
[openstack-exporter-k8s]=${EXTERNAL_OPENSTACK_EXPORTER_LIBS[@]}
|
||||||
[openstack-hypervisor]=${EXTERNAL_OPENSTACK_HYPERVISOR_LIBS[@]}
|
[openstack-hypervisor]=${EXTERNAL_OPENSTACK_HYPERVISOR_LIBS[@]}
|
||||||
|
[openstack-images-sync-k8s]=${EXTERNAL_OPENSTACK_IMAGES_SYNC_LIBS[@]}
|
||||||
[sunbeam-clusterd]=${EXTERNAL_SUNBEAM_CLUSTERD_LIBS[@]}
|
[sunbeam-clusterd]=${EXTERNAL_SUNBEAM_CLUSTERD_LIBS[@]}
|
||||||
[sunbeam-machine]=${EXTERNAL_SUNBEAM_MACHINE_LIBS[@]}
|
[sunbeam-machine]=${EXTERNAL_SUNBEAM_MACHINE_LIBS[@]}
|
||||||
[ovn-central-k8s]=${EXTERNAL_OVN_CENTRAL_LIBS[@]}
|
[ovn-central-k8s]=${EXTERNAL_OVN_CENTRAL_LIBS[@]}
|
||||||
@ -377,6 +387,7 @@ declare -A CONFIG_TEMPLATES=(
|
|||||||
[octavia-k8s]=${CONFIG_TEMPLATES_OCTAVIA[@]}
|
[octavia-k8s]=${CONFIG_TEMPLATES_OCTAVIA[@]}
|
||||||
[openstack-exporter-k8s]=${CONFIG_TEMPLATES_HORIZON[@]}
|
[openstack-exporter-k8s]=${CONFIG_TEMPLATES_HORIZON[@]}
|
||||||
[openstack-hypervisor]=${NULL_ARRAY[@]}
|
[openstack-hypervisor]=${NULL_ARRAY[@]}
|
||||||
|
[openstack-images-sync-k8s]=${NULL_ARRAY[@]}
|
||||||
[sunbeam-clusterd]=${NULL_ARRAY[@]}
|
[sunbeam-clusterd]=${NULL_ARRAY[@]}
|
||||||
[sunbeam-machine]=${NULL_ARRAY[@]}
|
[sunbeam-machine]=${NULL_ARRAY[@]}
|
||||||
[ovn-central-k8s]=${NULL_ARRAY[@]}
|
[ovn-central-k8s]=${NULL_ARRAY[@]}
|
||||||
|
@ -129,6 +129,23 @@ applications:
|
|||||||
debug: true
|
debug: true
|
||||||
resources:
|
resources:
|
||||||
neutron-server-image: ghcr.io/canonical/neutron-server:2024.1
|
neutron-server-image: ghcr.io/canonical/neutron-server:2024.1
|
||||||
|
openstack-images-sync:
|
||||||
|
{% if openstack_images_sync_k8s is defined and openstack_images_sync_k8s is sameas true -%}
|
||||||
|
charm: ../../../openstack-images-sync-k8s.charm
|
||||||
|
{% else -%}
|
||||||
|
charm: ch:openstack-images-sync-k8s
|
||||||
|
channel: 2024.1/edge
|
||||||
|
{% endif -%}
|
||||||
|
base: ubuntu@22.04
|
||||||
|
scale: 1
|
||||||
|
trust: true
|
||||||
|
options:
|
||||||
|
frequency: test-do-not-use
|
||||||
|
architecture: amd64
|
||||||
|
release: jammy
|
||||||
|
max-items: 1
|
||||||
|
resources:
|
||||||
|
openstack-images-sync-image: ghcr.io/canonical/openstack-images-sync:2024.1
|
||||||
|
|
||||||
relations:
|
relations:
|
||||||
- - tls-operator:certificates
|
- - tls-operator:certificates
|
||||||
@ -193,3 +210,8 @@ relations:
|
|||||||
- ovn-central:ovsdb-cms
|
- ovn-central:ovsdb-cms
|
||||||
- - keystone:send-ca-cert
|
- - keystone:send-ca-cert
|
||||||
- neutron:receive-ca-cert
|
- neutron:receive-ca-cert
|
||||||
|
|
||||||
|
- - keystone:identity-service
|
||||||
|
- openstack-images-sync:identity-service
|
||||||
|
- - traefik:ingress
|
||||||
|
- openstack-images-sync:ingress-public
|
||||||
|
@ -9,6 +9,7 @@ configure:
|
|||||||
- zaza.openstack.charm_tests.nova.setup.manage_ssh_key
|
- zaza.openstack.charm_tests.nova.setup.manage_ssh_key
|
||||||
tests:
|
tests:
|
||||||
- zaza.openstack.charm_tests.tempest.tests.TempestTestWithKeystoneMinimal
|
- zaza.openstack.charm_tests.tempest.tests.TempestTestWithKeystoneMinimal
|
||||||
|
- zaza.sunbeam.charm_tests.openstack_images_sync_k8s.tests.OpenStackImagesSyncK8sTest
|
||||||
tests_options:
|
tests_options:
|
||||||
trust:
|
trust:
|
||||||
- smoke
|
- smoke
|
||||||
@ -67,3 +68,6 @@ target_deploy_status:
|
|||||||
neutron:
|
neutron:
|
||||||
workload-status: active
|
workload-status: active
|
||||||
workload-status-message-regex: '^$'
|
workload-status-message-regex: '^$'
|
||||||
|
openstack-images-sync:
|
||||||
|
workload-status: active
|
||||||
|
workload-status-message-regex: '^$'
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
# Copyright (c) 2024 Canonical Ltd.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
# implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
import zaza.openstack.charm_tests.test_utils as test_utils
|
||||||
|
from zaza.openstack.utilities import openstack as openstack_utils
|
||||||
|
|
||||||
|
from glanceclient.v2.client import Client as GlanceClient
|
||||||
|
import tenacity
|
||||||
|
|
||||||
|
class OpenStackImagesSyncK8sTest(test_utils.BaseCharmTest):
|
||||||
|
"""Charm tests for clusterd."""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
"""Run class setup for running tests."""
|
||||||
|
super(OpenStackImagesSyncK8sTest, cls).setUpClass(
|
||||||
|
application_name="openstack-images-sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
keystone_session = openstack_utils.get_overcloud_keystone_session()
|
||||||
|
cls.glance_client: GlanceClient = openstack_utils.get_glance_session_client(
|
||||||
|
keystone_session
|
||||||
|
)
|
||||||
|
|
||||||
|
@tenacity.retry(wait=tenacity.wait_fixed(10), stop=tenacity.stop_after_delay(180), reraise=True)
|
||||||
|
def _wait_for_images(self):
|
||||||
|
"""Wait for images to be downloaded."""
|
||||||
|
images = list(self.glance_client.images.list())
|
||||||
|
for image in images:
|
||||||
|
if image.name.startswith("auto-sync"):
|
||||||
|
return
|
||||||
|
raise ValueError("No auto-sync images found")
|
||||||
|
|
||||||
|
def test_100_check_autosync_images_downloaded(self):
|
||||||
|
"""Checking if glance as any auto-sync image."""
|
||||||
|
try:
|
||||||
|
self._wait_for_images()
|
||||||
|
except ValueError as e:
|
||||||
|
self.fail(str(e))
|
@ -274,6 +274,18 @@
|
|||||||
- rebuild
|
- rebuild
|
||||||
vars:
|
vars:
|
||||||
charm: openstack-hypervisor
|
charm: openstack-hypervisor
|
||||||
|
- job:
|
||||||
|
name: charm-build-openstack-images-sync-k8s
|
||||||
|
description: Build sunbeam openstack-images-sync-k8s charm
|
||||||
|
run: playbooks/charm/build.yaml
|
||||||
|
timeout: 3600
|
||||||
|
match-on-config-updates: false
|
||||||
|
files:
|
||||||
|
- ops-sunbeam/ops_sunbeam/*
|
||||||
|
- charms/openstack-images-sync-k8s/*
|
||||||
|
- rebuild
|
||||||
|
vars:
|
||||||
|
charm: openstack-images-sync-k8s
|
||||||
- job:
|
- job:
|
||||||
name: charm-build-sunbeam-machine
|
name: charm-build-sunbeam-machine
|
||||||
description: Build sunbeam-machine charm
|
description: Build sunbeam-machine charm
|
||||||
@ -317,6 +329,8 @@
|
|||||||
soft: true
|
soft: true
|
||||||
- name: charm-build-neutron-k8s
|
- name: charm-build-neutron-k8s
|
||||||
soft: true
|
soft: true
|
||||||
|
- name: charm-build-openstack-images-sync-k8s
|
||||||
|
soft: true
|
||||||
- name: charm-build-ovn-central-k8s
|
- name: charm-build-ovn-central-k8s
|
||||||
soft: true
|
soft: true
|
||||||
- name: charm-build-ovn-relay-k8s
|
- name: charm-build-ovn-relay-k8s
|
||||||
@ -328,6 +342,7 @@
|
|||||||
- charms/nova-k8s/*
|
- charms/nova-k8s/*
|
||||||
- charms/neutron-k8s/*
|
- charms/neutron-k8s/*
|
||||||
- charms/placement-k8s/*
|
- charms/placement-k8s/*
|
||||||
|
- charms/openstack-images-sync-k8s/*
|
||||||
- charms/ovn-central-k8s/*
|
- charms/ovn-central-k8s/*
|
||||||
- charms/ovn-relay-k8s/*
|
- charms/ovn-relay-k8s/*
|
||||||
- rebuild
|
- rebuild
|
||||||
@ -339,6 +354,7 @@
|
|||||||
- charm-build-nova-k8s
|
- charm-build-nova-k8s
|
||||||
- charm-build-placement-k8s
|
- charm-build-placement-k8s
|
||||||
- charm-build-neutron-k8s
|
- charm-build-neutron-k8s
|
||||||
|
- charm-build-openstack-images-sync-k8s
|
||||||
- charm-build-ovn-central-k8s
|
- charm-build-ovn-central-k8s
|
||||||
- charm-build-ovn-relay-k8s
|
- charm-build-ovn-relay-k8s
|
||||||
# test_dir relative to project src dir
|
# test_dir relative to project src dir
|
||||||
@ -448,6 +464,7 @@
|
|||||||
soft: true
|
soft: true
|
||||||
- name: charm-build-ovn-central-k8s
|
- name: charm-build-ovn-central-k8s
|
||||||
soft: true
|
soft: true
|
||||||
|
|
||||||
files:
|
files:
|
||||||
- ops-sunbeam/ops_sunbeam/*
|
- ops-sunbeam/ops_sunbeam/*
|
||||||
- charms/heat-k8s/*
|
- charms/heat-k8s/*
|
||||||
@ -486,6 +503,7 @@
|
|||||||
soft: true
|
soft: true
|
||||||
- name: charm-build-horizon-k8s
|
- name: charm-build-horizon-k8s
|
||||||
soft: true
|
soft: true
|
||||||
|
|
||||||
files:
|
files:
|
||||||
- ops-sunbeam/ops_sunbeam/*
|
- ops-sunbeam/ops_sunbeam/*
|
||||||
- charms/designate-k8s/*
|
- charms/designate-k8s/*
|
||||||
@ -774,6 +792,19 @@
|
|||||||
- charmhub_token
|
- charmhub_token
|
||||||
timeout: 3600
|
timeout: 3600
|
||||||
|
|
||||||
|
- job:
|
||||||
|
name: publish-charm-openstack-images-sync-k8s
|
||||||
|
description: |
|
||||||
|
Publish openstack-images-sync-k8s built in gate pipeline.
|
||||||
|
run: playbooks/charm/publish.yaml
|
||||||
|
files:
|
||||||
|
- ops-sunbeam/ops_sunbeam/*
|
||||||
|
- charms/openstack-images-sync-k8s/*
|
||||||
|
- rebuild
|
||||||
|
secrets:
|
||||||
|
- charmhub_token
|
||||||
|
timeout: 3600
|
||||||
|
|
||||||
- job:
|
- job:
|
||||||
name: publish-charm-ovn-central-k8s
|
name: publish-charm-ovn-central-k8s
|
||||||
description: |
|
description: |
|
||||||
|
@ -80,6 +80,8 @@
|
|||||||
nodeset: ubuntu-jammy
|
nodeset: ubuntu-jammy
|
||||||
- charm-build-openstack-hypervisor:
|
- charm-build-openstack-hypervisor:
|
||||||
nodeset: ubuntu-jammy
|
nodeset: ubuntu-jammy
|
||||||
|
- charm-build-openstack-images-sync-k8s:
|
||||||
|
nodeset: ubuntu-jammy
|
||||||
- charm-build-sunbeam-machine:
|
- charm-build-sunbeam-machine:
|
||||||
nodeset: ubuntu-jammy
|
nodeset: ubuntu-jammy
|
||||||
- charm-build-sunbeam-clusterd:
|
- charm-build-sunbeam-clusterd:
|
||||||
@ -133,6 +135,8 @@
|
|||||||
nodeset: ubuntu-jammy
|
nodeset: ubuntu-jammy
|
||||||
- charm-build-openstack-hypervisor:
|
- charm-build-openstack-hypervisor:
|
||||||
nodeset: ubuntu-jammy
|
nodeset: ubuntu-jammy
|
||||||
|
- charm-build-openstack-images-sync-k8s:
|
||||||
|
nodeset: ubuntu-jammy
|
||||||
- charm-build-sunbeam-machine:
|
- charm-build-sunbeam-machine:
|
||||||
nodeset: ubuntu-jammy
|
nodeset: ubuntu-jammy
|
||||||
- charm-build-sunbeam-clusterd:
|
- charm-build-sunbeam-clusterd:
|
||||||
@ -190,6 +194,8 @@
|
|||||||
nodeset: ubuntu-jammy
|
nodeset: ubuntu-jammy
|
||||||
- publish-charm-openstack-hypervisor:
|
- publish-charm-openstack-hypervisor:
|
||||||
nodeset: ubuntu-jammy
|
nodeset: ubuntu-jammy
|
||||||
|
- publish-charm-openstack-images-sync-k8s:
|
||||||
|
nodeset: ubuntu-jammy
|
||||||
- publish-charm-sunbeam-machine:
|
- publish-charm-sunbeam-machine:
|
||||||
nodeset: ubuntu-jammy
|
nodeset: ubuntu-jammy
|
||||||
- publish-charm-sunbeam-clusterd:
|
- publish-charm-sunbeam-clusterd:
|
||||||
|
@ -1,75 +1,75 @@
|
|||||||
- secret:
|
- secret:
|
||||||
name: charmhub_token
|
name: charmhub_token
|
||||||
data:
|
data:
|
||||||
# Generated on 2024-02-02T09:33:56+00:00 with 90 days ttl
|
# Generated on 2024-04-11T11:37:37+00:00 with 90 days ttl
|
||||||
value: !encrypted/pkcs1-oaep
|
value: !encrypted/pkcs1-oaep
|
||||||
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
keystone-ldap-k8s: 2024.1/edge
|
keystone-ldap-k8s: 2024.1/edge
|
||||||
openstack-exporter-k8s: 2024.1/edge
|
openstack-exporter-k8s: 2024.1/edge
|
||||||
openstack-hypervisor: 2024.1/edge
|
openstack-hypervisor: 2024.1/edge
|
||||||
|
openstack-images-sync-k8s: 2024.1/edge
|
||||||
sunbeam-machine: 2024.1/edge
|
sunbeam-machine: 2024.1/edge
|
||||||
sunbeam-clusterd: 2024.1/edge
|
sunbeam-clusterd: 2024.1/edge
|
||||||
tempest-k8s: 2024.1/edge
|
tempest-k8s: 2024.1/edge
|
||||||
|
Loading…
x
Reference in New Issue
Block a user