Skip to content

Commit

Permalink
feat(operator): Add support for managed NetworkPolicy in operator (#5922
Browse files Browse the repository at this point in the history
)

* Add support for managed NetworkPolicy in operator

* Delete NetworkPolicy resource in activation condition

* fix(operator): missing RBAC for NetworkPolicy

* Apply PR feedback

* chore(operator): update install file

---------

Co-authored-by: Jakub Senko <[email protected]>
  • Loading branch information
EricWittmann and jsenko authored Feb 11, 2025
1 parent f618cce commit 1f99c3d
Show file tree
Hide file tree
Showing 17 changed files with 498 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ rules:
- networking.k8s.io
resources:
- ingresses
- networkpolicies
verbs:
- '*'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@
import io.apicurio.registry.operator.resource.LabelDiscriminators.AppDeploymentDiscriminator;
import io.apicurio.registry.operator.resource.app.AppDeploymentResource;
import io.apicurio.registry.operator.resource.app.AppIngressResource;
import io.apicurio.registry.operator.resource.app.AppNetworkPolicyResource;
import io.apicurio.registry.operator.resource.app.AppPodDisruptionBudgetResource;
import io.apicurio.registry.operator.resource.app.AppServiceResource;
import io.apicurio.registry.operator.resource.studioui.StudioUIDeploymentResource;
import io.apicurio.registry.operator.resource.studioui.StudioUIIngressResource;
import io.apicurio.registry.operator.resource.studioui.StudioUINetworkPolicyResource;
import io.apicurio.registry.operator.resource.studioui.StudioUIPodDisruptionBudgetResource;
import io.apicurio.registry.operator.resource.studioui.StudioUIServiceResource;
import io.apicurio.registry.operator.resource.ui.UIDeploymentResource;
import io.apicurio.registry.operator.resource.ui.UIIngressResource;
import io.apicurio.registry.operator.resource.ui.UINetworkPolicyResource;
import io.apicurio.registry.operator.resource.ui.UIPodDisruptionBudgetResource;
import io.apicurio.registry.operator.resource.ui.UIServiceResource;
import io.apicurio.registry.operator.updater.IngressCRUpdater;
Expand All @@ -31,22 +34,28 @@
import org.slf4j.LoggerFactory;

import static io.apicurio.registry.operator.resource.ActivationConditions.AppIngressActivationCondition;
import static io.apicurio.registry.operator.resource.ActivationConditions.AppNetworkPolicyActivationCondition;
import static io.apicurio.registry.operator.resource.ActivationConditions.AppPodDisruptionBudgetActivationCondition;
import static io.apicurio.registry.operator.resource.ActivationConditions.StudioUIDeploymentActivationCondition;
import static io.apicurio.registry.operator.resource.ActivationConditions.StudioUIIngressActivationCondition;
import static io.apicurio.registry.operator.resource.ActivationConditions.StudioUINetworkPolicyActivationCondition;
import static io.apicurio.registry.operator.resource.ActivationConditions.StudioUIPodDisruptionBudgetActivationCondition;
import static io.apicurio.registry.operator.resource.ActivationConditions.UIIngressActivationCondition;
import static io.apicurio.registry.operator.resource.ActivationConditions.UINetworkPolicyActivationCondition;
import static io.apicurio.registry.operator.resource.ActivationConditions.UIPodDisruptionBudgetActivationCondition;
import static io.apicurio.registry.operator.resource.ResourceKey.APP_DEPLOYMENT_ID;
import static io.apicurio.registry.operator.resource.ResourceKey.APP_INGRESS_ID;
import static io.apicurio.registry.operator.resource.ResourceKey.APP_NETWORK_POLICY_ID;
import static io.apicurio.registry.operator.resource.ResourceKey.APP_POD_DISRUPTION_BUDGET_ID;
import static io.apicurio.registry.operator.resource.ResourceKey.APP_SERVICE_ID;
import static io.apicurio.registry.operator.resource.ResourceKey.STUDIO_UI_DEPLOYMENT_ID;
import static io.apicurio.registry.operator.resource.ResourceKey.STUDIO_UI_INGRESS_ID;
import static io.apicurio.registry.operator.resource.ResourceKey.STUDIO_UI_NETWORK_POLICY_ID;
import static io.apicurio.registry.operator.resource.ResourceKey.STUDIO_UI_POD_DISRUPTION_BUDGET_ID;
import static io.apicurio.registry.operator.resource.ResourceKey.STUDIO_UI_SERVICE_ID;
import static io.apicurio.registry.operator.resource.ResourceKey.UI_DEPLOYMENT_ID;
import static io.apicurio.registry.operator.resource.ResourceKey.UI_INGRESS_ID;
import static io.apicurio.registry.operator.resource.ResourceKey.UI_NETWORK_POLICY_ID;
import static io.apicurio.registry.operator.resource.ResourceKey.UI_POD_DISRUPTION_BUDGET_ID;
import static io.apicurio.registry.operator.resource.ResourceKey.UI_SERVICE_ID;

Expand Down Expand Up @@ -74,6 +83,12 @@
dependsOn = {APP_DEPLOYMENT_ID},
activationCondition = AppPodDisruptionBudgetActivationCondition.class
),
@Dependent(
type = AppNetworkPolicyResource.class,
name = APP_NETWORK_POLICY_ID,
dependsOn = {APP_DEPLOYMENT_ID},
activationCondition = AppNetworkPolicyActivationCondition.class
),
// ===== Registry UI
@Dependent(
type = UIDeploymentResource.class,
Expand All @@ -96,6 +111,12 @@
dependsOn = {UI_DEPLOYMENT_ID},
activationCondition = UIPodDisruptionBudgetActivationCondition.class
),
@Dependent(
type = UINetworkPolicyResource.class,
name = UI_NETWORK_POLICY_ID,
dependsOn = {UI_DEPLOYMENT_ID},
activationCondition = UINetworkPolicyActivationCondition.class
),
// ===== Studio UI
@Dependent(
type = StudioUIDeploymentResource.class,
Expand All @@ -119,6 +140,12 @@
dependsOn = {STUDIO_UI_DEPLOYMENT_ID},
activationCondition = StudioUIPodDisruptionBudgetActivationCondition.class
),
@Dependent(
type = StudioUINetworkPolicyResource.class,
name = STUDIO_UI_NETWORK_POLICY_ID,
dependsOn = {STUDIO_UI_DEPLOYMENT_ID},
activationCondition = StudioUINetworkPolicyActivationCondition.class
)
}
)
// TODO: When renaming, do not forget to update application.properties (until we have a test for this).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,23 @@
import io.apicurio.registry.operator.api.v1.spec.AppSpec;
import io.apicurio.registry.operator.api.v1.spec.ComponentSpec;
import io.apicurio.registry.operator.api.v1.spec.IngressSpec;
import io.apicurio.registry.operator.api.v1.spec.NetworkPolicySpec;
import io.apicurio.registry.operator.api.v1.spec.PodDisruptionSpec;
import io.apicurio.registry.operator.api.v1.spec.StudioUiSpec;
import io.apicurio.registry.operator.api.v1.spec.UiSpec;
import io.apicurio.registry.operator.resource.app.AppIngressResource;
import io.apicurio.registry.operator.resource.app.AppNetworkPolicyResource;
import io.apicurio.registry.operator.resource.app.AppPodDisruptionBudgetResource;
import io.apicurio.registry.operator.resource.studioui.StudioUIDeploymentResource;
import io.apicurio.registry.operator.resource.studioui.StudioUIIngressResource;
import io.apicurio.registry.operator.resource.studioui.StudioUINetworkPolicyResource;
import io.apicurio.registry.operator.resource.studioui.StudioUIPodDisruptionBudgetResource;
import io.apicurio.registry.operator.resource.ui.UIIngressResource;
import io.apicurio.registry.operator.resource.ui.UINetworkPolicyResource;
import io.apicurio.registry.operator.resource.ui.UIPodDisruptionBudgetResource;
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.fabric8.kubernetes.api.model.networking.v1.Ingress;
import io.fabric8.kubernetes.api.model.networking.v1.NetworkPolicy;
import io.fabric8.kubernetes.api.model.policy.v1.PodDisruptionBudget;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
Expand Down Expand Up @@ -70,6 +75,21 @@ public boolean isMet(DependentResource<PodDisruptionBudget, ApicurioRegistry3> r
}
}

public static class AppNetworkPolicyActivationCondition
implements Condition<NetworkPolicy, ApicurioRegistry3> {
@Override
public boolean isMet(DependentResource<NetworkPolicy, ApicurioRegistry3> resource,
ApicurioRegistry3 primary, Context<ApicurioRegistry3> context) {
Boolean isManaged = ofNullable(primary.getSpec()).map(ApicurioRegistry3Spec::getApp)
.map(ComponentSpec::getNetworkPolicy).map(NetworkPolicySpec::getEnabled)
.orElse(Boolean.TRUE);
if (!isManaged) {
((AppNetworkPolicyResource) resource).delete(primary, context);
}
return isManaged;
}
}

// ===== Registry UI

public static class UIIngressActivationCondition implements Condition<Ingress, ApicurioRegistry3> {
Expand Down Expand Up @@ -106,6 +126,21 @@ public boolean isMet(DependentResource<PodDisruptionBudget, ApicurioRegistry3> r
}
}

public static class UINetworkPolicyActivationCondition
implements Condition<NetworkPolicy, ApicurioRegistry3> {
@Override
public boolean isMet(DependentResource<NetworkPolicy, ApicurioRegistry3> resource,
ApicurioRegistry3 primary, Context<ApicurioRegistry3> context) {
Boolean isManaged = ofNullable(primary.getSpec()).map(ApicurioRegistry3Spec::getUi)
.map(ComponentSpec::getNetworkPolicy).map(NetworkPolicySpec::getEnabled)
.orElse(Boolean.TRUE);
if (!isManaged) {
((UINetworkPolicyResource) resource).delete(primary, context);
}
return isManaged;
}
}

// ===== Studio UI

public static class StudioUIDeploymentActivationCondition
Expand Down Expand Up @@ -158,4 +193,19 @@ public boolean isMet(DependentResource<PodDisruptionBudget, ApicurioRegistry3> r
}
}


public static class StudioUINetworkPolicyActivationCondition
implements Condition<NetworkPolicy, ApicurioRegistry3> {
@Override
public boolean isMet(DependentResource<NetworkPolicy, ApicurioRegistry3> resource,
ApicurioRegistry3 primary, Context<ApicurioRegistry3> context) {
Boolean isManaged = ofNullable(primary.getSpec()).map(ApicurioRegistry3Spec::getStudioUi)
.map(ComponentSpec::getNetworkPolicy).map(NetworkPolicySpec::getEnabled)
.orElse(Boolean.TRUE);
if (!isManaged) {
((StudioUINetworkPolicyResource) resource).delete(primary, context);
}
return isManaged;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.fabric8.kubernetes.api.model.networking.v1.Ingress;
import io.fabric8.kubernetes.api.model.networking.v1.NetworkPolicy;
import io.fabric8.kubernetes.api.model.policy.v1.PodDisruptionBudget;
import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;

import java.util.Map;

import static io.apicurio.registry.operator.resource.ResourceFactory.*;
import static io.apicurio.registry.operator.resource.ResourceFactory.COMPONENT_APP;
import static io.apicurio.registry.operator.resource.ResourceFactory.COMPONENT_STUDIO_UI;
import static io.apicurio.registry.operator.resource.ResourceFactory.COMPONENT_UI;

public class LabelDiscriminators {

Expand Down Expand Up @@ -68,6 +71,20 @@ public AppPodDisruptionBudgetDiscriminator() {
}
}

public static class AppNetworkPolicyDiscriminator extends LabelDiscriminator<NetworkPolicy> {

public static final ResourceDiscriminator<NetworkPolicy, ApicurioRegistry3> INSTANCE = new AppNetworkPolicyDiscriminator();

public AppNetworkPolicyDiscriminator() {
// spotless:off
super(Map.of(
"app.kubernetes.io/name", "apicurio-registry",
"app.kubernetes.io/component", COMPONENT_APP
));
// spotless:on
}
}

// ===== Registry UI

public static class UIDeploymentDiscriminator extends LabelDiscriminator<Deployment> {
Expand Down Expand Up @@ -120,6 +137,20 @@ public UiPodDisruptionBudgetDiscriminator() {
}
}

public static class UINetworkPolicyDiscriminator extends LabelDiscriminator<NetworkPolicy> {

public static final ResourceDiscriminator<NetworkPolicy, ApicurioRegistry3> INSTANCE = new AppNetworkPolicyDiscriminator();

public UINetworkPolicyDiscriminator() {
// spotless:off
super(Map.of(
"app.kubernetes.io/name", "apicurio-registry",
"app.kubernetes.io/component", COMPONENT_UI
));
// spotless:on
}
}

// ===== Studio UI

public static class StudioUIDeploymentDiscriminator extends LabelDiscriminator<Deployment> {
Expand Down Expand Up @@ -173,4 +204,17 @@ public StudioUiPodDisruptionBudgetDiscriminator() {
}
}

public static class StudioUINetworkPolicyDiscriminator extends LabelDiscriminator<NetworkPolicy> {

public static final ResourceDiscriminator<NetworkPolicy, ApicurioRegistry3> INSTANCE = new AppNetworkPolicyDiscriminator();

public StudioUINetworkPolicyDiscriminator() {
// spotless:off
super(Map.of(
"app.kubernetes.io/name", "apicurio-registry",
"app.kubernetes.io/component", COMPONENT_STUDIO_UI
));
// spotless:on
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.fabric8.kubernetes.api.model.apps.DeploymentSpec;
import io.fabric8.kubernetes.api.model.networking.v1.Ingress;
import io.fabric8.kubernetes.api.model.networking.v1.NetworkPolicy;
import io.fabric8.kubernetes.api.model.policy.v1.PodDisruptionBudget;

import java.nio.charset.Charset;
Expand Down Expand Up @@ -39,6 +40,7 @@ public class ResourceFactory {
public static final String RESOURCE_TYPE_SERVICE = "service";
public static final String RESOURCE_TYPE_INGRESS = "ingress";
public static final String RESOURCE_TYPE_POD_DISRUPTION_BUDGET = "poddisruptionbudget";
public static final String RESOURCE_TYPE_NETWORK_POLICY = "networkpolicy";

public Deployment getDefaultAppDeployment(ApicurioRegistry3 primary) {
var r = initDefaultDeployment(primary, COMPONENT_APP,
Expand Down Expand Up @@ -258,6 +260,30 @@ private <T extends HasMetadata> T getDefaultResource(ApicurioRegistry3 primary,
return r;
}

public NetworkPolicy getDefaultAppNetworkPolicy(ApicurioRegistry3 primary) {
var networkPolicy = getDefaultResource(primary, NetworkPolicy.class, RESOURCE_TYPE_NETWORK_POLICY,
COMPONENT_APP);
networkPolicy.getSpec().getPodSelector().getMatchLabels().put("app.kubernetes.io/instance",
primary.getMetadata().getName());
return networkPolicy;
}

public NetworkPolicy getDefaultUINetworkPolicy(ApicurioRegistry3 primary) {
var networkPolicy = getDefaultResource(primary, NetworkPolicy.class, RESOURCE_TYPE_NETWORK_POLICY,
COMPONENT_UI);
networkPolicy.getSpec().getPodSelector().getMatchLabels().put("app.kubernetes.io/instance",
primary.getMetadata().getName());
return networkPolicy;
}

public NetworkPolicy getDefaultStudioUINetworkPolicy(ApicurioRegistry3 primary) {
var networkPolicy = getDefaultResource(primary, NetworkPolicy.class, RESOURCE_TYPE_NETWORK_POLICY,
COMPONENT_STUDIO_UI);
networkPolicy.getSpec().getPodSelector().getMatchLabels().put("app.kubernetes.io/instance",
primary.getMetadata().getName());
return networkPolicy;
}

private void addDefaultLabels(Map<String, String> labels, ApicurioRegistry3 primary, String component) {
labels.putAll(Map.of(
"app", primary.getMetadata().getName(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.fabric8.kubernetes.api.model.networking.v1.Ingress;
import io.fabric8.kubernetes.api.model.networking.v1.NetworkPolicy;
import io.fabric8.kubernetes.api.model.policy.v1.PodDisruptionBudget;
import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
import lombok.AllArgsConstructor;
Expand All @@ -29,16 +30,19 @@ public class ResourceKey<R> {
public static final String APP_SERVICE_ID = "AppServiceResource";
public static final String APP_INGRESS_ID = "AppIngressResource";
public static final String APP_POD_DISRUPTION_BUDGET_ID = "AppPodDisruptionBudgetResource";
public static final String APP_NETWORK_POLICY_ID = "AppNetworkPolicyResource";

public static final String UI_DEPLOYMENT_ID = "UIDeploymentResource";
public static final String UI_SERVICE_ID = "UIServiceResource";
public static final String UI_INGRESS_ID = "UIIngressResource";
public static final String UI_POD_DISRUPTION_BUDGET_ID = "UIPodDisruptionBudgetResource";
public static final String UI_NETWORK_POLICY_ID = "UINetworkPolicyResource";

public static final String STUDIO_UI_DEPLOYMENT_ID = "StudioUIDeploymentResource";
public static final String STUDIO_UI_SERVICE_ID = "StudioUIServiceResource";
public static final String STUDIO_UI_INGRESS_ID = "StudioUIIngressResource";
public static final String STUDIO_UI_POD_DISRUPTION_BUDGET_ID = "StudioUIPodDisruptionBudgetResource";
public static final String STUDIO_UI_NETWORK_POLICY_ID = "StudioUINetworkPolicyResource";

public static final ResourceKey<ApicurioRegistry3> REGISTRY_KEY = new ResourceKey<>(
REGISTRY_ID, ApicurioRegistry3.class,
Expand All @@ -62,6 +66,11 @@ public class ResourceKey<R> {
AppIngressDiscriminator.INSTANCE, ResourceFactory.INSTANCE::getDefaultAppIngress
);

public static final ResourceKey<NetworkPolicy> APP_NETWORK_POLICY_KEY = new ResourceKey<>(
APP_NETWORK_POLICY_ID, NetworkPolicy.class,
AppNetworkPolicyDiscriminator.INSTANCE, ResourceFactory.INSTANCE::getDefaultAppNetworkPolicy
);

public static final ResourceKey<PodDisruptionBudget> APP_POD_DISRUPTION_BUDGET_KEY = new ResourceKey<>(
APP_POD_DISRUPTION_BUDGET_ID, PodDisruptionBudget.class,
AppPodDisruptionBudgetDiscriminator.INSTANCE, ResourceFactory.INSTANCE::getDefaultAppPodDisruptionBudget
Expand All @@ -84,6 +93,11 @@ public class ResourceKey<R> {
UIIngressDiscriminator.INSTANCE, ResourceFactory.INSTANCE::getDefaultUIIngress
);

public static final ResourceKey<NetworkPolicy> UI_NETWORK_POLICY_KEY = new ResourceKey<>(
UI_NETWORK_POLICY_ID, NetworkPolicy.class,
UINetworkPolicyDiscriminator.INSTANCE, ResourceFactory.INSTANCE::getDefaultUINetworkPolicy
);

public static final ResourceKey<PodDisruptionBudget> UI_POD_DISRUPTION_BUDGET_KEY = new ResourceKey<>(
UI_POD_DISRUPTION_BUDGET_ID, PodDisruptionBudget.class,
UiPodDisruptionBudgetDiscriminator.INSTANCE, ResourceFactory.INSTANCE::getDefaultUIPodDisruptionBudget
Expand All @@ -106,6 +120,11 @@ public class ResourceKey<R> {
StudioUIIngressDiscriminator.INSTANCE, ResourceFactory.INSTANCE::getDefaultStudioUIIngress
);

public static final ResourceKey<NetworkPolicy> STUDIO_UI_NETWORK_POLICY_KEY = new ResourceKey<>(
STUDIO_UI_NETWORK_POLICY_ID, NetworkPolicy.class,
StudioUINetworkPolicyDiscriminator.INSTANCE, ResourceFactory.INSTANCE::getDefaultStudioUINetworkPolicy
);

public static final ResourceKey<PodDisruptionBudget> STUDIO_UI_POD_DISRUPTION_BUDGET_KEY = new ResourceKey<>(
STUDIO_UI_POD_DISRUPTION_BUDGET_ID, PodDisruptionBudget.class,
StudioUiPodDisruptionBudgetDiscriminator.INSTANCE, ResourceFactory.INSTANCE::getDefaultStudioUIPodDisruptionBudget
Expand Down
Loading

0 comments on commit 1f99c3d

Please sign in to comment.