Skip to content

Commit

Permalink
Merge branch 'develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
elevatebart authored Dec 2, 2024
2 parents cba00e9 + a5741aa commit 37a210e
Show file tree
Hide file tree
Showing 201 changed files with 5,243 additions and 556 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/generate_translations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 50
ref: ${{ github.head_ref }}
ref: ${{ github.sha }}

- name: Set up Python
uses: actions/setup-python@v5
Expand Down
47 changes: 40 additions & 7 deletions core/src/main/java/io/kestra/core/docs/JsonSchemaGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@
import com.github.victools.jsonschema.module.jakarta.validation.JakartaValidationOption;
import com.github.victools.jsonschema.module.swagger2.Swagger2Module;
import com.google.common.collect.ImmutableMap;
import io.kestra.core.models.property.Data;
import io.kestra.core.models.property.Property;
import io.kestra.core.models.annotations.Plugin;
import io.kestra.core.models.annotations.PluginProperty;
import io.kestra.core.models.conditions.Condition;
import io.kestra.core.models.conditions.ScheduleCondition;
import io.kestra.core.models.dashboards.DataFilter;
import io.kestra.core.models.dashboards.charts.Chart;
import io.kestra.core.models.dashboards.charts.DataChart;
import io.kestra.core.models.property.Data;
import io.kestra.core.models.property.Property;
import io.kestra.core.models.tasks.Output;
import io.kestra.core.models.tasks.Task;
import io.kestra.core.models.tasks.common.EncryptedString;
Expand All @@ -31,14 +34,12 @@
import io.kestra.core.plugins.RegisteredPlugin;
import io.kestra.core.serializers.JacksonMapper;
import io.micronaut.core.annotation.Nullable;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.*;
import java.time.Duration;
import java.time.LocalTime;
import java.util.*;
Expand Down Expand Up @@ -334,11 +335,20 @@ public CustomDefinition provideCustomSchemaDefinition(ResolvedType javaType, Sch
}
});

// PluginProperty additionalProperties
builder.forFields().withAdditionalPropertiesResolver(target -> {
PluginProperty pluginPropertyAnnotation = target.getAnnotationConsideringFieldAndGetter(PluginProperty.class);
Schema schemaAnnotation = target.getAnnotationConsideringFieldAndGetter(Schema.class);
Content contentAnnotation = target.getAnnotationConsideringFieldAndGetter(Content.class);
Schema contentSchemaAnnotation = contentAnnotation == null ? null : contentAnnotation.additionalPropertiesSchema();

if (pluginPropertyAnnotation != null) {
return pluginPropertyAnnotation.additionalProperties();
} else if (target.getType().isInstanceOf(Map.class)) {
return target.getTypeParameterFor(Map.class, 1);
} else if (schemaAnnotation != null && schemaAnnotation.additionalPropertiesSchema() != Void.class) {
return schemaAnnotation.additionalPropertiesSchema();
} else if (contentSchemaAnnotation != null && contentSchemaAnnotation.additionalPropertiesSchema() != Void.class) {
return contentSchemaAnnotation.additionalPropertiesSchema();
}

return Object.class;
Expand Down Expand Up @@ -472,6 +482,29 @@ protected List<ResolvedType> subtypeResolver(ResolvedType declaredType, TypeCont
.filter(Predicate.not(io.kestra.core.models.Plugin::isInternal))
.flatMap(clz -> safelyResolveSubtype(declaredType, clz, typeContext).stream())
.toList();
} else if (declaredType.getErasedType() == Chart.class) {
return getRegisteredPlugins()
.stream()
.flatMap(registeredPlugin -> registeredPlugin.getCharts().stream())
.filter(Predicate.not(io.kestra.core.models.Plugin::isInternal))
.<ResolvedType>mapMulti((clz, consumer) -> {
if (DataChart.class.isAssignableFrom(clz)) {
List<Class<? extends DataFilter<?, ?>>> dataFilters = getRegisteredPlugins()
.stream()
.flatMap(registeredPlugin -> registeredPlugin.getDataFilters().stream())
.filter(Predicate.not(io.kestra.core.models.Plugin::isInternal))
.toList();

TypeVariable<? extends Class<? extends Chart<?>>> dataFilterType = clz.getTypeParameters()[1];
ParameterizedType chartAwareColumnDescriptor = ((ParameterizedType) ((WildcardType) ((ParameterizedType) dataFilterType.getBounds()[0]).getActualTypeArguments()[1]).getUpperBounds()[0]);
dataFilters.forEach(dataFilter -> {
Type fieldsEnum = ((ParameterizedType) dataFilter.getGenericSuperclass()).getActualTypeArguments()[0];
consumer.accept(typeContext.resolve(clz, fieldsEnum, typeContext.resolve(dataFilter, typeContext.resolve(chartAwareColumnDescriptor, fieldsEnum))));
});
} else {
consumer.accept(typeContext.resolve(clz));
}
}).toList();
}

return null;
Expand Down
5 changes: 4 additions & 1 deletion core/src/main/java/io/kestra/core/docs/Plugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public class Plugin {
private List<String> taskRunners;
private List<String> guides;
private List<String> aliases;
private List<String> apps;
private List<String> appBlocks;
private List<PluginSubGroup.PluginCategory> categories;
private String subGroup;

Expand Down Expand Up @@ -81,7 +83,8 @@ public static Plugin of(RegisteredPlugin registeredPlugin, @Nullable String subg
plugin.storages = filterAndGetClassName(registeredPlugin.getStorages()).stream().filter(c -> subgroup == null || c.startsWith(subgroup)).toList();
plugin.secrets = filterAndGetClassName(registeredPlugin.getSecrets()).stream().filter(c -> subgroup == null || c.startsWith(subgroup)).toList();
plugin.taskRunners = filterAndGetClassName(registeredPlugin.getTaskRunners()).stream().filter(c -> subgroup == null || c.startsWith(subgroup)).toList();

plugin.apps = filterAndGetClassName(registeredPlugin.getApps()).stream().filter(c -> subgroup == null || c.startsWith(subgroup)).toList();
plugin.appBlocks = filterAndGetClassName(registeredPlugin.getAppBlocks()).stream().filter(c -> subgroup == null || c.startsWith(subgroup)).toList();

return plugin;
}
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/java/io/kestra/core/docs/SchemaType.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ public enum SchemaType {
task,
trigger,
plugindefault,
apps
apps,
dashboard
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.kestra.core.models.dashboards;

public enum AggregationType {
AVG,
MAX,
MIN,
SUM,
COUNT
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.kestra.core.models.dashboards;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

import java.util.Collections;
import java.util.List;

@SuperBuilder(toBuilder = true)
@Getter
@NoArgsConstructor
@EqualsAndHashCode
public class ChartOption {
@NotNull
@NotBlank
private String displayName;

private String description;

public List<String> neededColumns() {
return Collections.emptyList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.kestra.core.models.dashboards;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

@SuperBuilder(toBuilder = true)
@Getter
@NoArgsConstructor
@EqualsAndHashCode
public class ColumnDescriptor<F extends Enum<F>> {
private F field;
private String displayName;
private AggregationType agg;
private String labelKey;
}
90 changes: 90 additions & 0 deletions core/src/main/java/io/kestra/core/models/dashboards/Dashboard.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package io.kestra.core.models.dashboards;

import com.fasterxml.jackson.annotation.JsonIgnore;
import io.kestra.core.models.DeletedInterface;
import io.kestra.core.models.HasUID;
import io.kestra.core.models.dashboards.charts.Chart;
import io.kestra.core.utils.IdUtils;
import io.micronaut.core.annotation.Introspected;
import io.swagger.v3.oas.annotations.Hidden;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.SuperBuilder;

import java.time.Instant;
import java.util.List;
import java.util.Objects;

@SuperBuilder(toBuilder = true)
@Getter
@NoArgsConstructor
@Introspected
@ToString
public class Dashboard implements HasUID, DeletedInterface {
@Hidden
@Pattern(regexp = "^[a-z0-9][a-z0-9_-]*")
private String tenantId;

@Hidden
private String id;

@NotNull
@NotBlank
private String title;

private String description;

@Valid
@Builder.Default
private TimeWindow timeWindow = TimeWindow.builder().build();

@Valid
private List<Chart<?>> charts;

@Hidden
@NotNull
@Builder.Default
private boolean deleted = false;

@Hidden
private Instant created;

@Hidden
private Instant updated;

private String sourceCode;

@Override
@JsonIgnore
public String uid() {
return IdUtils.fromParts(
tenantId,
id
);
}

public Dashboard toDeleted() {
return this.toBuilder()
.deleted(true)
.build();
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Dashboard dashboard = (Dashboard) o;
return deleted == dashboard.deleted && Objects.equals(tenantId, dashboard.tenantId) && Objects.equals(id, dashboard.id) && Objects.equals(title, dashboard.title) && Objects.equals(description, dashboard.description) && Objects.equals(timeWindow, dashboard.timeWindow) && Objects.equals(charts, dashboard.charts) && Objects.equals(sourceCode, dashboard.sourceCode);
}

@Override
public int hashCode() {
return Objects.hash(tenantId, id, title, description, timeWindow, charts, deleted, sourceCode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package io.kestra.core.models.dashboards;

import io.kestra.core.models.annotations.Plugin;
import io.kestra.core.models.dashboards.filters.AbstractFilter;
import io.kestra.core.repositories.QueryBuilderInterface;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

@SuperBuilder(toBuilder = true)
@Getter
@NoArgsConstructor
@Plugin
@EqualsAndHashCode
public abstract class DataFilter<F extends Enum<F>, C extends ColumnDescriptor<F>> implements io.kestra.core.models.Plugin {
@NotNull
@NotBlank
@Pattern(regexp = "\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*(\\.\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*)*")
private String type;

private Map<String, C> columns;

private List<AbstractFilter<F>> where;

private List<OrderBy> orderBy;

public Set<F> aggregationForbiddenFields() {
return Collections.emptySet();
}

public abstract Class<? extends QueryBuilderInterface<F>> repositoryClass();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.kestra.core.models.dashboards;

public enum GraphStyle {
LINES,
BARS,
POINTS
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.kestra.core.models.dashboards;

public enum Order {
ASC,
DESC
}
22 changes: 22 additions & 0 deletions core/src/main/java/io/kestra/core/models/dashboards/OrderBy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.kestra.core.models.dashboards;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

@SuperBuilder(toBuilder = true)
@Getter
@NoArgsConstructor
@EqualsAndHashCode
public class OrderBy {
@NotNull
@NotBlank
private String column;

@Builder.Default
private Order order = Order.ASC;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.kestra.core.models.dashboards;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.kestra.core.validations.DashboardWindowValidation;
import io.micronaut.core.annotation.Introspected;
import lombok.*;
import lombok.experimental.SuperBuilder;
import org.hibernate.validator.constraints.time.DurationMax;

import java.time.Duration;

@SuperBuilder(toBuilder = true)
@Getter
@NoArgsConstructor
@Introspected
@ToString
@EqualsAndHashCode
@DashboardWindowValidation
public class TimeWindow {
@DurationMax(days = 366L, message = "Time window can't be more than 1 year (366 days).")
@JsonProperty("default")
@Builder.Default
private Duration defaultDuration = Duration.ofDays(30);

@DurationMax(days = 366L, message = "Time window can't be more than 1 year (366 days).")
@Builder.Default
private Duration max = Duration.ofDays(366);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.kestra.core.models.dashboards;

import io.kestra.core.models.dashboards.charts.LegendOption;

public interface WithLegend {
LegendOption getLegend();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.kestra.core.models.dashboards;

import io.kestra.core.models.dashboards.charts.TooltipBehaviour;

public interface WithTooltip {
TooltipBehaviour getTooltip();
}
Loading

0 comments on commit 37a210e

Please sign in to comment.