-
Notifications
You must be signed in to change notification settings - Fork 11
Feat: Support to accept the response of signing result from RADAS #294
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
Conversation
f017afb to
7a82d79
Compare
Pull Request Test Coverage Report for Build 15177290271Details
💛 - Coveralls |
charon/config.py
Outdated
| self.__quay_radas_auth_enabled: bool = data.get("quay_radas_auth_enabled", False) | ||
| self.__quay_radas_registry: str = data.get("quay_radas_registry", None) | ||
| self.__quay_radas_username: str = data.get("quay_radas_username", None) | ||
| self.__quay_radas_password: str = data.get("quay_radas_password", None) |
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.
These quay specified items should not be set through configuration. they should be specified through cmd flag.
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.
@ligangty, if through cmd flags, might need to transfer the flags values when setup umb client(sign request send) with umb listener register, since this will be used for on_message. But could you help to explain why it needs to be specified through cmd flag?
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 registry is a variable one but not fixed for different product packages. For example, eap will have different registry than quarkus one, and for different qurakus versions, the registry will also have different version tags in quay.
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.
and for the username and password, maybe we will use another way like registry-config file. See "oras --registry-config" for details.
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.
@ligangty Just for sure, you mean the registry host(https://quay.io/repository/signing/radas) will be changed for different products? This properties are just used for login, it means oras just needs hostname. For tags, it should be used for pull and we could get that from the result_reference url.
So,
- Maybe we don't need quay_radas_registry, just get the hostname from the result_reference url extracting, CMIMW.
- For the registry-config file, does it store in any env loc for different products, or still from user cmd input flags?
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.
Maybe we don't need quay_radas_registry, just get the hostname from the result_reference url extracting, CMIMW.
Agree with this.
For the registry-config file, does it store in any env loc for different products, or still from user cmd input flags?
FWIK now, the registry is a public one which don't need auth. So maybe for first version we will not care auth issue. For the registry-config file, I think it will be a configmap or secret later in openshift managed workspace.
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.
@ligangty So, I just file a quay_radas_registry_config.py and we could enhance more if it needs in future, or just ignore the login part, WDYT?
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.
Maybe you can directly add them to the RadasConfig class in my new merged PR?
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.
@ligangty Sure, will adjust that.
charon/config.py
Outdated
| self.__quay_radas_password: str = data.get("quay_radas_password", None) | ||
| self.__radas_sign_enabled: bool = data.get("radas_sign_enabled", False) | ||
| self.__radas_sign_timeout_count: int = data.get("radas_sign_timeout_count", 10) | ||
| self.__radas_sign_wait_interval_sec: int = data.get("radas_sign_wait_interval_sec", 60) |
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.
What's the difference between the interval and timeout here?
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.
@ligangty timeout_count means the number of retries, interval means the time for per sleep, maybe rename them as 'radas_sign_timeout_retry_count' and 'radas_sign_timeout_retry_interval' would be more explicit.
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.
Sounds good.
charon/config.py
Outdated
| self.__aws_cf_enable: bool = data.get("aws_cf_enable", False) | ||
| self.__amqp_queue: str = data.get("amqp_queue", None) | ||
| self.__sign_result_loc: str = data.get("sign_result_loc", None) | ||
| self.__quay_radas_auth_enabled: bool = data.get("quay_radas_auth_enabled", False) |
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.
Is this auth_enabled needed? I think if the user/pass is not provided, it means the auth is not enabled, vice versa.
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.
@ligangty ok, sure.
charon/config.py
Outdated
| self.__signature_command: str = data.get("detach_signature_command", None) | ||
| self.__aws_cf_enable: bool = data.get("aws_cf_enable", False) | ||
| self.__amqp_queue: str = data.get("amqp_queue", None) | ||
| self.__sign_result_loc: str = data.get("sign_result_loc", None) |
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.
@yma96 I think this one is also needed to be passed by cmd flag. The cause is that we should store this in Konflux workspace storage, but the path to this workspace is a variable which is passed by Konflux for each release pipeline run. That means it will always change and we don't know the exact value. So the only way here is give it through flag and then we can specify it through Konflux shell environment.
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.
@ligangty, ok, make sense.
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.
@yma96 BTW, can I ask this "sign_result_loc" 's purpose? Is it used to store the sign result bundle or extracted signing files?
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.
@ligangty, this's used to store the oras pull result json file from radas quay registry, and let maven-publish could detect this file to handle the following .asc files generation, the final singing files will be generated directly alongside the artifact.
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.
@yma96 Oh ok. Where will you want to process this file in charon? During the maven uploading phase?
What I want to check here is because the "sign" and the "process" may happen in different command(Should it?), so we need to know how to pass this file between these two command.
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.
@ligangty, this "sign_result_loc" should only be used for "sign"(when message received), oras pulls the files result to this loc and store the files result into the SignHandler:_downloaded_files, and we could use classmethod get_downloaded_files to detect the files result during "process"(when maven upload), since this kind of class method is bound to the class and not the instance of the class, so that could be shared by all instances/clsName call. Through this python feature, we may not need to transfer this value across two commands.
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.
@yma96 one big issue is "sign" and "maven_upload" are not happend in same time. In later Konflux usage, they are called in different tasks with two command call. That means we could not use any memory way (like you said for the classmethod) to store these files. We should store them into a Konflux reachable storage between different tasks. That's why I proposed to use a flag to pass this file location.
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.
@ligangty Ok, I just think of a flag to detect, not aware of the sign is a dependent task, so the SignHandler status management here should not be workable, and the corresponding process status handling should be adjusted too.
How about environ SIGN_RESULT_LOC for sign_result_loc after sign msg received? For maven upload, could it be able to fetch the env SIGN_RESULT_LOC across different tasks?
Or just open this flag for both of the two tasks, and Konflux could help to transfer that sequentially?
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.
@yma96 the env var is not shared between two tekton tasks. That's why the task is using the "result"(see https://medium.com/@email2smohanty/passing-values-between-tekton-tasks-using-task-results-9ac89a44b2b9). What I'm thinking here is passing this sign_result_loc into sign command in sign task, and then store it in to task result. Then extract it in the maven upload task by passing it to maven upload command.
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.
@ligangty, make sense, so both of the two tasks would open this loc as the cmd flag IIUC.
74c94d4 to
8931a7f
Compare
charon/config.py
Outdated
| self.__ignore_signature_suffix: Dict = data.get("ignore_signature_suffix", None) | ||
| self.__signature_command: str = data.get("detach_signature_command", None) | ||
| self.__aws_cf_enable: bool = data.get("aws_cf_enable", False) | ||
| self.__radas_config_enable: bool = data.get("radas_config_enable", False) |
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.
After thinking, we don't need an extra "enable" here, instead we can use "radas_config and radas_config.validate" to decide if radas is enabled.
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.
@ligangty sounds good, already update in the new commit, BTW I've committed code in the different commits with different aspects mentioned in the review, which might be more convenient to check.
charon/config.py
Outdated
| self.__radas_config_enable: bool = data.get("radas_config_enable", False) | ||
| radas_config: Dict = data.get("radas", None) | ||
| if radas_config: | ||
| self.__radas_config_enable = True |
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.
See above.
charon/config.py
Outdated
| return self.__aws_cf_enable | ||
|
|
||
| def is_radas_config_enable(self) -> bool: | ||
| return self.__radas_config_enable |
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.
we can use "radas_config and radas_config.validate()" to decide if it is enabled.
815dc4d to
e906e92
Compare
charon/config.py
Outdated
| self.__quay_radas_registry_config, os.R_OK | ||
| ): | ||
| logger.error("The quay registry config for oras is not valid!") | ||
| return False |
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.
Maybe this should not fail the radas config, but just give a warn message and leave this registry_config as None, which means we will consider it as a public registry without authentication.
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.
e391260 to
85fae74
Compare
|
|
||
| def is_aws_cf_enable(self) -> bool: | ||
| return self.__aws_cf_enable | ||
|
|
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.
I'm thinking we should add a __is_radas_enabled field here for convenient, which set to self.__radas_config__ and self.__radas_config__.validate(). So then we can use this with a get method is_radas_enabled() for unified way in other place to check if radas is usable.
| """ | ||
| conf = get_config() | ||
| rconf = conf.get_radas_config() if conf else None | ||
| if not rconf: |
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.
so maybe here we can also use not conf.is_radas_enabled()?
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.
96684b7 to
a4ad9e0
Compare
| logger.info("Number of files pulled: %d, path: %s", len(files), files[0]) | ||
|
|
||
|
|
||
| def generate_radas_sign(top_level: str, sign_result_loc: str) -> Tuple[List[str], List[str]]: |
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.
Do you think we should add some utests for this method to make sure it works as expectation?
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.
@ligangty Yeah, I want to add the unit test for this feat, sign result parse and generation, etc, might need some mock if more thorough , I could file a unit test JIRA for this, WDYT?
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.
@yma96 sure ok.
| wait_count = 0 | ||
|
|
||
| # Wait until files appear in the sign_result_loc directory | ||
| while True: |
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.
I don't think we need to wait here, because this this gen_file method should make sure the result_file is ready. If it is not, that means the umblistener already failed with some reasons, which does not retrieve the result correctly.
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.
@ligangty It takes time from sending the sign request to receiving and processing the message, if maven_upload is called immediately or in quite short time, no wait will lead to no sign result.
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.
@yma96 we need to make sure that the sign command has fixed result, like has this result file downloaded as success state or got some error as failure state. If succeeded then we can proceed the maven upload, vice visa the maven upload will never be triggered. This means all wait control should happen in umb receiver processing but not in maven processing.
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.
@ligangty You mean the sign task should have a state return for the sign result, which could be used to trigger the maven-upload, something like:
- name: maven-upload
when:
- input: "$(tasks.sign-cmd.results.is-signed-proccessed)"
operator: in
values: ["run"]
That might need the listener on_message is handled in a sync way, or I'm afraid sign task would not wait until the on_message is received and process ends.
Generally, proton client register the listener then container.run() automatically and keeps the event loop running until connections close. We may need another container.process() to perform the specific loop, when the sign receiver and process is not done. That is to say, we may need to consider the sign request and sign receive as a whole in the first sign task, CMIMW.
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.
@yma96
You mean the sign task should have a state return for the sign result, which could be used to trigger the maven-upload, something like:
- name: maven-upload
when:
- input: "$(tasks.sign-cmd.results.is-signed-proccessed)"
operator: in
values: ["run"]
What I mean is similar but we will not bring a new stuff like this is-signed-processed. We just pass the sign_result_loc between task, or failed the sign task if error happened, which will break the whole process.
That might need the listener on_message is handled in a sync way, or I'm afraid sign task would not wait until the on_message is received and process ends.
Generally, proton client register the listener then container.run() automatically and keeps the event loop running until connections close. We may need another container.process() to perform the specific loop, when the sign receiver and process is not done. That is to say, we may need to consider the sign request and sign receive as a whole in the first sign task, CMIMW.
I'm thinking we can use the main thread to control the sync process like what you have done in the maven_upload now, which checks and waits the sign file downloaded or error happened. I really don't want to bring more complexity into the maven process as this complexity is introduced by radas but not maven itself. If possible we'd keep the complexity in radas_sign process itself.
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.
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.
@yma96 Yes. We will have a function like "sign_in_radas()" in main thread which will be called in the cli part. It will be responsible to do the overall controlling of the whole process, like trigger the send and register the receiver, and control the wait and timeout there.
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.
I've created a PR which construct the skeleton of the sign command here: https://github.com/Commonjava/charon/pull/296/files
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.
ligangty
left a comment
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.
I think we can merge this. If any changes or fixes let's use separate PR later.
Let me know if we have other preferred branch rather than main, @ligangty