-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a basic manifest repository implementation #1
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
97 changes: 97 additions & 0 deletions
97
drydock/manifest_builder/infrastructure/tutor_based_manifests.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
""" | ||
Collection of tutor based renderers for Kubernetes manifests. | ||
""" | ||
import os | ||
import shutil | ||
import tempfile | ||
from os.path import join as path_join | ||
|
||
import pkg_resources | ||
from tutor import env as tutor_env | ||
from tutor import fmt, hooks | ||
|
||
from drydock.manifest_builder.domain.config import DrydockConfig | ||
from drydock.manifest_builder.domain.manifest_repository import ManifestRepository | ||
|
||
|
||
class BaseManifests(ManifestRepository): | ||
"""Baseline of Kubernetes configuration repository. | ||
|
||
Generates an environment based on Tutor with the relevant Kubernetes configuration | ||
to be tracked by version control. | ||
""" | ||
TEMPLATE_ROOT = "kustomized/tutor13" | ||
TEMPLATE_TARGETS = [ | ||
f"{TEMPLATE_ROOT}/base", | ||
f"{TEMPLATE_ROOT}/extensions", | ||
f"{TEMPLATE_ROOT}/kustomization.yml", | ||
] | ||
|
||
def __init__(self, options: dict) -> None: | ||
"""Initialize the class based on the `manifest_options` from the reference. | ||
|
||
Parameters | ||
---------- | ||
options: dict | ||
Defines additional configuration options for the generations of the | ||
configuration repository. | ||
|
||
- ["output"]: Name of the directory to store the manifests. | ||
""" | ||
self.output_dir = options.get("output", "drydock-env") | ||
|
||
def render(self, root: str, config: DrydockConfig) -> None: | ||
"""Register drydock custom templates and render a tutor env.""" | ||
with hooks.Contexts.APP("drydock-base").enter(): | ||
hooks.Filters.ENV_TEMPLATE_ROOTS.add_item(pkg_resources.resource_filename("drydock", "templates")) | ||
hooks.Filters.ENV_TEMPLATE_TARGETS.add_items( | ||
[ | ||
(target, "drydock") for target in self.TEMPLATE_TARGETS | ||
], | ||
) | ||
tutor_env.save(root, config.get_data()) | ||
hooks.Filters.ENV_TEMPLATE_ROOTS.clear(context=hooks.Contexts.APP("drydock-base").name) | ||
hooks.Filters.ENV_TEMPLATE_TARGETS.clear(context=hooks.Contexts.APP("drydock-base").name) | ||
|
||
def relocate_env(self, src: str, dst: str) -> None: | ||
"""Moves the drydock rendered templates and tutor plugins to src. | ||
|
||
At the moment we render a full tutor env with our templates under | ||
'env/drydock/default'. The final drydock env is the one in 'env/drydock' | ||
**plus** the plugin directory that has to be manually relocated to | ||
'env/drydock/base/plugins'. | ||
|
||
Parameters | ||
---------- | ||
src: str | ||
The inital path where the full tutor env was rendered. | ||
dst: str | ||
The path to save the final drydock env. | ||
""" | ||
base_dir = path_join(src, "env/drydock", f"{self.TEMPLATE_ROOT}") | ||
plugins_dir = path_join(src, "env/plugins") | ||
shutil.move(base_dir, dst) | ||
if os.path.exists(plugins_dir): | ||
shutil.move(plugins_dir, path_join(dst, "base")) | ||
|
||
def save(self, config: DrydockConfig) -> None: | ||
"""Creates an alternative tutor env with the base openedx installation. | ||
|
||
The generated env consists of a Kustomize application that uses the original | ||
tutor env as a base in addition to an `extensions` overlay to include additional | ||
resources. | ||
|
||
Parameters | ||
---------- | ||
config: DrydockConfig | ||
A Tutor configuration extension. | ||
""" | ||
tutor_root = config.get_root() | ||
dst = path_join(tutor_root, self.output_dir) | ||
with tempfile.TemporaryDirectory() as tmpdir: | ||
src = path_join(tmpdir) | ||
self.render(src, config) | ||
shutil.rmtree(path=dst, ignore_errors=True) | ||
self.relocate_env(src, dst) | ||
|
||
fmt.echo_info(f"Drydock environment generated in {dst}") | ||
mariajgrimaldi marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,65 @@ | ||
from abc import abstractmethod | ||
from tutor import config as tutor_config | ||
import pkg_resources | ||
import tutor | ||
import yaml | ||
|
||
from drydock.manifest_builder.domain.config import DrydockConfig | ||
|
||
|
||
class TutorConfig(DrydockConfig): | ||
|
||
def __init__(self, context, options: dict): | ||
self.context = context | ||
self.options = options | ||
|
||
def get_data(self) -> dict: | ||
config = tutor_config.load_full(self.context.obj.root) | ||
config = tutor.config.load_full(self.context.obj.root) | ||
return config | ||
|
||
def get_root(self) -> dict: | ||
return self.context.obj.root | ||
|
||
|
||
class TutorExtendedConfig(DrydockConfig): | ||
"""Drydock configuration based on tutor.""" | ||
DEFAULT_TEMPLATE_SET = "kustomized/tutor13" | ||
|
||
def __init__(self, context, options: dict): | ||
"""Initialize the class based on the `config_options` from the manifest. | ||
|
||
Parameters | ||
---------- | ||
context: clic.core.Context | ||
context of the current Tutor command. | ||
options: dict | ||
|
||
- ["template_set"]: template set to render default values from. | ||
""" | ||
self.context = context | ||
self.options = options | ||
|
||
def get_data(self) -> dict: | ||
"""Return tutor config values using a template set defaults as fallback. | ||
|
||
Retrieve the Tutor configuration values for the current TUTOR_ROOT and | ||
use the the values in `defaults.yml` of the chosen template set | ||
|
||
Returns | ||
------- | ||
base: dict | ||
Tutor configuration values taken from the config.yml at the TUTOR_ROOT | ||
using the defaults from the template set as a fallback. | ||
""" | ||
template_set = self.options.get("template_set", self.DEFAULT_TEMPLATE_SET) | ||
|
||
try: | ||
defaults_path = pkg_resources.resource_filename("drydock", f"templates/{template_set}/defaults.yml") | ||
with open(defaults_path, encoding="utf-8") as file: | ||
base = yaml.safe_load(file) | ||
except FileNotFoundError: | ||
base = {} | ||
|
||
config = tutor.config.load_full(self.get_root()) | ||
base.update(config) | ||
return base | ||
|
||
def get_root(self) -> str: | ||
return self.context.obj.root |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# The kustomized_v13 reference is a Kustomize based instalation that uses the environment | ||
# generated by tutor v13.3.1 as a Base with additional resources such as an ingress and | ||
# a flower deployment used as overlays. | ||
# | ||
drydock: | ||
builder_class: drydock.manifest_builder.application.manifest_builder.ManifestBuilder | ||
config_class: drydock.manifest_builder.infrastructure.tutor_config.TutorConfig | ||
manifest_class: drydock.manifest_builder.infrastructure.tutor_based_manifests.BaseManifests | ||
manifest_options: | ||
output: "drydock-environment" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Drydock Templates | ||
|
||
The inventory of template sets used by drydock. | ||
|
||
## Template list | ||
|
||
1. `kustomized/tutor13`: Kubernetes focused template set. Uses the templates from Tutor v13 as a Kustomize | ||
base (rendered in the `base` directory) and adds additional resources as an overlay in the | ||
`extensions` directory. | ||
The additional resources include: | ||
|
||
```yaml | ||
- flowers.yml # A flowers deployment to track celery tasks. | ||
- hpa.yml # An Horizontal Pod Autoscaler for lms, cms and workers. | ||
- ingress.yml # An ingress with certmanager to use instead of caddy as web proxy. | ||
``` | ||
|
||
The list of variables with their default values can be found in [defaults.yml](kustomized/tutor13/defaults.yml) | ||
|
||
<details> | ||
<summary>List of patches</summary> | ||
|
||
``` | ||
{{ patch("drydock-kustomization-resources")}} | ||
{{ patch("drydock-kustomization-patches")}} | ||
{{ patch("drydock-overrides") }} | ||
``` | ||
</details> | ||
|
||
2. `tutor/v13`: Small subset of templates from Tutor v13. Mostly as a proof con concept. | ||
|
||
3. `tutor/v13`: Small subset of templates from Tutor v12. Mostly as a proof con concept. |
62 changes: 62 additions & 0 deletions
62
drydock/templates/kustomized/tutor13/base/apps/caddy/Caddyfile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# Global configuration | ||
{ | ||
{{ patch("caddyfile-global")|indent(4) }} | ||
} | ||
|
||
# proxy directive snippet (with logging) to be used as follows: | ||
# | ||
# import proxy "containername:port" | ||
(proxy) { | ||
log { | ||
output stdout | ||
format filter { | ||
wrap json | ||
fields { | ||
common_log delete | ||
request>headers delete | ||
resp_headers delete | ||
tls delete | ||
} | ||
} | ||
} | ||
|
||
reverse_proxy {args.0} { | ||
header_up X-Forwarded-Port {{ 443 if ENABLE_HTTPS else 80 }} | ||
} | ||
} | ||
|
||
{{ LMS_HOST }}{$default_site_port}, {{ PREVIEW_LMS_HOST }}{$default_site_port} { | ||
@favicon_matcher { | ||
path_regexp ^/favicon.ico$ | ||
} | ||
rewrite @favicon_matcher /theming/asset/images/favicon.ico | ||
|
||
# Limit profile image upload size | ||
request_body /api/profile_images/*/*/upload { | ||
max_size 1MB | ||
} | ||
request_body { | ||
max_size 4MB | ||
} | ||
|
||
import proxy "lms:8000" | ||
|
||
{{ patch("caddyfile-lms")|indent(4) }} | ||
} | ||
|
||
{{ CMS_HOST }}{$default_site_port} { | ||
@favicon_matcher { | ||
path_regexp ^/favicon.ico$ | ||
} | ||
rewrite @favicon_matcher /theming/asset/images/favicon.ico | ||
|
||
request_body { | ||
max_size 250MB | ||
} | ||
|
||
import proxy "cms:8000" | ||
|
||
{{ patch("caddyfile-cms")|indent(4) }} | ||
} | ||
|
||
{{ patch("caddyfile") }} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is my current folder structure:
My tutor plugins list:
Then I run:
tutor drydock save -r reference.yml
When the command finishes, I run:
tutor plugins list
And this happens:
Is that okay?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes (actually is not ok, but is a current limitation). At the moment we don't render module nor yaml plugins on
base/plugins
. The current workaround is to define theTUTOR_PLUGINS_ROOTS
outsideenv
.The folder structure would look something like this:
and your
TUTOR_PLUGINS_ROOT
should be something like$TUTOR_ROOT/plugins