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

[OSPP]Support Kubernetes ConfigMap for Apollo java, golang client #79 #318

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

dyx1234
Copy link

@dyx1234 dyx1234 commented Sep 14, 2024

What's the purpose of this PR

解决Apollo客户端在Kubernetes环境下因服务端宕机或Pod重启导致配置信息文件丢失的问题。通过使用Kubernetes ConfigMap作为新的持久化存储方案,提高配置信息的可靠性和容错性。

Solve the problem of Apollo client configuration information files being lost due to server downtime or Pod restart in the Kubernetes environment. By using Kubernetes ConfigMap as a new persistent storage solution, the reliability and fault tolerance of configuration information are improved.

discussion apolloconfig/apollo#5210

Summary by CodeRabbit

  • New Features

    • Introduced configuration management for Kubernetes ConfigMaps, enhancing integration capabilities.
    • Added options for backup configurations to ConfigMaps, providing more flexibility in configuration management.
    • Implemented a centralized handler for managing ConfigMap data.
  • Bug Fixes

    • Improved error handling during configuration loading processes.
  • Tests

    • Added unit tests for the new ConfigMap functionalities to ensure reliability and correctness.
  • Chores

    • Updated dependencies and Go version to enhance module capabilities and compatibility.

Copy link

coderabbitai bot commented Sep 14, 2024

Walkthrough

The changes introduce a configuration management feature that integrates Kubernetes ConfigMaps into the agollo package. This includes adding a handler for ConfigMaps, enhancing the loadBackupConfig function to support loading configurations from ConfigMaps, and modifying the AppConfig struct to include new fields for backup configurations. New files are created for managing ConfigMaps and testing their functionality. Additionally, the go.mod file is updated with new dependencies for Kubernetes support and testing. Overall, the modifications enhance the flexibility and functionality of configuration management within the application.

Changes

Files Change Summary
client.go, component/remote/async.go, env/config/config.go, extension/configmap.go, extension/configmap_test.go, start.go, start_test.go, storage/repository.go, storage/repository_test.go, store/configMap/manager.go, store/configMap/manager_test.go, store/configMap/store.go, store/configMap/store_test.go, store/configmap.go Introduced configuration management for Kubernetes ConfigMaps, including handlers, loading and writing methods, and testing functionalities. Added fields to AppConfig for backup configurations. Updated go.mod with new dependencies for Kubernetes and testing.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant App
    participant ConfigMapHandler
    participant K8sManager

    User->>App: Request Configuration
    App->>ConfigMapHandler: Load ConfigMap
    ConfigMapHandler->>K8sManager: Get ConfigMap
    K8sManager-->>ConfigMapHandler: Return ConfigMap Data
    ConfigMapHandler-->>App: Return Loaded Configuration
    App-->>User: Provide Configuration
Loading

🐰 "In the garden of code, changes bloom bright,
With ConfigMaps dancing, a wonderful sight.
Kubernetes whispers, 'Manage with ease,'
As backups now flourish, like leaves in the breeze.
Hops of joy echo, for features anew,
In the patchwork of logic, our dreams now come true!" 🌼

Tip

OpenAI O1 model for chat
  • We have deployed OpenAI's latest O1 model for chat.
  • OpenAI claims that this model has superior reasoning capabilities than their GPT-4o model.
  • Please share any feedback with us in the discussions post.

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

mergify bot commented Sep 14, 2024

感谢您提出Pull Request,我会尽快Review。我会在1-2日内进行查看或者回复,如果遇到节假日可能会处理较慢,敬请谅解。

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Outside diff range and nitpick comments (2)
store/configMap/store_test.go (2)

52-99: Great test coverage for the happy path scenario!

The TestStore_LoadConfigMap function is well-structured and covers the successful loading of a ConfigMap. It initializes the necessary dependencies, creates a sample ConfigMap with comprehensive test data, and makes appropriate assertions to verify the expected behavior of the LoadConfigMap method.

To further enhance the test coverage, consider adding more test cases to cover error scenarios and edge cases, such as:

  • Loading a non-existent ConfigMap
  • Handling errors during ConfigMap retrieval
  • Dealing with invalid or malformed ConfigMap data

101-135: Excellent test coverage for the ConfigMap write operation!

The TestStore_WriteConfigMap function is well-structured and covers the successful writing of a ConfigMap. It initializes the necessary dependencies, prepares the test data, and makes appropriate assertions to verify the expected behavior of the WriteConfigMap method.

To further improve the test coverage, consider adding more test cases to handle error scenarios and edge cases, such as:

  • Writing a ConfigMap with invalid data
  • Handling errors during ConfigMap creation or update
  • Dealing with permission issues or other Kubernetes-related errors
Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 9660dd0 and 9c177c8.

Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
Files selected for processing (15)
  • client.go (2 hunks)
  • component/remote/async.go (1 hunks)
  • env/config/config.go (2 hunks)
  • extension/configmap.go (1 hunks)
  • extension/configmap_test.go (1 hunks)
  • go.mod (1 hunks)
  • start.go (1 hunks)
  • start_test.go (1 hunks)
  • storage/repository.go (2 hunks)
  • storage/repository_test.go (1 hunks)
  • store/configMap/manager.go (1 hunks)
  • store/configMap/manager_test.go (1 hunks)
  • store/configMap/store.go (1 hunks)
  • store/configMap/store_test.go (1 hunks)
  • store/configmap.go (1 hunks)
Additional context used
golangci-lint
client.go

53-53: cannot use &configMap.Store{…} (value of type *configMap.Store) as store.ConfigMapHandler value in argument to extension.SetConfigMapHandler: *configMap.Store does not implement store.ConfigMapHandler (wrong type for method LoadConfigMap)
have LoadConfigMap(*config.ApolloConfig, string) (*config.ApolloConfig, error)
want LoadConfigMap(string) (*config.ApolloConfig, error)

(typecheck)

Additional comments not posted (29)
store/configmap.go (1)

22-27: LGTM!

The ConfigMapHandler interface provides a clean abstraction for managing configuration maps. The method signatures are well-defined, and the comments provide clear explanations of the method behaviors. The code follows Go conventions and best practices.

extension/configmap.go (2)

25-27: LGTM!

The SetConfigMapHandler function correctly sets the global configMapHandler variable to the provided inConfigMapHandler parameter. The function is exported, which is appropriate as it is intended to be used by other packages to set the configMapHandler.


30-32: LGTM!

The GetConfigMapHandler function correctly returns the global configMapHandler variable. The function is exported, which is appropriate as it is intended to be used by other packages to get the configMapHandler.

extension/configmap_test.go (4)

26-27: LGTM!

The TestConfigMapHandler struct is correctly defined. It appears to be a test stub for the ConfigMapHandler interface.


29-31: LGTM!

The LoadConfigMap method is correctly defined on the TestConfigMapHandler struct. The method signature matches the ConfigMapHandler interface. Returning nil values is appropriate for a test stub.


33-35: LGTM!

The WriteConfigMap method is correctly defined on the TestConfigMapHandler struct. The method signature matches the ConfigMapHandler interface. Returning a nil value is appropriate for a test stub.


38-44: LGTM!

The TestSetConfigMapHandler function is a well-defined test case. It correctly tests the functionality of setting and retrieving the ConfigMapHandler. The assertion ensures that the handler is properly set.

store/configMap/store.go (2)

24-27: LGTM!

The Store struct definition looks good. Using dependency injection for the K8sManager is a nice approach to make the code more testable.


38-44: LGTM!

The WriteConfigMap method looks good. It properly uses the AppID, Cluster, and NamespaceName to uniquely identify the ConfigMap and the configuration key, which is consistent with the LoadConfigMap method. The error handling is also done correctly.

start.go (6)

30-35: LGTM!

The changes to SetSignature are limited to comment formatting and do not alter the functionality. The nil check ensures that only a valid auth component is set.


37-42: LGTM!

The changes to SetBackupFileHandler are limited to comment formatting and do not alter the functionality. The nil check ensures that only a valid file component is set.


44-49: New feature looks good!

The new SetConfigMapHandler function enables setting a custom ConfigMap persistence component, which aligns with the PR objective of integrating Kubernetes ConfigMap as a new persistent storage solution. The nil check ensures that only a valid configMapHandler is set.


51-56: LGTM!

The changes to SetLoadBalance are limited to comment formatting and do not alter the functionality. The nil check ensures that only a valid loadBalance component is set.


58-63: LGTM!

The changes to SetLogger are limited to comment formatting and do not alter the functionality. The nil check ensures that only a valid loggerInterface is set.


Line range hint 65-70: LGTM!

The changes to SetCache are limited to comment formatting and do not alter the functionality. The nil check ensures that only a valid cacheFactory is set.

store/configMap/manager_test.go (2)

30-55: LGTM!

The test function TestK8sManager_SetConfigMap is well-written and covers the happy path scenario of setting a ConfigMap using the K8sManager. It follows a clear arrange-act-assert pattern, uses a fake Kubernetes client for testing, and makes comprehensive assertions to verify the expected behavior.


57-82: LGTM!

The test function TestK8sManager_GetConfigMap is well-written and covers the scenario of retrieving a ConfigMap using the K8sManager. It follows a clear arrange-act-assert pattern, uses a fake Kubernetes client with a pre-existing ConfigMap for testing, and makes assertions to verify that the returned configurations match the expected values.

go.mod (1)

1-67: LGTM! The changes to the go.mod file align with the PR objectives.

The updates to the go.mod file, including the addition of Kubernetes-related dependencies, testing libraries, and configuration management libraries, are consistent with the PR objectives of implementing Kubernetes ConfigMap support and enhancing the module's capabilities.

The updated Go version from 1.13 to 1.22.0 may introduce new features and improvements that could benefit the module.

Please ensure that the new dependencies are compatible with the updated Go version to avoid any potential integration issues. You can verify this by running the following commands:

If there are no errors or compatibility issues, the changes to the go.mod file should be good to go.

Verification successful

Go module dependencies look good and compatible

The analysis of the go.mod file shows that the dependencies and Go version are up-to-date and compatible. Here are the key points:

  • Go version 1.22.0 is specified, which is recent and supported.
  • Direct dependencies, including Kubernetes-related packages, are at consistent versions.
  • No version conflicts were detected among the dependencies.

The changes to the go.mod file align well with the PR objectives and don't introduce any apparent compatibility issues.

While the static analysis shows no issues, it's recommended that you perform a final manual verification in your development environment to ensure everything works as expected, especially regarding the Kubernetes integration and new dependencies.

Scripts executed

The following scripts were executed for the analysis:

Script:

go mod tidy
go build ./...
go test ./...

Length of output: 256


Script:

#!/bin/bash
# Display the content of go.mod file
cat go.mod

# Extract and display the Go version
echo "Go version:"
grep "^go " go.mod

# Extract and display direct dependencies
echo "Direct dependencies:"
sed -n '/^require (/,/^)$/p' go.mod | grep -v "^require (" | grep -v "^)$"

# Check for any potential version conflicts
echo "Checking for potential version conflicts:"
grep -P "v\d+\.\d+\.\d+" go.mod | sort | uniq -d

Length of output: 5634

store/configMap/manager.go (3)

42-57: LGTM!

The GetK8sManager function correctly initializes the singleton K8sManager instance using in-cluster configuration. It handles errors appropriately and ensures thread-safe lazy initialization using sync.Once.


60-86: LGTM!

The SetConfigMap method correctly converts the ApolloConfig data to JSON and creates or updates a Kubernetes ConfigMap. It handles errors appropriately and sets a timeout for the API operations.


89-112: LGTM!

The GetConfigMap method correctly retrieves a ConfigMap, extracts JSON data for the given key, and unmarshals it into the Configurations field of an ApolloConfig struct. It handles errors appropriately and sets a timeout for the API operation.

component/remote/async.go (1)

150-158: LGTM!

The changes introduce support for loading configurations from ConfigMaps as a fallback mechanism. The logic correctly prioritizes loading from the local backup file over the ConfigMap. This aligns with the PR objective of using ConfigMaps for persistent storage in Kubernetes environments.

The error handling is maintained by logging any issues encountered during the loading process.

env/config/config.go (3)

44-54: LGTM!

The addition of the new fields IsBackupConfigToConfigMap and ConfigMapNamespace to the AppConfig struct, along with the clarifying comment for the existing IsBackupConfig field, looks good. The default value of false for IsBackupConfigToConfigMap ensures that this feature is opt-in, and the ConfigMapNamespace field provides flexibility in specifying the namespace for the ConfigMap.


81-86: LGTM!

The addition of the GetIsBackupConfigToConfigMap getter method to the AppConfig struct looks good. The method name follows the Go naming convention, and it provides a way to retrieve the value of the IsBackupConfigToConfigMap field.


88-90: LGTM!

The addition of the GetConfigMapNamespace getter method to the AppConfig struct looks good. The method name follows the Go naming convention, and it provides a way to retrieve the value of the ConfigMapNamespace field.

start_test.go (1)

228-246: LGTM!

The code changes introduce a new testConfigMapHandler struct and its placeholder methods LoadConfigMap and WriteConfigMap, which serve as a foundation for future implementation of loading and writing configurations to Kubernetes ConfigMaps.

The TestSetConfigMapHandler test function ensures that the ConfigMap handler can be set and retrieved correctly, providing adequate coverage for the newly introduced SetConfigMapHandler function.

The code changes are well-structured, follow the existing coding style and conventions, and align with the larger effort to integrate Kubernetes ConfigMaps into the agollo package for configuration management.

client.go (1)

23-23: LGTM!

The import statement is correct and necessary for the changes introduced in this file.

storage/repository_test.go (1)

61-61: LGTM!

The TODO comment is a good reminder for a planned test enhancement. It does not alter any functionality at this time.

storage/repository.go (1)

Line range hint 456-492: LGTM!

The changes to the UpdateApolloConfig function look good:

  • The new conditional check for writing the configuration to a ConfigMap follows the existing pattern for writing backup files.
  • The WriteConfigMap method from the ConfigMapHandler is invoked with the appropriate parameters.
  • The changes maintain the existing code structure, style, and conventions.

Comment on lines +33 to +34
// TODO 在这里把json转为ApolloConfig, 但ReleaseKey字段会丢失
config.Configurations, _ = c.K8sManager.GetConfigMap(configMapName, configMapNamespace, key)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Address the TODO comment about losing the ReleaseKey.

The comment indicates that the ReleaseKey field is lost when converting the JSON to ApolloConfig. This seems like an important piece of information that shouldn't be discarded. Please investigate this further and ensure that the ReleaseKey is properly handled.

configMapName := config.AppID
key := config.Cluster + "+" + config.NamespaceName
// TODO 在这里把json转为ApolloConfig, 但ReleaseKey字段会丢失
config.Configurations, _ = c.K8sManager.GetConfigMap(configMapName, configMapNamespace, key)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handle the error returned from GetConfigMap.

The error returned from GetConfigMap is being ignored. It's a good practice to always handle errors. If an error occurs while retrieving the ConfigMap, it should be returned from the LoadConfigMap method so that the caller can handle it appropriately.

Modify the code to handle the error:

-config.Configurations, _ = c.K8sManager.GetConfigMap(configMapName, configMapNamespace, key)
+config.Configurations, err := c.K8sManager.GetConfigMap(configMapName, configMapNamespace, key)
+if err != nil {
+    return nil, err
+}
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
config.Configurations, _ = c.K8sManager.GetConfigMap(configMapName, configMapNamespace, key)
config.Configurations, err := c.K8sManager.GetConfigMap(configMapName, configMapNamespace, key)
if err != nil {
return nil, err
}

@@ -49,6 +50,7 @@ const separator = ","
func init() {
extension.SetCacheFactory(&memory.DefaultCacheFactory{})
extension.SetLoadBalance(&roundrobin.RoundRobin{})
extension.SetConfigMapHandler(&configMap.Store{configMap.GetK8sManager()})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type mismatch error in LoadConfigMap method signature.

The static analysis tool has correctly identified a type mismatch error in the LoadConfigMap method implemented by configMap.Store. The method signature does not match the one expected by the store.ConfigMapHandler interface:

have LoadConfigMap(*config.ApolloConfig, string) (*config.ApolloConfig, error)
want LoadConfigMap(string) (*config.ApolloConfig, error)

This error needs to be fixed to ensure the correct functionality of the configuration map handler.

Do you want me to suggest the necessary changes to fix this type mismatch error or open a GitHub issue to track this task?

Tools
golangci-lint

53-53: cannot use &configMap.Store{…} (value of type *configMap.Store) as store.ConfigMapHandler value in argument to extension.SetConfigMapHandler: *configMap.Store does not implement store.ConfigMapHandler (wrong type for method LoadConfigMap)
have LoadConfigMap(*config.ApolloConfig, string) (*config.ApolloConfig, error)
want LoadConfigMap(string) (*config.ApolloConfig, error)

(typecheck)

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

Successfully merging this pull request may close these issues.

1 participant