-
Notifications
You must be signed in to change notification settings - Fork 121
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
Move Mirroring Configuration to Individual Repositories #1086
base: main
Are you sure you want to change the base?
Conversation
Will continue after #1085 is merged. 😉 |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1086 +/- ##
============================================
+ Coverage 70.29% 70.37% +0.08%
- Complexity 4284 4443 +159
============================================
Files 427 442 +15
Lines 17258 17882 +624
Branches 1915 1974 +59
============================================
+ Hits 12131 12585 +454
- Misses 4077 4240 +163
- Partials 1050 1057 +7 ☔ View full report in Codecov by Sentry. |
commandExecutor.execute(Command.updateServerStatus(ServerStatus.REPLICATION_ONLY)) | ||
.get(1, TimeUnit.MINUTES); | ||
logger.info("Starting Mirrors migration ..."); | ||
if (commandExecutor instanceof ZooKeeperCommandExecutor) { | ||
logger.debug("Waiting for 10 seconds to make sure that all cluster have been notified of the " + | ||
"read-only mode ..."); | ||
Thread.sleep(10000); | ||
} |
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 prefer migrating without entering read-only mode because
- It's not critical if mirroring is temporarily unavailable for a minute.
- Any issues can be promptly addressed if they arise.
If this is acceptable, I will remove these lines of code. Please let me know your opinion.
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.
Agreed.
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.
Understood the changes
if (entries.isEmpty()) { | ||
return false; | ||
} | ||
repository.parent().name(); |
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.
repository.parent().name(); |
...java/com/linecorp/centraldogma/server/internal/storage/repository/DefaultMetaRepository.java
Outdated
Show resolved
Hide resolved
While reviewing this PR, I found out two bugs in |
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 couldn't fully review this PR. I will do another round tomorrow.
@@ -66,7 +67,7 @@ public CredentialServiceV1(ProjectApiManager projectApiManager, CommandExecutor | |||
* | |||
* <p>Returns the list of the credentials in the project. | |||
*/ | |||
@RequiresRepositoryRole(value = RepositoryRole.READ, repository = Project.REPO_META) | |||
@RequiresProjectRole(ProjectRole.MEMBER) |
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.
Currently, credentials are only exposed to owners in the UI. Do you want to allow members to read credentials? It may not be harmful since all sensitive information is masked.
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 need to allow the admin of each repository to read the credentials. Since it's read, I thought we could give the read permission to all members.
server/src/main/java/com/linecorp/centraldogma/server/internal/api/MirroringServiceV1.java
Show resolved
Hide resolved
* It is in the form of {@code "projects/<project>/credentials/<credential>"} or | ||
* {@code "projects/<project>/repos/<repo>/credentials/<credential>"}. | ||
*/ | ||
String mirrorCredentialId(); |
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 do you think of making
Credential
return the resource name instead?
The ownership of the resource belongs toCredential
so it would make more sense to delegate it such asCredential.resourceName()
orCredential.name()
?
https://google.aip.dev/122#fields-representing-resource-names
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.
Alright, let me try that. 😉
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.
@ikhoon
I tried that approach, but it seems to make the logic and codebase more complicated.
What do you think of just removing credential.id()
and using crendential.name()
as we do for representing an xDS resource?
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.
Never mind. Let me just add the resourceName field to the classes. 😉
throw new MirrorAccessException( | ||
"The mirroring from " + mirror.remoteRepoUri() + | ||
" is not allowed: " + | ||
mirrorKey.projectName + '/' + mirrorKey.mirrorId); |
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.
To apply the same approach as above here
mirrorKey.projectName + '/' + mirrorKey.mirrorId); | |
mirrorKey.repoName + '/' + mirrorKey.mirrorId); |
@@ -125,57 +152,124 @@ public CompletableFuture<Mirror> mirror(String id, Revision revision) { | |||
throw new RepositoryMetadataException("failed to load the mirror configuration", e); | |||
} | |||
|
|||
final CompletableFuture<List<Credential>> credentials; | |||
if (Strings.isNullOrEmpty(c.credentialId())) { |
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.
nit:
if (Strings.isNullOrEmpty(c.credentialId())) { | |
if (c.credentialId().isEmpty()) { |
for (Credential c : credentials) { | ||
private Credential findCredential(Map<String, List<Credential>> repoCredentials, | ||
List<Credential> projectCredentials) { | ||
if (repoCredential) { |
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.
Suggestion) This logic seems complicated to be included in a data class. What do you think of extracting the methods to MirrorConverter
?
continue; | ||
} | ||
final MirrorConfig newMirrorConfig = mirrorConfig.withCredentialId( | ||
projectMirrorCredentialId(repository.parent().name(), mirrorConfig.credentialId())); |
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.
Should we skip migration for a MirrorConfig
whose the credential ID starts with projects/
? Because we don't rollback if the migration process is halt somehow. This migration could be partially applied.
|
||
final List<String> credentialRepoNames; | ||
final boolean hasProjectCredential; | ||
if (c.repoCredential()) { |
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.
Suggestion) What do you think of adding a new resource repository layer to find a credential from a given ID? This logic could be simplified as we don't have to care if the ID is a repo credential.
interface MetaResourceRepository {
T find(String resourceName, Class<T> clazz);
}
Credential credential = repositoryRepository.find(mirror.credentialId(), Credential.class);
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 used this logic not to fetch the resource one by one when multiple credentials are needed to be found. Let me encapsulate the logic into another class then.
commandExecutor.execute(Command.updateServerStatus(ServerStatus.REPLICATION_ONLY)) | ||
.get(1, TimeUnit.MINUTES); | ||
logger.info("Starting Mirrors migration ..."); | ||
if (commandExecutor instanceof ZooKeeperCommandExecutor) { | ||
logger.debug("Waiting for 10 seconds to make sure that all cluster have been notified of the " + | ||
"read-only mode ..."); | ||
Thread.sleep(10000); | ||
} |
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.
Agreed.
Motivation:
Mirroring configurations should belong to the repository where the mirroring is executed to ensure proper ownership and management alignment.
Modifications:
projects/foo/credentials/foo-credential
.projects/foo/repos/bar/credentials/bar-credential
.Result: