Skip to content

Commit dea1103

Browse files
committed
Initial Caching Impl
1 parent b5617d7 commit dea1103

File tree

12 files changed

+185
-29
lines changed

12 files changed

+185
-29
lines changed

.applier/inventory/group_vars/all.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ build_vars:
1111
OUTPUT_IMAGE_NAME: '{{ app_name }}'
1212
OUTPUT_IMAGE_TAG: latest
1313
PUSH_SECRET: quay-registry-secret
14-
BUILDER_IMAGE_NAME: registry.access.redhat.com/fuse7/fuse-java-openshift
14+
BUILDER_IMAGE_NAME: registry.access.redhat.com/redhat-openjdk-18/openjdk18-openshift:1.8
1515
BUILDER_IMAGE_TAG: 1.5
1616

1717
pipeline_vars:

README.md

Lines changed: 85 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,26 @@ If you want to learn more about Quarkus, please visit its website: https://quark
77

88
Prior to running the app, you need to create a **Personal Access Token** linked to your GitLab account.
99

10+
### Local Infinispan (if necessary)
11+
12+
Fire 🔥 up a docker instance of Infinispan to work with the app
13+
14+
```
15+
docker run -it -p 11222:11222 -e USER="omp" -e PASS="omp" infinispan/server:10.1
16+
```
17+
1018
### Running in dev mode
1119

1220
You can run your application in dev mode that enables **live coding** using:
1321
```
22+
export CACHE_CLIENT_INTELLIGENCE=<For mac dev set to BASIC>
23+
export CACHE_USE_AUTH=true
24+
export CONFIG_REPOSITORY_ID =<Git Repo id where the config files are>
25+
export GITLAB_API_URL=<The base url of your git api. ie https://gitlab.com>
1426
export GITLAB_PERSONAL_ACCESS_TOKEN=<GitLab Personal Access Token>
27+
export OMP_LOGGING=DEBUG
28+
export RESIDENCIES_PARENT_REPOSITORIES_ID=<Parent project id where repos will be saved>
29+
export TEMPLATE_REPOSITORY_ID=<Repo where template live>
1530
./mvnw quarkus:dev
1631
```
1732

@@ -27,7 +42,14 @@ source ~/.zshrc
2742

2843
You can run your application using Quarkus profiles using:
2944
```
45+
export CACHE_CLIENT_INTELLIGENCE=<For mac dev set to BASIC>
46+
export CACHE_USE_AUTH=true
47+
export CONFIG_REPOSITORY_ID =<Git Repo id where the config files are>
48+
export GITLAB_API_URL=<The base url of your git api. ie https://gitlab.com>
3049
export GITLAB_PERSONAL_ACCESS_TOKEN=<GitLab Personal Access Token>
50+
export OMP_LOGGING=DEBUG
51+
export RESIDENCIES_PARENT_REPOSITORIES_ID=<Parent project id where repos will be saved>
52+
export TEMPLATE_REPOSITORY_ID=<Repo where template live>
3153
export QUARKUS_PROFILE=<Quarkus profile>
3254
./mvnw clean package
3355
java -jar target/open-management-portal-git-api-*-runner.jar
@@ -51,40 +73,92 @@ You can then execute your binary: `./target/open-management-portal-git-api-1.0.0
5173

5274
If you want to learn more about building native executables, please consult https://quarkus.io/guides/building-native-image-guide .
5375

54-
## Add basic JDG to OCP
76+
## Add Infinispan to OCP via the Infinispan Operator
77+
78+
* Cluster admin probably needed for CRD
79+
80+
### Create secret
81+
82+
Create a secret file named `omp-cache-secret.yaml`. This secret will create an `identities.yaml` file on the cache. Take note of the name that must match the app secret By default the user / pass will be omp / omp as defined in `src/main/resources/application.properties` and the secret below.
83+
84+
```
85+
apiVersion: v1
86+
data:
87+
identities.yaml: Y3JlZGVudGlhbHM6Ci0gdXNlcm5hbWU6IG9tcAogIHBhc3N3b3JkOiBvbXAKLSB1c2VybmFtZTogb3BlcmF0b3IKICBwYXNzd29yZDogTDdFYXZOQklBRXhORDVHdAo=
88+
kind: Secret
89+
metadata:
90+
labels:
91+
app: infinispan-secret-identities
92+
clusterName: omp-cache
93+
infinispan_cr: omp-cache
94+
name: omp-cache-secret
95+
type: Opaque
96+
```
97+
98+
### Create the Infinispan cluster file
99+
100+
Create a file named infinispan-cluster.yaml
101+
102+
```
103+
apiVersion: infinispan.org/v1
104+
kind: Infinispan
105+
metadata:
106+
name: omp-cache
107+
spec:
108+
replicas: 1
109+
image: infinispan/server:10.1
110+
logging:
111+
categories:
112+
org.infinispan: info
113+
org.jgroups: info
114+
security:
115+
endpointSecretName: omp-cache-secret
116+
```
117+
118+
### Create the Infinispan Operator
119+
120+
Login to OpenShift with the `oc` client and run the following commands
121+
55122
```
56-
oc new-app cache-service \
57-
-p APPLICATION_USER=omp \
58-
-p APPLICATION_PASSWORD=<PASSWORD> \
59-
-p TOTAL_CONTAINER_MEM=4096 \
60-
-p EVICTION_POLICY=reject \
61-
-n <PROJECT_NAME>
123+
# Install Infinispan Operator running these commands
124+
oc apply -f omp-cache-secret.yaml
125+
oc apply -f https://raw.githubusercontent.com/infinispan/infinispan-operator/master/deploy/rbac.yaml
126+
oc apply -f https://raw.githubusercontent.com/infinispan/infinispan-operator/master/deploy/operator.yaml
127+
oc apply -f https://raw.githubusercontent.com/infinispan/infinispan-operator/master/deploy/crd.yaml
128+
129+
# Create an Infinispan Cluster
130+
oc apply -f infinispan-cluster.yaml
62131
```
63132

64133
## Configuration
65134
The preferred place to store non-sensitive data is in the application.properties.
66135

67-
Sensitive fields like git repo location, repository id for residencies, repository id for the config and the GitLab API token are stored in the secrets.
136+
Sensitive fields like the gitlab token and cluster credentials should be stored in a OpenShift secret at a minimum. Other environment specific information should be stored in environmental variables such as repository id for residencies and repository id for the config.
68137
This info is stored in `ocp-s11/labs-test/omp-gitlab-configuration`.
69138

70139
Deployment template will read from the above secret and inject following env variables. These are controlled from application.properties, so if a different env name is needed, change in the application properties file and the deployment template.
71140

72141
* `TEMPLATE_REPOSITORY_ID`
73142
* `RESIDENCIES_PARENT_REPOSITORIES_ID`
74143
* `GITLAB_API_URL`
75-
* `GITLAB_PERSONAL_ACCESS_TOKEN`
144+
* `GITLAB_PERSONAL_ACCESS_TOKEN` (should be secret and a service account)
145+
* `CACHE_SERVICE`
146+
* `CACHE_USER`
147+
* `CACHE_PASS` (should be secret and match the Infinispan operator secret)
148+
* `CACHE_USE_AUTH` set to true
149+
* *
76150

77151
### OpenShift Applier
78152

79-
This project includes an `openshift-applier` inventory. To use it, make sure that you are logged in to the cluster and that you customize the variables in `.applier/inventory/group_vars/all.yml` - namely make sure that `deploy_vars` uses the correct endpoints. Once these are configured, you can deploy the project with:
153+
This section is not guaranteed to be up to date. This project includes an `openshift-applier` inventory. To use it, make sure that you are logged in to the cluster and that you customize the variables in `.applier/inventory/group_vars/all.yml` - namely make sure that `deploy_vars` uses the correct endpoints. Once these are configured, you can deploy the project with:
80154

81155
```bash
82156
cd .applier/
83157
ansible-galaxy install -r requirements.yml --roles-path=roles --force
84158
ansible-playbook apply.yml -i inventory/
85159
```
86160

87-
## Pipeline
161+
## Pipeline (deprecated)
88162

89163
The deployment pipeline is running through a `Jenkinsfile` located in the root folder of the project. This `Jenksinfile` is written in groovy.
90164
The pipeline expects the nexus is available nexus:8080. Make sure that nexus is available and accessible to Jenkins.

src/main/java/com/redhat/labs/cache/GitSyncManager.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
*
2424
* @author faisalmasood
2525
*/
26+
@Deprecated
2627
@Singleton
2728
public class GitSyncManager {
2829

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.redhat.labs.cache;
2+
3+
import javax.enterprise.context.ApplicationScoped;
4+
import javax.inject.Inject;
5+
6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
8+
9+
import com.redhat.labs.cache.cacheStore.ResidencyDataCache;
10+
import com.redhat.labs.omp.models.filesmanagement.SingleFileResponse;
11+
12+
import io.quarkus.vertx.ConsumeEvent;
13+
14+
@ApplicationScoped
15+
public class GitSyncService {
16+
public static Logger LOGGER = LoggerFactory.getLogger(GitSyncService.class);
17+
18+
public static final String FILE_CACHE_EVENT = "fileCacheEvent";
19+
20+
@Inject
21+
ResidencyDataCache cache;
22+
23+
@ConsumeEvent(FILE_CACHE_EVENT)
24+
public void consumeTemplate(SingleFileResponse message) {
25+
LOGGER.warn("Caching repo file event:::: {} ", message.cacheKey);
26+
cache.store(message);
27+
}
28+
}

src/main/java/com/redhat/labs/cache/ResidencyDataStore.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public interface ResidencyDataStore {
2222
*/
2323
public void store(String key, ResidencyInformation residencyInformation);
2424

25-
public void store(String key, SingleFileResponse file);
25+
public void store(SingleFileResponse file);
2626

2727
/**
2828
* return NULL if the key is not present
@@ -32,7 +32,7 @@ public interface ResidencyDataStore {
3232
* @param key
3333
* @return
3434
*/
35-
public ResidencyInformation fetch(String key);
35+
public String fetch(String key);
3636

3737
/**
3838
* return all the KEYS stored in the cahe.

src/main/java/com/redhat/labs/cache/cacheStore/ResidencyDataCache.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@
55
import java.util.stream.StreamSupport;
66

77
import javax.enterprise.context.ApplicationScoped;
8+
import javax.enterprise.event.Observes;
89
import javax.inject.Inject;
910

1011
import org.infinispan.client.hotrod.RemoteCache;
1112
import org.infinispan.client.hotrod.RemoteCacheManager;
13+
import org.infinispan.configuration.cache.Configuration;
14+
import org.infinispan.configuration.cache.ConfigurationBuilder;
1215
import org.slf4j.Logger;
1316
import org.slf4j.LoggerFactory;
1417

@@ -17,6 +20,7 @@
1720
import com.redhat.labs.omp.models.filesmanagement.SingleFileResponse;
1821

1922
import io.quarkus.infinispan.client.Remote;
23+
import io.quarkus.runtime.StartupEvent;
2024

2125
/**
2226
* A very simple facade to write the cache data to remote JDG caches.
@@ -28,6 +32,13 @@ public class ResidencyDataCache implements ResidencyDataStore {
2832

2933
public static Logger LOGGER = LoggerFactory.getLogger(ResidencyDataCache.class);
3034

35+
void onStart(@Observes StartupEvent ev) {
36+
LOGGER.debug("On start cache check available ==> {}", cache != null);
37+
if(cache == null) {
38+
createCache();
39+
}
40+
}
41+
3142
@Inject
3243
protected RemoteCacheManager cacheManager;
3344

@@ -44,28 +55,33 @@ public void store(String key, ResidencyInformation residencyInformation) {
4455
}
4556

4657
@Override
47-
public void store(String key, SingleFileResponse file) {
48-
cache.put(key, file);
58+
public void store(SingleFileResponse file) {
59+
cache.put(file.cacheKey, file.fileContent);
4960
}
5061

5162
public void store(String key, String file) {
5263
cache.put(key, file);
5364
}
5465

5566
@Override
56-
public ResidencyInformation fetch(String key) {
57-
return (ResidencyInformation) cache.get(key);
67+
public String fetch(String key) {
68+
return (String) cache.get(key);
5869
}
5970

6071
@Override
6172
public List<String> getAllKeys() {
6273
return StreamSupport
6374
.stream(cache.keySet().spliterator(), true)
6475
.collect(Collectors.toList());
65-
6676
}
6777

6878
public void cleanCache() {
6979
cache.clear();
7080
}
81+
82+
private void createCache() {
83+
LOGGER.info("Create OMP cache");
84+
Configuration config = new ConfigurationBuilder().build();
85+
cache = cacheManager.administration().createCache("omp", config);
86+
}
7187
}

src/main/java/com/redhat/labs/omp/models/filesmanagement/GetMultipleFilesResponse.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,8 @@
99
public class GetMultipleFilesResponse implements Serializable {
1010
@JsonbProperty("files")
1111
public List<SingleFileResponse> files;
12+
13+
public String toString() {
14+
return GetMultipleFilesResponse.class.getName() + " :: " + files;
15+
}
1216
}
Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
11
package com.redhat.labs.omp.models.filesmanagement;
22

33
import javax.json.bind.annotation.JsonbProperty;
4-
import java.io.Serializable;
54

65
/**
76
* This class defines the single file content fetchged from Git.
87
*
98
*/
10-
public class SingleFileResponse implements Serializable {
9+
public class SingleFileResponse {
1110

1211
public SingleFileResponse(){
1312

1413
}
1514

1615
public SingleFileResponse(String fileName, String fileContent){
1716
this.fileName = fileName;
18-
1917
this.fileContent = fileContent;
2018
}
2119

@@ -25,7 +23,17 @@ public SingleFileResponse(String fileName, String fileContent){
2523
@JsonbProperty("fileContent")
2624
public String fileContent;
2725

26+
public String cacheKey;
27+
28+
public void setCacheKey(String repoId, String branch) {
29+
cacheKey = String.format("%s:%s:%s", fileName, repoId, branch);
30+
}
31+
2832
public String getFileContent(){
2933
return fileContent;
3034
}
35+
36+
public String toString() {
37+
return String.format("Single FileResponse: name: %s contents: %s", fileName, fileContent);
38+
}
3139
}

src/main/java/com/redhat/labs/omp/resources/CacheResource.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ private SingleFileResponse fetchContentFromGit(String fileName) {
8484
GetFileResponse metaFileResponse = gitLabService.getFile(templateRepositoryId, fileName, "master");
8585
String base64Content = metaFileResponse.content;
8686
String content = new String(Base64.getDecoder().decode(base64Content), StandardCharsets.UTF_8);
87-
LOGGER.info("File {} content fetched {}", fileName, content);
87+
LOGGER.debug("File {} content fetched {}", fileName, content);
8888
return new SingleFileResponse(fileName, content);
8989
}
9090
}

src/main/java/com/redhat/labs/omp/resources/FileResource.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package com.redhat.labs.omp.resources;
22

3+
import com.redhat.labs.cache.GitSyncService;
34
import com.redhat.labs.cache.cacheStore.ResidencyDataCache;
45
import com.redhat.labs.omp.models.GetFileResponse;
56
import com.redhat.labs.omp.models.filesmanagement.SingleFileResponse;
67
import com.redhat.labs.omp.resources.filters.Logged;
78
import com.redhat.labs.omp.services.GitLabService;
89

10+
import io.vertx.axle.core.eventbus.EventBus;
11+
912
import org.eclipse.microprofile.config.inject.ConfigProperty;
1013
import org.eclipse.microprofile.rest.client.inject.RestClient;
1114
import org.slf4j.Logger;
@@ -28,6 +31,9 @@ public class FileResource {
2831
@RestClient
2932
protected GitLabService gitLabService;
3033

34+
@Inject
35+
protected EventBus bus;
36+
3137
@Inject
3238
protected ResidencyDataCache cache;
3339

@@ -45,15 +51,24 @@ public SingleFileResponse fetchContentFromGit(String fileName, String templateRe
4551
LOGGER.debug(String.format("Template Repo %s filename %s branch %s", templateRepositoryId, fileName, branch));
4652
}
4753

54+
String key = String.format("%s:%s:%s", fileName, templateRepositoryId, branch == null ? defaultBranch : branch);
55+
56+
String fileContent = cache.fetch(key);
57+
if(fileContent != null) {
58+
LOGGER.debug("Cache hit for key {}", key);
59+
return new SingleFileResponse(fileName, fileContent);
60+
}
61+
62+
LOGGER.info("Cache miss for key: {}", key);
4863
GetFileResponse metaFileResponse = gitLabService.getFile(templateRepositoryId, fileName, branch == null ? defaultBranch : branch);
4964
String base64Content = metaFileResponse.content;
5065
String content = new String(Base64.getDecoder().decode(base64Content), StandardCharsets.UTF_8);
5166
LOGGER.debug("File {} content fetched {}", fileName, content);
5267
SingleFileResponse response = new SingleFileResponse(fileName, content);
5368
if(content != null) {
54-
String cacheJson = JsonbBuilder.create().toJson(response);
5569
LOGGER.info("adding {} to cache", fileName);
56-
cache.store(fileName, cacheJson);
70+
response.cacheKey = key;
71+
bus.publish(GitSyncService.FILE_CACHE_EVENT, response);
5772
}
5873
return response;
5974
}

0 commit comments

Comments
 (0)