All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ca.ibodrov.mica.server.api.EntityUploadResource Maven / Gradle / Ivy

There is a newer version: 0.0.25
Show newest version
package ca.ibodrov.mica.server.api;

import ca.ibodrov.mica.api.model.EntityVersion;
import ca.ibodrov.mica.api.model.PartialEntity;
import ca.ibodrov.mica.server.YamlMapper;
import ca.ibodrov.mica.server.data.EntityController;
import ca.ibodrov.mica.server.exceptions.ApiException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.walmartlabs.concord.server.sdk.rest.Resource;
import com.walmartlabs.concord.server.security.UserPrincipal;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;

import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import static java.util.Objects.requireNonNull;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;

@Tag(name = "Entity Upload")
@Path("/api/mica/v1/upload")
@Produces(APPLICATION_JSON)
public class EntityUploadResource implements Resource {

    private final EntityController controller;
    private final Validator validator;
    private final YamlMapper yamlMapper;

    @Inject
    public EntityUploadResource(EntityController controller,
                                Validator validator,
                                ObjectMapper objectMapper) {

        this.controller = requireNonNull(controller);
        this.validator = requireNonNull(validator);
        this.yamlMapper = new YamlMapper(objectMapper);
    }

    @PUT
    @Path("yaml")
    @Consumes("*/yaml")
    @Operation(summary = "Upload an entity in YAML format", operationId = "putYaml")
    public EntityVersion putYaml(@Context UserPrincipal session,
                                 InputStream in,
                                 @QueryParam("overwrite") @DefaultValue("false") boolean overwrite) {

        // assume the name is present in the document
        return putPartialYaml(session, null, null, false, overwrite, in);
    }

    @PUT
    @Path("partialYaml")
    @Consumes("*/yaml")
    @Operation(summary = "Upload a partial entity in YAML format", description = "Upload a (possibly) partial entity in YAML format with 'name' or 'kind' overrides", operationId = "putPartialYaml")
    public EntityVersion putPartialYaml(@Context UserPrincipal session,
                                        @Nullable @QueryParam("entityName") String entityName,
                                        @Nullable @QueryParam("entityKind") String entityKind,
                                        @Parameter(description = "Replace any entity with the same name") @QueryParam("replace") @DefaultValue("false") boolean replace,
                                        @Parameter(description = "Overwrite any other changes to the entity") @QueryParam("overwrite") @DefaultValue("false") boolean overwrite,
                                        InputStream in) {
        byte[] doc;
        try {
            doc = in.readAllBytes();
        } catch (IOException e) {
            throw ApiException.badRequest("Error reading the input: " + e.getMessage());
        }

        // TODO validate entityName
        PartialEntity entity;
        try {
            var object = yamlMapper.readValue(new ByteArrayInputStream(doc), ObjectNode.class);
            if (entityName != null && !entityName.isBlank()) {
                object = object.put("name", entityName);
            }
            if (entityKind != null && !entityKind.isBlank()) {
                object = object.put("kind", entityKind);
            }
            entity = yamlMapper.convertValue(object, PartialEntity.class);
        } catch (IOException e) {
            throw ApiException.badRequest("Error parsing YAML: " + e.getMessage());
        }

        var violations = validator.validate(entity);
        if (!violations.isEmpty()) {
            throw new ConstraintViolationException("Invalid entity", violations);
        }

        // TODO single transaction
        if (replace) {
            controller.deleteIfExists(session, entity.name());
        }
        return controller.createOrUpdate(session, entity, doc, overwrite);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy