package io.cattle.platform.servicediscovery.dao.impl; import static io.cattle.platform.core.model.tables.HostTable.*; import static io.cattle.platform.core.model.tables.InstanceHostMapTable.*; import static io.cattle.platform.core.model.tables.InstanceTable.*; import static io.cattle.platform.core.model.tables.ServiceExposeMapTable.*; import static io.cattle.platform.core.model.tables.ServiceTable.*; import io.cattle.platform.core.constants.CommonStatesConstants; import io.cattle.platform.core.constants.InstanceConstants; import io.cattle.platform.core.constants.ServiceConstants; import io.cattle.platform.core.dao.GenericMapDao; import io.cattle.platform.core.model.Host; import io.cattle.platform.core.model.Instance; import io.cattle.platform.core.model.Service; import io.cattle.platform.core.model.ServiceExposeMap; import io.cattle.platform.core.model.tables.records.HostRecord; import io.cattle.platform.core.model.tables.records.InstanceRecord; import io.cattle.platform.core.model.tables.records.ServiceExposeMapRecord; import io.cattle.platform.core.model.tables.records.ServiceRecord; import io.cattle.platform.db.jooq.dao.impl.AbstractJooqDao; import io.cattle.platform.object.ObjectManager; import io.cattle.platform.object.jooq.utils.JooqUtils; import io.cattle.platform.object.process.ObjectProcessManager; import io.cattle.platform.object.util.DataAccessor; import io.cattle.platform.servicediscovery.api.dao.ServiceExposeMapDao; import io.cattle.platform.servicediscovery.api.util.ServiceDiscoveryUtil; import io.cattle.platform.servicediscovery.service.ServiceDiscoveryService; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import javax.inject.Inject; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.TransformerUtils; import org.apache.commons.lang3.tuple.Pair; import org.jooq.Condition; import org.jooq.Configuration; import org.jooq.impl.DSL; public class ServiceExposeMapDaoImpl extends AbstractJooqDao implements ServiceExposeMapDao { @Inject ObjectManager objectManager; @Inject ObjectProcessManager objectProcessManager; @Inject ServiceDiscoveryService sdService; @Inject GenericMapDao mapDao; Configuration lockingConfiguration; @Override public Pair<Instance, ServiceExposeMap> createServiceInstance(Map<String, Object> properties, Service service) { final ServiceRecord record = JooqUtils.getRecordObject(objectManager.loadResource(Service.class, service.getId())); record.attach(lockingConfiguration); record.setCreateIndex((record.getCreateIndex() == null ? 0 : record.getCreateIndex()) + 1); record.update(); properties.put(InstanceConstants.FIELD_CREATE_INDEX, record.getCreateIndex()); properties.put(ServiceConstants.FIELD_SYSTEM, ServiceConstants.isSystem(service)); final Instance instance = objectManager.create(Instance.class, properties); ServiceExposeMap exposeMap = createServiceInstanceMap(service, instance, true); return Pair.of(instance, exposeMap); } @Override @SuppressWarnings("unchecked") public ServiceExposeMap createServiceInstanceMap(Service service, final Instance instance, boolean managed) { Map<String, String> instanceLabels = DataAccessor.fields(instance) .withKey(InstanceConstants.FIELD_LABELS).withDefault(Collections.EMPTY_MAP).as(Map.class); String dnsPrefix = instanceLabels .get(ServiceConstants.LABEL_SERVICE_LAUNCH_CONFIG); if (ServiceConstants.PRIMARY_LAUNCH_CONFIG_NAME.equalsIgnoreCase(dnsPrefix)) { dnsPrefix = null; } ServiceExposeMap map = getServiceInstanceMap(service, instance); if (map == null) { map = objectManager.create(ServiceExposeMap.class, SERVICE_EXPOSE_MAP.INSTANCE_ID, instance.getId(), SERVICE_EXPOSE_MAP.SERVICE_ID, service.getId(), SERVICE_EXPOSE_MAP.ACCOUNT_ID, service.getAccountId(), SERVICE_EXPOSE_MAP.DNS_PREFIX, dnsPrefix, SERVICE_EXPOSE_MAP.MANAGED, managed); } return map; } @Override public ServiceExposeMap getServiceInstanceMap(Service service, final Instance instance) { return objectManager.findAny(ServiceExposeMap.class, SERVICE_EXPOSE_MAP.INSTANCE_ID, instance.getId(), SERVICE_EXPOSE_MAP.SERVICE_ID, service.getId(), SERVICE_EXPOSE_MAP.REMOVED, null); } @Override public List<? extends Instance> listServiceManagedInstances(Service service) { return create() .select(INSTANCE.fields()) .from(INSTANCE) .join(SERVICE_EXPOSE_MAP) .on(SERVICE_EXPOSE_MAP.INSTANCE_ID.eq(INSTANCE.ID) .and(SERVICE_EXPOSE_MAP.SERVICE_ID.eq(service.getId())) .and(SERVICE_EXPOSE_MAP.MANAGED.eq(true)) .and(SERVICE_EXPOSE_MAP.STATE.in(CommonStatesConstants.ACTIVATING, CommonStatesConstants.ACTIVE, CommonStatesConstants.REQUESTED)) .and(INSTANCE.STATE.notIn(CommonStatesConstants.PURGING, CommonStatesConstants.PURGED, CommonStatesConstants.REMOVED, CommonStatesConstants.REMOVING, InstanceConstants.STATE_ERROR, InstanceConstants.STATE_ERRORING)) .and(SERVICE_EXPOSE_MAP.DNS_PREFIX.isNull().or( SERVICE_EXPOSE_MAP.DNS_PREFIX.in(ServiceDiscoveryUtil .getServiceLaunchConfigNames(service))))) .fetchInto(InstanceRecord.class); } @Override public List<? extends Instance> listServiceManagedInstancesAll(Service service) { return create() .select(INSTANCE.fields()) .from(INSTANCE) .join(SERVICE_EXPOSE_MAP) .on(SERVICE_EXPOSE_MAP.INSTANCE_ID.eq(INSTANCE.ID) .and(SERVICE_EXPOSE_MAP.SERVICE_ID.eq(service.getId())) .and(SERVICE_EXPOSE_MAP.MANAGED.eq(true)) .and(SERVICE_EXPOSE_MAP.STATE.in(CommonStatesConstants.ACTIVATING, CommonStatesConstants.ACTIVE, CommonStatesConstants.REQUESTED)) .and(SERVICE_EXPOSE_MAP.DNS_PREFIX.isNull().or( SERVICE_EXPOSE_MAP.DNS_PREFIX.in(ServiceDiscoveryUtil .getServiceLaunchConfigNames(service))))) .fetchInto(InstanceRecord.class); } @Override public Integer getCurrentScale(long serviceId) { return create() .select(DSL.count()) .from(INSTANCE) .join(SERVICE_EXPOSE_MAP) .on(SERVICE_EXPOSE_MAP.INSTANCE_ID.eq(INSTANCE.ID) .and(SERVICE_EXPOSE_MAP.SERVICE_ID.eq(serviceId)) .and(SERVICE_EXPOSE_MAP.STATE.in(CommonStatesConstants.ACTIVATING, CommonStatesConstants.ACTIVE, CommonStatesConstants.REQUESTED)) .and(SERVICE_EXPOSE_MAP.UPGRADE.eq(false)) .and(INSTANCE.STATE.notIn(CommonStatesConstants.PURGING, CommonStatesConstants.PURGED, CommonStatesConstants.REMOVED, CommonStatesConstants.REMOVING, InstanceConstants.STATE_ERROR, InstanceConstants.STATE_ERRORING))) .and(SERVICE_EXPOSE_MAP.DNS_PREFIX.isNull()) .fetchOne(0, Integer.class); } @Override public List<? extends Instance> listServiceManagedInstances(Service service, String launchConfigName) { Condition condition = null; if (launchConfigName == null || launchConfigName.equals(service.getName()) || launchConfigName.equals(ServiceConstants.PRIMARY_LAUNCH_CONFIG_NAME)) { condition = SERVICE_EXPOSE_MAP.DNS_PREFIX.isNull(); } else { condition = SERVICE_EXPOSE_MAP.DNS_PREFIX.eq(launchConfigName); } List<? extends Instance> instances = create() .select(INSTANCE.fields()) .from(INSTANCE) .join(SERVICE_EXPOSE_MAP) .on(SERVICE_EXPOSE_MAP.INSTANCE_ID.eq(INSTANCE.ID) .and(SERVICE_EXPOSE_MAP.SERVICE_ID.eq(service.getId())) .and(SERVICE_EXPOSE_MAP.MANAGED.eq(true)) .and(SERVICE_EXPOSE_MAP.STATE.in(CommonStatesConstants.ACTIVATING, CommonStatesConstants.ACTIVE, CommonStatesConstants.REQUESTED)) .and(INSTANCE.STATE.notIn(CommonStatesConstants.PURGING, CommonStatesConstants.PURGED, CommonStatesConstants.REMOVED, CommonStatesConstants.REMOVING, InstanceConstants.STATE_ERROR, InstanceConstants.STATE_ERRORING)) .and(condition)) .fetchInto(InstanceRecord.class); List<? extends Host> validHosts = create() .select(HOST.fields()) .from(HOST) .where(HOST.ACCOUNT_ID.eq(service.getAccountId())) .and(HOST.STATE.notIn(CommonStatesConstants.REMOVED, CommonStatesConstants.REMOVING, CommonStatesConstants.PURGED, CommonStatesConstants.PURGING)) .and(HOST.ACCOUNT_ID.eq(service.getAccountId())) .fetchInto(HostRecord.class); @SuppressWarnings("unchecked") List<Long> validHostIds = (List<Long>) CollectionUtils.collect(validHosts, TransformerUtils.invokerTransformer("getId")); List<Instance> toReturn = new ArrayList<>(); for (Instance instance : instances) { Long hostId = DataAccessor.fieldLong(instance, InstanceConstants.FIELD_HOST_ID); if (hostId == null || validHostIds.contains(hostId)) { toReturn.add(instance); } } return toReturn; } @Override public ServiceExposeMap findInstanceExposeMap(Instance instance) { if (instance == null) { return null; } List<? extends ServiceExposeMap> instanceServiceMap = mapDao.findNonRemoved(ServiceExposeMap.class, Instance.class, instance.getId()); if (instanceServiceMap.isEmpty()) { // not a service instance return null; } return instanceServiceMap.get(0); } @Override public ServiceExposeMap createIpToServiceMap(Service service, String ipAddress) { ServiceExposeMap map = getServiceIpExposeMap(service, ipAddress); if (map == null) { map = objectManager.create(ServiceExposeMap.class, SERVICE_EXPOSE_MAP.SERVICE_ID, service.getId(), SERVICE_EXPOSE_MAP.IP_ADDRESS, ipAddress, SERVICE_EXPOSE_MAP.ACCOUNT_ID, service.getAccountId()); } return map; } @Override public ServiceExposeMap getServiceIpExposeMap(Service service, String ipAddress) { return objectManager.findAny(ServiceExposeMap.class, SERVICE_EXPOSE_MAP.SERVICE_ID, service.getId(), SERVICE_EXPOSE_MAP.IP_ADDRESS, ipAddress, SERVICE_EXPOSE_MAP.REMOVED, null); } @Override public List<? extends Service> getActiveServices(long accountId) { return create() .select(SERVICE.fields()) .from(SERVICE) .where(SERVICE.ACCOUNT_ID.eq(accountId)) .and(SERVICE.REMOVED.isNull()) .and(SERVICE.STATE.in(sdService.getServiceActiveStates())) .fetchInto(ServiceRecord.class); } @Override public List<? extends ServiceExposeMap> getNonRemovedServiceIpMaps(long serviceId) { return create() .select(SERVICE_EXPOSE_MAP.fields()) .from(SERVICE_EXPOSE_MAP) .where(SERVICE_EXPOSE_MAP.SERVICE_ID.eq(serviceId)) .and(SERVICE_EXPOSE_MAP.REMOVED.isNull() .and(SERVICE_EXPOSE_MAP.STATE.notIn(CommonStatesConstants.REMOVED, CommonStatesConstants.REMOVING)) .and(SERVICE_EXPOSE_MAP.IP_ADDRESS.isNotNull())) .fetchInto(ServiceExposeMapRecord.class); } @Override public Host getHostForInstance(long instanceId) { List<? extends Host> results = create() .select(HOST.fields()) .from(HOST) .join(INSTANCE_HOST_MAP) .on(HOST.ID.eq(INSTANCE_HOST_MAP.HOST_ID)) .where(INSTANCE_HOST_MAP.INSTANCE_ID.eq(instanceId)) .fetchInto(HostRecord.class); if (results.size() > 0) { return results.get(0); } return null; } @Override public ServiceExposeMap getServiceHostnameExposeMap(Service service, String hostName) { return objectManager.findAny(ServiceExposeMap.class, SERVICE_EXPOSE_MAP.SERVICE_ID, service.getId(), SERVICE_EXPOSE_MAP.HOST_NAME, hostName, SERVICE_EXPOSE_MAP.REMOVED, null); } @Override public ServiceExposeMap createHostnameToServiceMap(Service service, String hostName) { ServiceExposeMap map = getServiceHostnameExposeMap(service, hostName); if (map == null) { map = objectManager.create(ServiceExposeMap.class, SERVICE_EXPOSE_MAP.SERVICE_ID, service.getId(), SERVICE_EXPOSE_MAP.HOST_NAME, hostName, SERVICE_EXPOSE_MAP.ACCOUNT_ID, service.getAccountId()); } return map; } @Override public List<? extends ServiceExposeMap> getNonRemovedServiceHostnameMaps(long serviceId) { return create() .select(SERVICE_EXPOSE_MAP.fields()) .from(SERVICE_EXPOSE_MAP) .where(SERVICE_EXPOSE_MAP.SERVICE_ID.eq(serviceId)) .and(SERVICE_EXPOSE_MAP.REMOVED.isNull() .and(SERVICE_EXPOSE_MAP.STATE.notIn(CommonStatesConstants.REMOVED, CommonStatesConstants.REMOVING)) .and(SERVICE_EXPOSE_MAP.HOST_NAME.isNotNull())) .fetchInto(ServiceExposeMapRecord.class); } public Configuration getLockingConfiguration() { return lockingConfiguration; } public void setLockingConfiguration(Configuration lockingConfiguration) { this.lockingConfiguration = lockingConfiguration; } @Override public List<? extends ServiceExposeMap> getUnmanagedServiceInstanceMapsToRemove(long serviceId) { return create() .select(SERVICE_EXPOSE_MAP.fields()) .from(SERVICE_EXPOSE_MAP) .join(INSTANCE) .on(SERVICE_EXPOSE_MAP.INSTANCE_ID.eq(INSTANCE.ID) .and(SERVICE_EXPOSE_MAP.SERVICE_ID.eq(serviceId)) .and(SERVICE_EXPOSE_MAP.REMOVED.isNull()) .and(SERVICE_EXPOSE_MAP.MANAGED.eq(false)) .and(SERVICE_EXPOSE_MAP.UPGRADE.eq(false)) .and(SERVICE_EXPOSE_MAP.STATE.notIn(CommonStatesConstants.REQUESTED, CommonStatesConstants.REMOVED, CommonStatesConstants.REMOVING))) .fetchInto(ServiceExposeMapRecord.class); } @Override public List<? extends Instance> getInstancesToUpgrade(Service service, String launchConfigName, String toVersion) { Condition condition = null; if (launchConfigName == null || launchConfigName.equals(service.getName()) || launchConfigName.equals(ServiceConstants.PRIMARY_LAUNCH_CONFIG_NAME)) { condition = SERVICE_EXPOSE_MAP.DNS_PREFIX.isNull(); } else { condition = SERVICE_EXPOSE_MAP.DNS_PREFIX.eq(launchConfigName); } // add all managed return create() .select(INSTANCE.fields()) .from(INSTANCE) .join(SERVICE_EXPOSE_MAP) .on(SERVICE_EXPOSE_MAP.INSTANCE_ID.eq(INSTANCE.ID) .and(SERVICE_EXPOSE_MAP.SERVICE_ID.eq(service.getId())) .and(SERVICE_EXPOSE_MAP.MANAGED.eq(true)) .and(SERVICE_EXPOSE_MAP.STATE.in(CommonStatesConstants.ACTIVATING, CommonStatesConstants.ACTIVE, CommonStatesConstants.REQUESTED)) .and(INSTANCE.STATE.notIn(CommonStatesConstants.PURGING, CommonStatesConstants.PURGED, CommonStatesConstants.REMOVED, CommonStatesConstants.REMOVING)).and(condition) .and(INSTANCE.VERSION.ne(toVersion))) .fetchInto(InstanceRecord.class); } @Override public List<? extends Instance> getUpgradedInstances(Service service, String launchConfigName, String toVersion, boolean managed) { Condition condition1 = null; if (launchConfigName == null || launchConfigName.equals(service.getName()) || launchConfigName.equals(ServiceConstants.PRIMARY_LAUNCH_CONFIG_NAME)) { condition1 = SERVICE_EXPOSE_MAP.DNS_PREFIX.isNull(); } else { condition1 = SERVICE_EXPOSE_MAP.DNS_PREFIX.eq(launchConfigName); } Condition condition2 = null; if (managed) { condition2 = SERVICE_EXPOSE_MAP.MANAGED.eq(true); } else { condition2 = SERVICE_EXPOSE_MAP.MANAGED.eq(false).and(SERVICE_EXPOSE_MAP.UPGRADE.eq(true)); } return create() .select(INSTANCE.fields()) .from(INSTANCE) .join(SERVICE_EXPOSE_MAP) .on(SERVICE_EXPOSE_MAP.INSTANCE_ID.eq(INSTANCE.ID) .and(SERVICE_EXPOSE_MAP.SERVICE_ID.eq(service.getId())) .and(SERVICE_EXPOSE_MAP.STATE.in(CommonStatesConstants.ACTIVATING, CommonStatesConstants.ACTIVE, CommonStatesConstants.REQUESTED)) .and(INSTANCE.STATE.notIn(CommonStatesConstants.PURGING, CommonStatesConstants.PURGED, CommonStatesConstants.REMOVED, CommonStatesConstants.REMOVING)).and(condition1) .and(condition2) .and(INSTANCE.VERSION.eq(toVersion))) .fetchInto(InstanceRecord.class); } @Override public List<? extends Instance> getInstancesToCleanup(Service service, String launchConfigName, String toVersion) { Condition condition = null; if (launchConfigName == null || launchConfigName.equals(service.getName()) || launchConfigName.equals(ServiceConstants.PRIMARY_LAUNCH_CONFIG_NAME)) { condition = SERVICE_EXPOSE_MAP.DNS_PREFIX.isNull(); } else { condition = SERVICE_EXPOSE_MAP.DNS_PREFIX.eq(launchConfigName); } // add unmanaged and marked for upgrade return create() .select(INSTANCE.fields()) .from(INSTANCE) .join(SERVICE_EXPOSE_MAP) .on(SERVICE_EXPOSE_MAP.INSTANCE_ID.eq(INSTANCE.ID) .and(SERVICE_EXPOSE_MAP.SERVICE_ID.eq(service.getId())) .and(SERVICE_EXPOSE_MAP.MANAGED.eq(false)) .and(SERVICE_EXPOSE_MAP.UPGRADE.eq(true)) .and(SERVICE_EXPOSE_MAP.STATE.in(CommonStatesConstants.ACTIVATING, CommonStatesConstants.ACTIVE, CommonStatesConstants.REQUESTED)) .and(INSTANCE.STATE.notIn(CommonStatesConstants.PURGING, CommonStatesConstants.PURGED, CommonStatesConstants.REMOVED, CommonStatesConstants.REMOVING)).and(condition) .and(INSTANCE.VERSION.ne(toVersion))) .fetchInto(InstanceRecord.class); } @Override public List<? extends ServiceExposeMap> getInstancesSetForUpgrade(long serviceId) { return create() .select(SERVICE_EXPOSE_MAP.fields()) .from(SERVICE_EXPOSE_MAP) .where(SERVICE_EXPOSE_MAP.SERVICE_ID.eq(serviceId)) .and(SERVICE_EXPOSE_MAP.MANAGED.eq(false)) .and(SERVICE_EXPOSE_MAP.UPGRADE.eq(true)) .and(SERVICE_EXPOSE_MAP.STATE.in(CommonStatesConstants.ACTIVATING, CommonStatesConstants.ACTIVE, CommonStatesConstants.REQUESTED)) .fetchInto(ServiceExposeMapRecord.class); } }