use of org.bf2.cos.fleetshard.support.resources.Operators in project cos-fleetshard by bf2fc6cc711aee1a0c2a.
the class ConnectorProvisionerTest method updateResources.
@Test
void updateResources() {
//
// Given that the resources associated to the provided deployment exist
//
final ConnectorDeployment oldDeployment = createDeployment(0);
final List<ManagedConnector> connectors = List.of(new ManagedConnectorBuilder().withMetadata(new ObjectMetaBuilder().withName(Connectors.generateConnectorId(oldDeployment.getId())).addToLabels(LABEL_CLUSTER_ID, CLUSTER_ID).addToLabels(LABEL_CONNECTOR_ID, oldDeployment.getSpec().getConnectorId()).addToLabels(LABEL_DEPLOYMENT_ID, oldDeployment.getId()).build()).build());
final List<Secret> secrets = List.of(new SecretBuilder().withMetadata(new ObjectMetaBuilder().withName(Secrets.generateConnectorSecretId(oldDeployment.getId())).addToLabels(LABEL_CLUSTER_ID, CLUSTER_ID).addToLabels(LABEL_CONNECTOR_ID, oldDeployment.getSpec().getConnectorId()).addToLabels(LABEL_DEPLOYMENT_ID, oldDeployment.getId()).addToLabels(LABEL_DEPLOYMENT_RESOURCE_VERSION, "" + oldDeployment.getMetadata().getResourceVersion()).build()).build());
final FleetShardClient fleetShard = ConnectorTestSupport.fleetShard(CLUSTER_ID, connectors, secrets);
final FleetManagerClient fleetManager = ConnectorTestSupport.fleetManagerClient();
final FleetShardSyncConfig config = ConnectorTestSupport.config();
final MeterRegistry registry = Mockito.mock(MeterRegistry.class);
final ConnectorDeploymentProvisioner provisioner = new ConnectorDeploymentProvisioner(config, fleetShard, fleetManager, registry);
final ArgumentCaptor<Secret> sc = ArgumentCaptor.forClass(Secret.class);
final ArgumentCaptor<ManagedConnector> mcc = ArgumentCaptor.forClass(ManagedConnector.class);
//
// When deployment is updated
//
final ConnectorDeployment newDeployment = createDeployment(0, d -> {
d.getSpec().getKafka().setUrl("my-kafka.acme.com:218");
((ObjectNode) d.getSpec().getConnectorSpec()).with("connector").put("foo", "connector-baz");
((ObjectNode) d.getSpec().getShardMetadata()).put("connector_image", "quay.io/mcs_dev/aws-s3-sink:0.1.0");
});
provisioner.provision(newDeployment);
verify(fleetShard).createSecret(sc.capture());
verify(fleetShard).createConnector(mcc.capture());
//
// Then the existing resources must be updated to reflect the changes made to the
// deployment. This scenario could happen when a resource on the connector cluster
// is amended outside the control of fleet manager (i.e. with kubectl) and in such
// case, the expected behavior is that the resource is re-set to the configuration
// from the fleet manager.
//
assertThat(sc.getValue()).satisfies(val -> {
assertThat(val.getMetadata().getName()).isEqualTo(Secrets.generateConnectorSecretId(oldDeployment.getId()));
assertThat(val.getMetadata().getLabels()).containsEntry(LABEL_CLUSTER_ID, CLUSTER_ID).containsEntry(LABEL_CONNECTOR_ID, newDeployment.getSpec().getConnectorId()).containsEntry(LABEL_DEPLOYMENT_ID, newDeployment.getId()).containsEntry(LABEL_DEPLOYMENT_RESOURCE_VERSION, "" + newDeployment.getMetadata().getResourceVersion()).containsKey(LABEL_UOW);
assertThat(val.getData()).containsKey(Secrets.SECRET_ENTRY_SERVICE_ACCOUNT).containsKey(Secrets.SECRET_ENTRY_CONNECTOR);
var serviceAccountNode = Secrets.extract(val, Secrets.SECRET_ENTRY_SERVICE_ACCOUNT, ServiceAccount.class);
assertThat(serviceAccountNode.getClientSecret()).isEqualTo(newDeployment.getSpec().getServiceAccount().getClientSecret());
assertThat(serviceAccountNode.getClientId()).isEqualTo(newDeployment.getSpec().getServiceAccount().getClientId());
var connectorNode = Secrets.extract(val, Secrets.SECRET_ENTRY_CONNECTOR);
assertThatJson(Secrets.extract(val, Secrets.SECRET_ENTRY_CONNECTOR)).inPath("connector.foo").isEqualTo("connector-baz");
assertThatJson(connectorNode).inPath("kafka.topic").isEqualTo("kafka-foo");
var metaNode = Secrets.extract(val, Secrets.SECRET_ENTRY_META);
assertThatJson(metaNode).isObject().containsKey("connector_type").containsKey("connector_image").containsKey("kamelets").containsKey("operators");
});
assertThat(mcc.getValue()).satisfies(val -> {
assertThat(val.getMetadata().getName()).isEqualTo(Connectors.generateConnectorId(oldDeployment.getId()));
assertThat(val.getMetadata().getLabels()).containsEntry(LABEL_CLUSTER_ID, CLUSTER_ID).containsEntry(LABEL_CONNECTOR_ID, oldDeployment.getSpec().getConnectorId()).containsEntry(LABEL_DEPLOYMENT_ID, oldDeployment.getId()).containsKey(LABEL_UOW);
assertThat(val.getSpec().getDeployment()).satisfies(d -> {
assertThat(d.getDeploymentResourceVersion()).isEqualTo(oldDeployment.getMetadata().getResourceVersion());
assertThat(d.getDeploymentResourceVersion()).isEqualTo(newDeployment.getMetadata().getResourceVersion());
assertThat(d.getSecret()).isEqualTo(sc.getValue().getMetadata().getName());
assertThat(d.getUnitOfWork()).isNotEmpty().isEqualTo(sc.getValue().getMetadata().getLabels().get(LABEL_UOW));
assertThat(d.getKafka().getUrl()).isNotEmpty().isEqualTo(newDeployment.getSpec().getKafka().getUrl());
});
});
}
use of org.bf2.cos.fleetshard.support.resources.Operators in project cos-fleetshard by bf2fc6cc711aee1a0c2a.
the class ConnectorProvisionerTest method updateAndCreateResources.
@Test
void updateAndCreateResources() {
//
// Given that the resources associated to the provided deployment exist
//
final ConnectorDeployment oldDeployment = createDeployment(0);
final List<ManagedConnector> connectors = List.of(new ManagedConnectorBuilder().withMetadata(new ObjectMetaBuilder().withName(Connectors.generateConnectorId(oldDeployment.getId())).addToLabels(LABEL_CLUSTER_ID, CLUSTER_ID).addToLabels(LABEL_CONNECTOR_ID, oldDeployment.getSpec().getConnectorId()).addToLabels(LABEL_DEPLOYMENT_ID, oldDeployment.getId()).build()).build());
final List<Secret> secrets = List.of(new SecretBuilder().withMetadata(new ObjectMetaBuilder().withName(Secrets.generateConnectorSecretId(oldDeployment.getId())).addToLabels(LABEL_CLUSTER_ID, CLUSTER_ID).addToLabels(LABEL_CONNECTOR_ID, oldDeployment.getSpec().getConnectorId()).addToLabels(LABEL_DEPLOYMENT_ID, oldDeployment.getId()).addToLabels(LABEL_DEPLOYMENT_RESOURCE_VERSION, "" + oldDeployment.getMetadata().getResourceVersion()).build()).build());
final FleetShardClient fleetShard = ConnectorTestSupport.fleetShard(CLUSTER_ID, connectors, secrets);
final FleetManagerClient fleetManager = ConnectorTestSupport.fleetManagerClient();
final FleetShardSyncConfig config = ConnectorTestSupport.config();
final MeterRegistry registry = Mockito.mock(MeterRegistry.class);
final ConnectorDeploymentProvisioner provisioner = new ConnectorDeploymentProvisioner(config, fleetShard, fleetManager, registry);
final ArgumentCaptor<Secret> sc = ArgumentCaptor.forClass(Secret.class);
final ArgumentCaptor<ManagedConnector> mcc = ArgumentCaptor.forClass(ManagedConnector.class);
//
// When a change to the deployment happen that ends up with a new resource version
//
final ConnectorDeployment newDeployment = createDeployment(1, d -> {
d.getMetadata().setResourceVersion(1L);
d.getSpec().getKafka().setUrl("my-kafka.acme.com:218");
((ObjectNode) d.getSpec().getConnectorSpec()).with("connector").put("foo", "connector-baz");
((ObjectNode) d.getSpec().getShardMetadata()).put("connector_image", "quay.io/mcs_dev/aws-s3-sink:0.1.0");
});
provisioner.provision(newDeployment);
verify(fleetShard).createSecret(sc.capture());
verify(fleetShard).createConnector(mcc.capture());
//
// Then the managed connector resource is expected to be updated to reflect the
// changes made to the deployment
//
assertThat(sc.getValue()).satisfies(val -> {
assertThat(val.getMetadata().getName()).isEqualTo(Secrets.generateConnectorSecretId(oldDeployment.getId()));
assertThat(val.getMetadata().getLabels()).containsEntry(LABEL_CLUSTER_ID, CLUSTER_ID).containsEntry(LABEL_CONNECTOR_ID, newDeployment.getSpec().getConnectorId()).containsEntry(LABEL_DEPLOYMENT_ID, newDeployment.getId()).containsEntry(LABEL_DEPLOYMENT_RESOURCE_VERSION, "" + newDeployment.getMetadata().getResourceVersion()).containsKey(LABEL_UOW);
assertThat(val.getData()).containsKey(Secrets.SECRET_ENTRY_SERVICE_ACCOUNT).containsKey(Secrets.SECRET_ENTRY_CONNECTOR);
var serviceAccountNode = Secrets.extract(val, Secrets.SECRET_ENTRY_SERVICE_ACCOUNT, ServiceAccount.class);
assertThat(serviceAccountNode.getClientSecret()).isEqualTo(newDeployment.getSpec().getServiceAccount().getClientSecret());
assertThat(serviceAccountNode.getClientId()).isEqualTo(newDeployment.getSpec().getServiceAccount().getClientId());
var connectorNode = Secrets.extract(val, Secrets.SECRET_ENTRY_CONNECTOR);
assertThatJson(Secrets.extract(val, Secrets.SECRET_ENTRY_CONNECTOR)).inPath("connector.foo").isEqualTo("connector-baz");
assertThatJson(connectorNode).inPath("kafka.topic").isEqualTo("kafka-foo");
var metaNode = Secrets.extract(val, Secrets.SECRET_ENTRY_META);
assertThatJson(metaNode).isObject().containsKey("connector_type").containsKey("connector_image").containsKey("kamelets").containsKey("operators");
});
assertThat(mcc.getValue()).satisfies(val -> {
assertThat(val.getMetadata().getName()).isEqualTo(Connectors.generateConnectorId(oldDeployment.getId()));
assertThat(val.getMetadata().getLabels()).containsEntry(LABEL_CLUSTER_ID, CLUSTER_ID).containsEntry(LABEL_CONNECTOR_ID, oldDeployment.getSpec().getConnectorId()).containsEntry(LABEL_DEPLOYMENT_ID, oldDeployment.getId()).containsKey(LABEL_UOW);
assertThat(val.getSpec().getDeployment()).satisfies(d -> {
assertThat(d.getDeploymentResourceVersion()).isEqualTo(newDeployment.getMetadata().getResourceVersion());
assertThat(d.getDeploymentResourceVersion()).isNotEqualTo(oldDeployment.getMetadata().getResourceVersion());
assertThat(d.getSecret()).isEqualTo(sc.getValue().getMetadata().getName());
assertThat(d.getUnitOfWork()).isNotEmpty().isEqualTo(sc.getValue().getMetadata().getLabels().get(LABEL_UOW));
assertThat(d.getKafka().getUrl()).isNotEmpty().isEqualTo(newDeployment.getSpec().getKafka().getUrl());
});
});
}
use of org.bf2.cos.fleetshard.support.resources.Operators in project cos-fleetshard by bf2fc6cc711aee1a0c2a.
the class ConnectorProvisionerTest method createResources.
@Test
void createResources() {
//
// Given that no resources associated to the provided deployment exist
//
final ConnectorDeployment deployment = createDeployment(0);
final List<ManagedConnector> connectors = List.of();
final List<Secret> secrets = List.of();
final FleetShardClient fleetShard = ConnectorTestSupport.fleetShard(CLUSTER_ID, connectors, secrets);
final FleetManagerClient fleetManager = ConnectorTestSupport.fleetManagerClient();
final FleetShardSyncConfig config = ConnectorTestSupport.config();
final MeterRegistry registry = Mockito.mock(MeterRegistry.class);
final ArgumentCaptor<Secret> sc = ArgumentCaptor.forClass(Secret.class);
final ArgumentCaptor<ManagedConnector> mcc = ArgumentCaptor.forClass(ManagedConnector.class);
final ConnectorDeploymentProvisioner provisioner = new ConnectorDeploymentProvisioner(config, fleetShard, fleetManager, registry);
//
// When deployment is applied
//
provisioner.provision(deployment);
verify(fleetShard).createSecret(sc.capture());
verify(fleetShard).createConnector(mcc.capture());
//
// Then resources must be created according to the deployment
//
assertThat(sc.getValue()).satisfies(val -> {
assertThat(val.getMetadata().getName()).isEqualTo(Secrets.generateConnectorSecretId(deployment.getId()));
assertThat(val.getMetadata().getLabels()).containsEntry(LABEL_CLUSTER_ID, CLUSTER_ID).containsEntry(LABEL_CONNECTOR_ID, deployment.getSpec().getConnectorId()).containsEntry(LABEL_DEPLOYMENT_ID, deployment.getId()).containsEntry(LABEL_DEPLOYMENT_RESOURCE_VERSION, "" + deployment.getMetadata().getResourceVersion()).containsKey(LABEL_UOW);
assertThat(val.getData()).containsKey(Secrets.SECRET_ENTRY_SERVICE_ACCOUNT).containsKey(Secrets.SECRET_ENTRY_CONNECTOR);
var serviceAccountNode = Secrets.extract(val, Secrets.SECRET_ENTRY_SERVICE_ACCOUNT, ServiceAccount.class);
assertThat(serviceAccountNode.getClientSecret()).isEqualTo(deployment.getSpec().getServiceAccount().getClientSecret());
assertThat(serviceAccountNode.getClientId()).isEqualTo(deployment.getSpec().getServiceAccount().getClientId());
var connectorNode = Secrets.extract(val, Secrets.SECRET_ENTRY_CONNECTOR);
assertThatJson(Secrets.extract(val, Secrets.SECRET_ENTRY_CONNECTOR)).inPath("connector.foo").isEqualTo("connector-foo");
assertThatJson(connectorNode).inPath("kafka.topic").isEqualTo("kafka-foo");
var metaNode = Secrets.extract(val, Secrets.SECRET_ENTRY_META);
assertThatJson(metaNode).isObject().containsKey("connector_type").containsKey("connector_image").containsKey("kamelets").containsKey("operators");
});
assertThat(mcc.getValue()).satisfies(val -> {
assertThat(val.getMetadata().getName()).isEqualTo(Connectors.generateConnectorId(deployment.getId()));
assertThat(val.getMetadata().getLabels()).containsEntry(LABEL_CLUSTER_ID, CLUSTER_ID).containsEntry(LABEL_CONNECTOR_ID, deployment.getSpec().getConnectorId()).containsEntry(LABEL_DEPLOYMENT_ID, deployment.getId()).containsKey(LABEL_UOW);
assertThat(val.getSpec().getDeployment()).satisfies(d -> {
assertThat(d.getSecret()).isEqualTo(sc.getValue().getMetadata().getName());
assertThat(d.getUnitOfWork()).isNotEmpty().isEqualTo(sc.getValue().getMetadata().getLabels().get(LABEL_UOW));
assertThat(d.getKafka().getUrl()).isNotEmpty().isEqualTo(deployment.getSpec().getKafka().getUrl());
});
});
}
use of org.bf2.cos.fleetshard.support.resources.Operators in project cos-fleetshard by bf2fc6cc711aee1a0c2a.
the class ConnectorDeploymentProvisioner method createManagedConnector.
private ManagedConnector createManagedConnector(String uow, ConnectorDeployment deployment, HasMetadata owner) {
ManagedConnector connector = fleetShard.getConnector(deployment).orElseGet(() -> {
LOGGER.info("Connector not found (cluster_id: {}, namespace_id: {}, connector_id: {}, deployment_id: {}, resource_version: {}), creating a new one", fleetShard.getClusterId(), deployment.getSpec().getNamespaceId(), deployment.getSpec().getConnectorId(), deployment.getId(), deployment.getMetadata().getResourceVersion());
ManagedConnector answer = new ManagedConnector();
answer.setMetadata(new ObjectMeta());
answer.getMetadata().setNamespace(fleetShard.generateNamespaceId(deployment.getSpec().getNamespaceId()));
answer.getMetadata().setName(Connectors.generateConnectorId(deployment.getId()));
Resources.setLabels(answer, LABEL_CLUSTER_ID, fleetShard.getClusterId(), LABEL_CONNECTOR_ID, deployment.getSpec().getConnectorId(), LABEL_DEPLOYMENT_ID, deployment.getId());
answer.getSpec().setClusterId(fleetShard.getClusterId());
answer.getSpec().setConnectorId(deployment.getSpec().getConnectorId());
answer.getSpec().setDeploymentId(deployment.getId());
return answer;
});
// TODO: change APIs to include a single operator
// move operator one level up
// include full operator info in ConnectorDeployment APIs
ArrayNode operatorsMeta = deployment.getSpec().getShardMetadata().withArray("operators");
if (operatorsMeta.size() != 1) {
throw new IllegalArgumentException("Multiple selectors are not yet supported");
}
OperatorSelector operatorSelector = new OperatorSelector(deployment.getSpec().getOperatorId(), operatorsMeta.get(0).requiredAt("/type").asText(), operatorsMeta.get(0).requiredAt("/version").asText());
if (operatorSelector.getId() == null) {
final OperatorSelector currentSelector = connector.getSpec().getOperatorSelector();
// don't select a new operator if previously set.
if (currentSelector != null && currentSelector.getId() != null) {
operatorSelector.setId(currentSelector.getId());
} else {
Collection<Operator> operators = fleetShard.getOperators().stream().map(mco -> new Operator(mco.getMetadata().getName(), mco.getSpec().getType(), mco.getSpec().getVersion())).collect(Collectors.toList());
OperatorSelectorUtil.assign(operatorSelector, operators).map(Operator::getId).ifPresent(operatorSelector::setId);
}
}
if (operatorSelector.getId() != null) {
Resources.setLabel(connector, LABEL_OPERATOR_ASSIGNED, operatorSelector.getId());
}
if (operatorSelector.getType() != null) {
Resources.setLabel(connector, LABEL_OPERATOR_TYPE, operatorSelector.getType());
}
if (config != null) {
config.connectors().labels().forEach((k, v) -> {
Resources.setLabel(connector, k, v);
});
config.connectors().annotations().forEach((k, v) -> {
Resources.setAnnotation(connector, k, v);
});
}
Resources.setOwnerReferences(connector, owner);
// add resource version to label
Resources.setLabel(connector, LABEL_DEPLOYMENT_RESOURCE_VERSION, "" + deployment.getMetadata().getResourceVersion());
// add uow
Resources.setLabel(connector, LABEL_UOW, uow);
connector.getSpec().getDeployment().setDeploymentResourceVersion(deployment.getMetadata().getResourceVersion());
connector.getSpec().getDeployment().setDesiredState(deployment.getSpec().getDesiredState().getValue());
connector.getSpec().getDeployment().setConnectorTypeId(deployment.getSpec().getConnectorTypeId());
connector.getSpec().getDeployment().setConnectorResourceVersion(deployment.getSpec().getConnectorResourceVersion());
KafkaConnectionSettings kafkaConnectionSettings = deployment.getSpec().getKafka();
if (kafkaConnectionSettings != null) {
connector.getSpec().getDeployment().setKafka(new KafkaSpec(kafkaConnectionSettings.getId(), kafkaConnectionSettings.getUrl()));
}
SchemaRegistryConnectionSettings schemaRegistryConnectionSettings = deployment.getSpec().getSchemaRegistry();
if (schemaRegistryConnectionSettings != null) {
connector.getSpec().getDeployment().setSchemaRegistry(new SchemaRegistrySpec(schemaRegistryConnectionSettings.getId(), schemaRegistryConnectionSettings.getUrl()));
}
connector.getSpec().getDeployment().setConnectorResourceVersion(deployment.getSpec().getConnectorResourceVersion());
connector.getSpec().getDeployment().setSecret(Secrets.generateConnectorSecretId(deployment.getId()));
connector.getSpec().getDeployment().setUnitOfWork(uow);
connector.getSpec().setOperatorSelector(operatorSelector);
LOGGER.info("Provisioning connector namespace: {}, name: {}, revision: {}", connector.getMetadata().getNamespace(), connector.getMetadata().getName(), connector.getSpec().getDeployment().getDeploymentResourceVersion());
try {
return fleetShard.createConnector(connector);
} catch (Exception e) {
LOGGER.warn("", e);
throw e;
}
}
use of org.bf2.cos.fleetshard.support.resources.Operators in project cos-fleetshard by bf2fc6cc711aee1a0c2a.
the class ClusterStatusUpdaterWithOperatorTest method statusIsUpdated.
@Test
void statusIsUpdated() {
final String statusUrl = "/api/connector_mgmt/v1/agent/kafka_connector_clusters/" + config.cluster().id() + "/status";
final String operatorId = uid();
kubernetesClient.resources(ManagedConnectorOperator.class).inNamespace(ns).create(new ManagedConnectorOperatorBuilder().withNewMetadata().withName(operatorId).endMetadata().withSpec(new ManagedConnectorOperatorSpecBuilder().withType("operator-type").withVersion("999").withRuntime("operator-runtime").build()).build());
RestAssured.given().contentType(MediaType.TEXT_PLAIN).post("/test/provisioner/all");
untilAsserted(() -> {
server.verify(putRequestedFor(urlEqualTo(statusUrl)).withHeader(ContentTypeHeader.KEY, equalTo(APPLICATION_JSON)).withRequestBody(jp("$.phase", "ready")).withRequestBody(jp("$.operators.size()", "1")).withRequestBody(jp("$.operators[0].namespace", ns)).withRequestBody(jp("$.operators[0].status", "ready")).withRequestBody(jp("$.operators[0].operator.id", operatorId)).withRequestBody(jp("$.operators[0].operator.type", "operator-type")).withRequestBody(jp("$.operators[0].operator.version", "999")));
});
}
Aggregations