Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 58 additions & 58 deletions .github/workflows/build-and-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Create and publish a Docker image

on:
push:
branches: ['main']
branches: ['main', 'try-to-fix']

env:
REGISTRY: ghcr.io
Expand Down Expand Up @@ -81,60 +81,60 @@ jobs:
namespace: operators
action: deploy

## API cluster ##
- name: Bake api manifests with Kustomize
uses: azure/k8s-bake@v2
with:
renderEngine: 'kustomize'
kustomizationPath: 'kustomize/overlays/api'
id: bake-api

- uses: azure/login@v1
with:
creds: '${{ secrets.AKS_API_FINT_GITHUB }}'

- name: Set the target Api cluster.
uses: azure/aks-set-context@v3
with:
cluster-name: ${{ env.API_CLUSTER_NAME }}
resource-group: ${{ env.API_CLUSTER_RESOURCE_GROUP }}
admin: 'true'
use-kubelogin: 'true'

- name: Deploy to Api
uses: azure/k8s-deploy@v4.9
with:
manifests: ${{ steps.bake-api.outputs.manifestsBundle }}
images: |
${{ steps.meta.outputs.tags }}
namespace: operators
action: deploy

## Beta cluster ##
- name: Bake beta manifests with Kustomize
uses: azure/k8s-bake@v2
with:
renderEngine: 'kustomize'
kustomizationPath: 'kustomize/overlays/beta'
id: bake-beta

- uses: azure/login@v1
with:
creds: '${{ secrets.AKS_BETA_FINT_GITHUB }}'

- name: Set the target Beta cluster.
uses: azure/aks-set-context@v3
with:
cluster-name: ${{ env.BETA_CLUSTER_NAME }}
resource-group: ${{ env.BETA_CLUSTER_RESOURCE_GROUP }}
admin: 'true'
use-kubelogin: 'true'

- name: Deploy to Beta
uses: azure/k8s-deploy@v4.9
with:
manifests: ${{ steps.bake-beta.outputs.manifestsBundle }}
images: |
${{ steps.meta.outputs.tags }}
namespace: operators
action: deploy
# ## API cluster ##
# - name: Bake api manifests with Kustomize
# uses: azure/k8s-bake@v2
# with:
# renderEngine: 'kustomize'
# kustomizationPath: 'kustomize/overlays/api'
# id: bake-api
#
# - uses: azure/login@v1
# with:
# creds: '${{ secrets.AKS_API_FINT_GITHUB }}'
#
# - name: Set the target Api cluster.
# uses: azure/aks-set-context@v3
# with:
# cluster-name: ${{ env.API_CLUSTER_NAME }}
# resource-group: ${{ env.API_CLUSTER_RESOURCE_GROUP }}
# admin: 'true'
# use-kubelogin: 'true'
#
# - name: Deploy to Api
# uses: azure/k8s-deploy@v4.9
# with:
# manifests: ${{ steps.bake-api.outputs.manifestsBundle }}
# images: |
# ${{ steps.meta.outputs.tags }}
# namespace: operators
# action: deploy
#
# ## Beta cluster ##
# - name: Bake beta manifests with Kustomize
# uses: azure/k8s-bake@v2
# with:
# renderEngine: 'kustomize'
# kustomizationPath: 'kustomize/overlays/beta'
# id: bake-beta
#
# - uses: azure/login@v1
# with:
# creds: '${{ secrets.AKS_BETA_FINT_GITHUB }}'
#
# - name: Set the target Beta cluster.
# uses: azure/aks-set-context@v3
# with:
# cluster-name: ${{ env.BETA_CLUSTER_NAME }}
# resource-group: ${{ env.BETA_CLUSTER_RESOURCE_GROUP }}
# admin: 'true'
# use-kubelogin: 'true'
#
# - name: Deploy to Beta
# uses: azure/k8s-deploy@v4.9
# with:
# manifests: ${{ steps.bake-beta.outputs.manifestsBundle }}
# images: |
# ${{ steps.meta.outputs.tags }}
# namespace: operators
# action: deploy
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'

implementation 'no.fintlabs:flais-operator-starter:1.0.0'
annotationProcessor 'io.fabric8:crd-generator-apt:6.2.0'
testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1'
annotationProcessor 'io.fabric8:crd-generator-apt:6.2.0'

implementation 'org.springframework.kafka:spring-kafka'
implementation 'no.fintlabs:fint-kafka:4.0.1'
Expand Down
9 changes: 9 additions & 0 deletions kustomize/overlays/alpha/exclude-kafka.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
$patch: delete
apiVersion: "fintlabs.no/v1alpha1"
kind: KafkaUserAndAcl
metadata:
name: finterator
spec:
acls:
- permission: admin
topic: 'flais-io.fint-customer-objects.*'
11 changes: 11 additions & 0 deletions kustomize/overlays/alpha/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,22 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patchesStrategicMerge:
- exclude-kafka.yaml
patches:
- patch: |-
- op: replace
path: "/spec/itemPath"
value: "vaults/aks-alpha-vault/items/finterator"
target:
kind: OnePasswordItem
name: finterator
- patch: |-
- op: add
path: "/spec/template/spec/containers/0/env/-"
value:
name: fint.application-id
value: finterator-alpha
target:
kind: Deployment
name: finterator
4 changes: 3 additions & 1 deletion src/main/java/no/fintlabs/CrdUtilities.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package no.fintlabs;

import io.fabric8.kubernetes.api.model.HasMetadata;
import org.springframework.util.StringUtils;

import java.util.Optional;

public class CrdUtilities {

public static Optional<String> getValueFromAnnotationByKey(HasMetadata crd, String key) {
return Optional.ofNullable(crd.getMetadata().getAnnotations().get(key));
return Optional.ofNullable(crd.getMetadata().getAnnotations().get(key))
.filter(StringUtils::hasText);
}
}
70 changes: 70 additions & 0 deletions src/main/java/no/fintlabs/LdapNameGeneratorUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package no.fintlabs;

import org.apache.commons.lang3.RandomStringUtils;

public class LdapNameGeneratorUtil {

public static final int RANDOM_CHARS = 5;
public static final int MAX_LDAP_CHARS = 64;

public static String generate(String crdName, String orgId, String type) {

// drosjeloyve-beta-trondelagfylke-no-wayzk@client.trondelagfylke.no
// drosjeloyve-beta-trondelagfylke-wayzk@client.trondelagfylke.no
// drosjeloyve-wayzk@client.trondelagfylke.no

String randomString = RandomStringUtils.randomAlphabetic(RANDOM_CHARS).toLowerCase();

// Remove if too long and contains -no-
if (getFullNameLength(crdName, randomString, orgId, type) > MAX_LDAP_CHARS && crdName.contains("-no-")) {
crdName = crdName.replace("-no-", "-");
}

// remove if too long and ends with -no
if (getFullNameLength(crdName, randomString, orgId, type) > MAX_LDAP_CHARS && crdName.endsWith("-no")) {
crdName = crdName.substring(0, crdName.length() - 3);
}

// remove if too long and contains fylke
if (getFullNameLength(crdName, randomString, orgId, type) > MAX_LDAP_CHARS && crdName.contains("fylke")) {
crdName = crdName.replace("fylke", "");
}

while (getFullNameLength(crdName, randomString, orgId, type) > MAX_LDAP_CHARS) {
crdName = removeCharacterFromLongestPart(crdName);
}

return String.format("%s-%s", crdName, randomString);
}

private static String removeCharacterFromLongestPart(String crdName) {
String[] parts = crdName.split("-");
int longestPartIndex = -1;
int longestPartLength = 0;

// Finn indeksen til den lengste delen, sortert fra høyre
for (int i = 0; i < parts.length; i++) {
if (parts[i].length() >= longestPartLength) {
longestPartLength = parts[i].length();
longestPartIndex = i;
}
}

// Fjern siste tegn fra den lengste delen
if (longestPartIndex != -1 && parts[longestPartIndex].length() > 0) {
parts[longestPartIndex] = parts[longestPartIndex].substring(0, parts[longestPartIndex].length() - 1);
}

// Sett sammen strengen igjen
return String.join("-", parts);
}

public static int getFullNameLength(String crdName, String randomString, String orgId, String type) {
return generateFullName(crdName, randomString, orgId, type).length();
}

public static String generateFullName(String crdName, String randomString, String orgId, String type) {
return String.format("%s-%s@%s.%s", crdName, randomString, type, orgId);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@
import io.javaoperatorsdk.operator.processing.dependent.Updater;
import lombok.extern.slf4j.Slf4j;
import no.fintlabs.FlaisExternalDependentResource;
import no.fintlabs.LdapNameGeneratorUtil;
import no.fintlabs.SecretService;
import no.fintlabs.client.Client;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.SerializationUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

Expand Down Expand Up @@ -60,7 +59,7 @@ public Adapter desired(FintAdapterCrd primary, Context<FintAdapterCrd> context)

private Supplier<Adapter> handleDesiredOnNew(FintAdapterCrd primary) {
return () -> {
String adapterName = String.format("%s-%s", primary.getMetadata().getName(), RandomStringUtils.randomAlphabetic(5).toLowerCase());
String adapterName = LdapNameGeneratorUtil.generate(primary.getMetadata().getName(), primary.getSpec().getOrgId(), "adapter");
Adapter adapter = Adapter
.builder()
.name(adapterName)
Expand Down Expand Up @@ -122,29 +121,20 @@ public Adapter create(Adapter desired, FintAdapterCrd primary, Context<FintAdapt

@Override
public Set<Adapter> fetchResources(FintAdapterCrd primaryResource) {
Set<Adapter> adapters = fintAdapterRepository.get(primaryResource);

for (var adapter : adapters) {
if (isSecretOrPasswordMissing(adapter)) {
adapter.setNote("Trigger update because clientSecret or password is empty");
log.info("Change adapter '{}' to trigger update", adapter.getName());
}
}

return adapters;
}

private boolean isSecretOrPasswordMissing(Adapter adapter) {
return /*adapter.isManaged() &&*/ (StringUtils.isEmpty(adapter.getClientSecret()) || StringUtils.isEmpty(adapter.getPassword()));
return fintAdapterRepository.get(primaryResource);
}

@Override
public Matcher.Result<Adapter> match(
Adapter actualResource, FintAdapterCrd primary, Context<FintAdapterCrd> context
) {
DesiredEqualsMatcher<Adapter, FintAdapterCrd> matcher = new DesiredEqualsMatcher<>(this);
// TODO: 27/10/2023 Finn ut hvorfor managed blir false
actualResource.setManaged(true);

return matcher.match(actualResource, primary, context);
DesiredEqualsMatcher<Adapter, FintAdapterCrd> matcher = new DesiredEqualsMatcher<>(this);
Matcher.Result<Adapter> result = matcher.match(actualResource, primary, context);
log.debug("Match {} ={}", primary.getMetadata().getName(), result.matched());
return result;
}

}
24 changes: 22 additions & 2 deletions src/main/java/no/fintlabs/adapter/FintAdapterReconciler.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
import lombok.extern.slf4j.Slf4j;
import no.fintlabs.FlaisReconiler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.List;

Expand All @@ -19,12 +21,30 @@ public FintAdapterReconciler(
FintAdapterWorkflow workflow,
List<? extends DependentResource<?, FintAdapterCrd>> eventSourceProviders,
List<? extends Deleter<FintAdapterCrd>> deleters
) {
) {
super(workflow, eventSourceProviders, deleters);
}

@Value("${fint.accepted.adapter-name:}")
private String acceptedName;

@Value("${fint.accepted.adapter-namespace:}")
private String acceptedNamespace;

@Override
public UpdateControl<FintAdapterCrd> reconcile(FintAdapterCrd resource, Context<FintAdapterCrd> context) {
return super.reconcile(resource, context);
//return super.reconcile(resource, context);

String name = resource.getMetadata().getName();
String namespace = resource.getMetadata().getNamespace();

if (name.contains(acceptedName) && namespace.contains(acceptedNamespace)
&& StringUtils.hasText(acceptedName) && StringUtils.hasText(acceptedNamespace)) {
log.info("Include update for " + name + " in " + namespace);
return super.reconcile(resource, context);
} else {
log.info("Skip update for " + name + " in " + namespace);
return UpdateControl.noUpdate();
}
}
}
6 changes: 4 additions & 2 deletions src/main/java/no/fintlabs/adapter/FintAdapterRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,20 @@ public Set<Adapter> get(FintAdapterCrd crd) {
Optional<AdapterEvent> responseOptional = adapterEventRequestProducerService.get(createRequestEvent(crd, dn.get()));

if (responseOptional.isEmpty()) {
log.error("Empty response from Kafka. The request has probably timed out. Client: {}", dn.get());
throw new CustomerObjectResponseException("Empty response from Kafka. The request has probably timed out. Client: " + dn.get());
}

AdapterEvent response = responseOptional.get();

if (response.hasError()){
log.error("Error response from Kafka: {}", response.getErrorMessage());
throw new CustomerObjectResponseException(response.getErrorMessage());
}

if (response.getObject() == null) {
log.debug("Object in response is null");
return Collections.emptySet();
log.error("DN has been set, but the client could not be found! {}", dn.get());
throw new IllegalStateException("DN has been set, but the client could not be found! " + dn.get());
}

return Collections.singleton(response.getObject());
Expand Down
Loading