Skip to content
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

Ask question only once #1459

Closed
henningWoehr opened this issue Dec 20, 2023 · 3 comments
Closed

Ask question only once #1459

henningWoehr opened this issue Dec 20, 2023 · 3 comments

Comments

@henningWoehr
Copy link

henningWoehr commented Dec 20, 2023

Actual Situation

We are using copier, to copy kubernetes manifests of app to a repo (set name, namespace and app specific stuff). After deploying that app on kubernetes, changing the name or namespace is pretty difficult when using something like a persistent volume.

Desired Situation

When answering the questions like name or namespace of a resource, it shouldn't be allowed to change these afterwards to force a clean deletion and new creation of the app. Otherwise it could lead to multiple instances of the app and the deletion of each resource would be a hassle.

Proposed solution

Current Solution

My current workaround to this consists of the following:

In the copier.yaml I specify the question with the when key checking if the question already has a value. If so, skip this answer

resource_name:
  when: "{{ not resource_name }}"
  type: str
  help: What is the name for the resources which will be applied in k8s? (Can't be changed afterwards)
  default: container-registry
  validator: "{{resource_name | validate_dns_name}}"

Because questions won't get saved in the answers.yaml, on the third copy/update the questions would be asked again. For that I use the ContextHook and write the answer in into the _copier_answers dict in the context.

from copier_templates_extensions import ContextHook

CONST_QUESTIONS = [
    "resource_name",
    "resource_namespace"
]

class ConstQuestions(ContextHook):
    update = False

    def hook(self, context: dict):
        for question in CONST_QUESTIONS:
            context["_copier_answers"][question] = context.get(question)

Possible Solution

The problem with my solution is that we will never see the answered question again. Nice would be, that the answered question would be grey instead of yellow.

Possible copier.yaml:

resource_name:
  type: str
  help: What is the name for the resources which will be applied in k8s? (Can't be changed afterwards)
  answer_once: true
  default: container-registry
  validator: "{{resource_name | validate_dns_name}}"
@debo

This comment was marked as off-topic.

@yajo
Copy link
Member

yajo commented Dec 25, 2023

@debo that's a different subject. I marked your comment as off-topic to keep the conversation focused. Feel free to open a new issue or discussion about that.

Back into the subject, it's not a trivial request. Adding support for this would require completely refactoring the logic of how and why we manage the state of the project, which is tailored to our use case.

The use case for copier as a tool is to let you provide new answers and make those answers change the resulting project. This thing you want fits more into a validation tool, such as a pre-commit hook, CI or linter, that forbids unwanted changes. After all, what if you do that change manually, without copier involved? You'd also delete the cluster resources...

However you can be creative. For example, you could deploy your manifests with kustomize, and set the name and namespace in a patch file. Then, add that file to _skip_if_exists and copier won't update it anymore.

If I don't want users to update values of a question, I'd just add a big warning in the question help.

Another option would be to use a validation based on a computed previous value. I haven't tested this but it could help:

old:
  type: str
  when: false
  default: '{{ resource_name|d("") }}'

resource_name:
  type: str
  help: What is the name for the resources which will be applied in k8s? (Can't be changed afterwards)
  answer_once: true
  default: container-registry
  validator: "{{not old or resource_name == old}}"

@yajo
Copy link
Member

yajo commented Dec 25, 2023

Closing because I think there's nothing we could or should do here, but please feel free to continue with the discussion. Thanks for reaching out!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants