Search in sources :

Example 16 with ProductContent

use of org.candlepin.model.ProductContent in project candlepin by candlepin.

the class ContentManager method importContent.

/**
 * Creates or updates content from the given content DTOs, omitting product updates for the
 * provided Red Hat product IDs.
 * <p></p>
 * The content DTOs provided in the given map should be mapped by the content's Red Hat ID. If
 * the mappings are incorrect or inconsistent, the result of this method is undefined.
 *
 * @param owner
 *  The owner for which to import the given content
 *
 * @param contentData
 *  A mapping of Red Hat content ID to content DTOs to import
 *
 * @param importedProductIds
 *  A set of Red Hat product IDs specifying products which are being imported and should not be
 *  updated as part of this import operation
 *
 * @return
 *  A mapping of Red Hat content ID to content entities representing the imported content
 */
@SuppressWarnings("checkstyle:methodlength")
@Transactional
@Traceable
public ImportResult<Content> importContent(@TraceableParam("owner") Owner owner, Map<String, ContentData> contentData, Set<String> importedProductIds) {
    if (owner == null) {
        throw new IllegalArgumentException("owner is null");
    }
    ImportResult<Content> importResult = new ImportResult<>();
    if (contentData == null || contentData.isEmpty()) {
        // Nothing to import
        return importResult;
    }
    Map<String, Content> skippedContent = importResult.getSkippedEntities();
    Map<String, Content> createdContent = importResult.getCreatedEntities();
    Map<String, Content> updatedContent = importResult.getUpdatedEntities();
    Map<String, Integer> contentVersions = new HashMap<>();
    Map<String, Content> sourceContent = new HashMap<>();
    Map<String, List<Content>> existingVersions = new HashMap<>();
    List<OwnerContent> ownerContentBuffer = new LinkedList<>();
    // - Divide imported products into sets of updates and creates
    log.debug("Fetching existing content for update...");
    for (Content content : this.ownerContentCurator.getContentByIds(owner, contentData.keySet())) {
        ContentData update = contentData.get(content.getId());
        if (!this.isChangedBy(content, update)) {
            // This content won't be changing, so we'll just pretend it's not being imported at all
            skippedContent.put(content.getId(), content);
            continue;
        }
        // Content is coming from an upstream source; lock it so only upstream can make
        // further changes to it. If we ever use this method for anything other than
        // imports, we'll need to stop doing this.
        sourceContent.put(content.getId(), content);
        content = this.applyContentChanges((Content) content.clone(), update);
        updatedContent.put(content.getId(), content);
        contentVersions.put(content.getId(), content.getEntityVersion());
    }
    log.debug("Validating new content...");
    for (ContentData update : contentData.values()) {
        if (!skippedContent.containsKey(update.getId()) && !updatedContent.containsKey(update.getId())) {
            // Ensure content is minimally populated
            if (update.getId() == null || update.getType() == null || update.getLabel() == null || update.getName() == null || update.getVendor() == null) {
                throw new IllegalStateException("Content data is incomplete: " + update);
            }
            Content content = this.applyContentChanges(new Content(update.getId()), update);
            createdContent.put(content.getId(), content);
            contentVersions.put(content.getId(), content.getEntityVersion());
        }
    }
    log.debug("Checking for existing content versions...");
    for (Content alt : this.ownerContentCurator.getContentByVersions(owner, contentVersions)) {
        List<Content> alternates = existingVersions.get(alt.getId());
        if (alternates == null) {
            alternates = new LinkedList<>();
            existingVersions.put(alt.getId(), alternates);
        }
        alternates.add(alt);
    }
    contentVersions.clear();
    contentVersions = null;
    // We're about to start modifying the maps, so we need to clone the created set before we
    // start adding the update forks to it.
    Map<String, Content> stagedEntities = new HashMap<>(createdContent);
    // Process the created group...
    // Check our created set for existing versions:
    // - If there's an existing version, we'll remove the staged entity from the creation
    // set, and stage an owner-content mapping for the existing version
    // - Otherwise, we'll stage the new entity for persistence by leaving it in the created
    // set, and stage an owner-content mapping to the new entity
    Iterator<Content> iterator = stagedEntities.values().iterator();
    createdContentLoop: while (iterator.hasNext()) {
        Content created = iterator.next();
        List<Content> alternates = existingVersions.get(created.getId());
        if (alternates != null) {
            for (Content alt : alternates) {
                if (created.equals(alt)) {
                    ownerContentBuffer.add(new OwnerContent(owner, alt));
                    createdContent.put(alt.getId(), alt);
                    iterator.remove();
                    continue createdContentLoop;
                }
            }
        }
        ownerContentBuffer.add(new OwnerContent(owner, created));
    }
    // - Otherwise, we need to stage the updated entity for persistence
    updatedContentLoop: for (Map.Entry<String, Content> entry : updatedContent.entrySet()) {
        Content updated = entry.getValue();
        List<Content> alternates = existingVersions.get(updated.getId());
        if (alternates != null) {
            for (Content alt : alternates) {
                if (!updated.getUuid().equals(alt.getUuid()) && updated.equals(alt)) {
                    updated = alt;
                    entry.setValue(alt);
                    continue updatedContentLoop;
                }
            }
        }
        // We need to stage the updated entity for persistence. We'll reuse the now-empty
        // createdContent map for this.
        updated.setUuid(null);
        stagedEntities.put(updated.getId(), updated);
    }
    // Persist our staged entities
    // We probably don't want to evict the content yet, as they'll appear as unmanaged if
    // they're used later. However, the join objects can be evicted safely since they're only
    // really used here.
    log.debug("Persisting content changes...");
    this.contentCurator.saveAll(stagedEntities.values(), true, false);
    this.ownerContentCurator.saveAll(ownerContentBuffer, true, true);
    // Fetch collection of products affected by this import that aren't being imported themselves
    log.debug("Updating non-imported, affected products...");
    List<Product> affectedProducts = this.productCurator.getProductsByContent(owner, sourceContent.keySet(), importedProductIds).list();
    if (affectedProducts != null && !affectedProducts.isEmpty()) {
        // Get the collection of content those products use
        Map<String, Content> affectedProductsContent = new HashMap<>();
        for (Content content : this.contentCurator.getContentByProducts(affectedProducts)) {
            affectedProductsContent.put(content.getId(), content);
        }
        // Update the content map so it references the updated content
        affectedProductsContent.putAll(updatedContent);
        Map<String, ProductData> affectedProductData = new HashMap<>();
        Map<String, ContentData> contentDTOCache = new HashMap<>();
        for (Product product : affectedProducts) {
            ProductData pdto = product.toDTO();
            for (ProductContent pcdata : product.getProductContent()) {
                Content content = pcdata.getContent();
                Content updated = updatedContent.get(content.getId());
                if (updated != null) {
                    ContentData cdto = contentDTOCache.get(content.getId());
                    if (cdto == null) {
                        cdto = content.toDTO();
                        contentDTOCache.put(cdto.getId(), cdto);
                    }
                    pdto.addContent(cdto, pcdata.isEnabled());
                }
            }
            affectedProductData.put(pdto.getId(), pdto);
        }
        // Perform a micro-import for these products using the content map we just built
        this.productManager.importProducts(owner, affectedProductData, affectedProductsContent);
    }
    // Perform bulk reference update
    Map<String, String> contentUuidMap = new HashMap<>();
    for (Content update : updatedContent.values()) {
        Content source = sourceContent.get(update.getId());
        contentUuidMap.put(source.getUuid(), update.getUuid());
    }
    this.ownerContentCurator.updateOwnerContentReferences(owner, contentUuidMap);
    // Return
    return importResult;
}
Also used : OwnerContent(org.candlepin.model.OwnerContent) HashMap(java.util.HashMap) Product(org.candlepin.model.Product) ContentData(org.candlepin.model.dto.ContentData) ProductContentData(org.candlepin.model.dto.ProductContentData) LinkedList(java.util.LinkedList) List(java.util.List) ProductData(org.candlepin.model.dto.ProductData) LinkedList(java.util.LinkedList) ProductContent(org.candlepin.model.ProductContent) ProductContent(org.candlepin.model.ProductContent) Content(org.candlepin.model.Content) OwnerContent(org.candlepin.model.OwnerContent) Traceable(org.candlepin.util.Traceable) Transactional(com.google.inject.persist.Transactional)

Example 17 with ProductContent

use of org.candlepin.model.ProductContent in project candlepin by candlepin.

the class X509Util method filterContentByContentArch.

/*
     * remove content sets that do not match the consumers arch
     */
public Set<ProductContent> filterContentByContentArch(Set<ProductContent> pcSet, Consumer consumer, Product product) {
    Set<ProductContent> filtered = new HashSet<>();
    String consumerArch = consumer.getFact(ARCH_FACT);
    if (consumerArch == null) {
        log.debug("consumer: " + consumer.getId() + " has no " + ARCH_FACT + " attribute.");
        log.debug("Not filtering by arch");
        return pcSet;
    }
    for (ProductContent pc : pcSet) {
        boolean canUse = true;
        Set<String> contentArches = Arch.parseArches(pc.getContent().getArches());
        Set<String> productArches = Arch.parseArches(product.getAttributeValue(Product.Attributes.ARCHITECTURE));
        // inheriting the arches from the product
        if (contentArches.isEmpty()) {
            // and if so inherit it.
            if (!productArches.isEmpty()) {
                contentArches.addAll(productArches);
            } else {
                // No Product arches either, log it, but do
                // not filter out this content
                log.debug("No arch attributes found for content or product");
            }
        }
        for (String contentArch : contentArches) {
            if (Arch.contentForConsumer(contentArch, consumerArch)) {
                canUse = true;
                break;
            } else {
                canUse = false;
            }
        }
        // Content or on Product)
        if (canUse) {
            filtered.add(pc);
        }
    }
    return filtered;
}
Also used : ProductContent(org.candlepin.model.ProductContent) HashSet(java.util.HashSet)

Example 18 with ProductContent

use of org.candlepin.model.ProductContent in project candlepin by candlepin.

the class ProductTranslatorTest method verifyOutput.

@Override
protected void verifyOutput(Product source, ProductDTO dto, boolean childrenGenerated) {
    if (source != null) {
        assertEquals(source.getUuid(), dto.getUuid());
        assertEquals(source.getId(), dto.getId());
        assertEquals(source.getName(), dto.getName());
        assertEquals(source.getMultiplier(), dto.getMultiplier());
        assertEquals(source.getAttributes(), dto.getAttributes());
        assertEquals(source.getDependentProductIds(), dto.getDependentProductIds());
        assertEquals(source.isLocked(), dto.isLocked());
        assertEquals(source.getHref(), dto.getHref());
        assertNotNull(dto.getProductContent());
        if (childrenGenerated) {
            for (ProductContent pc : source.getProductContent()) {
                for (ProductContentDTO pcdto : dto.getProductContent()) {
                    Content content = pc.getContent();
                    ContentDTO cdto = pcdto.getContent();
                    assertNotNull(cdto);
                    assertNotNull(cdto.getUuid());
                    if (cdto.getUuid().equals(content.getUuid())) {
                        assertEquals(pc.isEnabled(), pcdto.isEnabled());
                        // Pass the content off to the ContentTranslatorTest to verify it
                        this.contentTranslatorTest.verifyOutput(content, cdto, childrenGenerated);
                    }
                }
            }
        } else {
            assertTrue(dto.getProductContent().isEmpty());
        }
    } else {
        assertNull(dto);
    }
}
Also used : ProductContentDTO(org.candlepin.dto.api.v1.ProductDTO.ProductContentDTO) ProductContent(org.candlepin.model.ProductContent) Content(org.candlepin.model.Content) ProductContentDTO(org.candlepin.dto.api.v1.ProductDTO.ProductContentDTO) ProductContent(org.candlepin.model.ProductContent)

Example 19 with ProductContent

use of org.candlepin.model.ProductContent in project candlepin by candlepin.

the class ProductManagerTest method testUpdateProductContentOnSharedProduct.

// Move this to ContentManagerTest
@Test
public void testUpdateProductContentOnSharedProduct() {
    Owner owner1 = this.createOwner("test-owner-1", "Test Owner 1");
    Owner owner2 = this.createOwner("test-owner-2", "Test Owner 2");
    Product product = this.createProduct("p1", "prod1", owner1);
    Content content = this.createContent("c1", "content1", owner1);
    this.ownerProductCurator.mapProductToOwners(product, owner1, owner2);
    product.setProductContent(Arrays.asList(new ProductContent(product, content, true)));
    this.productCurator.merge(product);
    ProductDTO pdto = this.modelTranslator.translate(product, ProductDTO.class);
    pdto.getProductContent(content.getId()).setEnabled(false);
    Product output = this.productManager.updateProduct(pdto, owner1, false);
    assertNotEquals(product, output);
    assertTrue(product.hasContent(content.getId()));
    assertTrue(output.hasContent(content.getId()));
    assertTrue(product.getProductContent().iterator().next().isEnabled());
    assertFalse(output.getProductContent().iterator().next().isEnabled());
    assertFalse(this.ownerProductCurator.isProductMappedToOwner(product, owner1));
    assertTrue(this.ownerProductCurator.isProductMappedToOwner(product, owner2));
    assertTrue(this.ownerProductCurator.isProductMappedToOwner(output, owner1));
    assertFalse(this.ownerProductCurator.isProductMappedToOwner(output, owner2));
    verifyZeroInteractions(this.mockEntCertGenerator);
}
Also used : Owner(org.candlepin.model.Owner) ProductContent(org.candlepin.model.ProductContent) Content(org.candlepin.model.Content) Product(org.candlepin.model.Product) ProductContent(org.candlepin.model.ProductContent) ProductDTO(org.candlepin.dto.api.v1.ProductDTO) Test(org.junit.Test)

Example 20 with ProductContent

use of org.candlepin.model.ProductContent in project candlepin by candlepin.

the class X509ExtensionUtil method contentExtensions.

public Set<X509ExtensionWrapper> contentExtensions(Collection<ProductContent> productContentList, String contentPrefix, Map<String, EnvironmentContent> promotedContent, Consumer consumer, Product skuProduct) {
    Set<ProductContent> productContent = new HashSet<>(productContentList);
    Set<X509ExtensionWrapper> toReturn = new LinkedHashSet<>();
    boolean enableEnvironmentFiltering = config.getBoolean(ConfigProperties.ENV_CONTENT_FILTERING);
    List<String> skuDisabled = skuProduct.getSkuDisabledContentIds();
    List<String> skuEnabled = skuProduct.getSkuEnabledContentIds();
    // informative error message to the user.
    for (ProductContent pc : productContent) {
        // augment the content path with the prefix if it is passed in
        String contentPath = this.createFullContentPath(contentPrefix, pc);
        // skip it. see rhbz#997970
        if (!OIDUtil.CF_REPO_TYPE.containsKey(pc.getContent().getType())) {
            log.warn("No content type OID found for {} with content type: {}", pc.getContent(), pc.getContent().getType());
            continue;
        }
        String contentOid = OIDUtil.REDHAT_OID + "." + OIDUtil.TOPLEVEL_NAMESPACES.get(OIDUtil.CHANNEL_FAMILY_NAMESPACE_KEY) + "." + pc.getContent().getId().toString() + "." + OIDUtil.CF_REPO_TYPE.get(pc.getContent().getType());
        toReturn.add(new X509ExtensionWrapper(contentOid, false, pc.getContent().getType()));
        toReturn.add(new X509ExtensionWrapper(contentOid + "." + OIDUtil.CHANNEL_FAMILY_OIDS.get(OIDUtil.CF_NAME_KEY), false, pc.getContent().getName()));
        toReturn.add(new X509ExtensionWrapper(contentOid + "." + OIDUtil.CHANNEL_FAMILY_OIDS.get(OIDUtil.CF_LABEL_KEY), false, pc.getContent().getLabel()));
        toReturn.add(new X509ExtensionWrapper(contentOid + "." + OIDUtil.CHANNEL_FAMILY_OIDS.get(OIDUtil.CF_VENDOR_ID_KEY), false, pc.getContent().getVendor()));
        toReturn.add(new X509ExtensionWrapper(contentOid + "." + OIDUtil.CHANNEL_FAMILY_OIDS.get(OIDUtil.CF_DOWNLOAD_URL_KEY), false, contentPath));
        toReturn.add(new X509ExtensionWrapper(contentOid + "." + OIDUtil.CHANNEL_FAMILY_OIDS.get(OIDUtil.CF_GPG_URL_KEY), false, pc.getContent().getGpgUrl()));
        Boolean enabled = pc.isEnabled();
        log.debug("default enabled flag = " + enabled);
        // sku level content enable override. if on both lists, active wins.
        if (skuDisabled.contains(pc.getContent().getId())) {
            enabled = false;
        }
        if (skuEnabled.contains(pc.getContent().getId())) {
            enabled = true;
        }
        // content:
        if (enableEnvironmentFiltering && consumer.getEnvironmentId() != null) {
            // we know content has been promoted at this point:
            Boolean enabledOverride = promotedContent.get(pc.getContent().getId()).getEnabled();
            if (enabledOverride != null) {
                log.debug("overriding enabled flag: {}", enabledOverride);
                enabled = enabledOverride;
            }
        }
        toReturn.add(new X509ExtensionWrapper(contentOid + "." + OIDUtil.CHANNEL_FAMILY_OIDS.get(OIDUtil.CF_ENABLED), false, (enabled) ? "1" : "0"));
        // Include metadata expiry if specified on the content:
        if (pc.getContent().getMetadataExpire() != null) {
            toReturn.add(new X509ExtensionWrapper(contentOid + "." + OIDUtil.CHANNEL_FAMILY_OIDS.get(OIDUtil.CF_METADATA_EXPIRE), false, pc.getContent().getMetadataExpire().toString()));
        }
        // Include required tags if specified on the content set:
        String requiredTags = pc.getContent().getRequiredTags();
        if ((requiredTags != null) && !requiredTags.equals("")) {
            toReturn.add(new X509ExtensionWrapper(contentOid + "." + OIDUtil.CHANNEL_FAMILY_OIDS.get(OIDUtil.CF_REQUIRED_TAGS), false, requiredTags));
        }
    }
    return toReturn;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) X509ExtensionWrapper(org.candlepin.pki.X509ExtensionWrapper) ProductContent(org.candlepin.model.ProductContent) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Aggregations

ProductContent (org.candlepin.model.ProductContent)30 Content (org.candlepin.model.Content)20 Test (org.junit.Test)11 Product (org.candlepin.model.Product)9 HashSet (java.util.HashSet)7 HashMap (java.util.HashMap)5 LinkedList (java.util.LinkedList)5 ContentDTO (org.candlepin.dto.api.v1.ContentDTO)4 ProductContentDTO (org.candlepin.dto.api.v1.ProductDTO.ProductContentDTO)4 Owner (org.candlepin.model.Owner)4 X509ExtensionWrapper (org.candlepin.pki.X509ExtensionWrapper)4 Transactional (com.google.inject.persist.Transactional)3 ArrayList (java.util.ArrayList)3 LinkedHashSet (java.util.LinkedHashSet)3 List (java.util.List)3 ProductDTO (org.candlepin.dto.api.v1.ProductDTO)3 ContentData (org.candlepin.model.dto.ContentData)3 ProductContentData (org.candlepin.model.dto.ProductContentData)3 CertificateSizeException (org.candlepin.util.CertificateSizeException)3 IOException (java.io.IOException)2