Search in sources :

Example 6 with Restricted

use of org.kohsuke.accmod.Restricted in project configuration-as-code-plugin by jenkinsci.

the class BaseConfigurator method describe.

@NonNull
public Set<Attribute<T, ?>> describe() {
    Map<String, Attribute<T, ?>> attributes = new HashMap<>();
    final Set<String> exclusions = exclusions();
    for (Field field : getTarget().getFields()) {
        final String name = field.getName();
        if (exclusions.contains(name))
            continue;
        if (PersistedList.class.isAssignableFrom(field.getType())) {
            if (Modifier.isTransient(field.getModifiers())) {
                exclusions.add(name);
                continue;
            }
            Attribute attribute = createAttribute(name, TypePair.of(field)).getter(// get value by direct access to public final field
            field::get);
            attributes.put(name, attribute);
        }
    }
    final Class<T> target = getTarget();
    // TODO: Overloaded setters with different types can corrupt this logic
    for (Method method : target.getMethods()) {
        final String methodName = method.getName();
        TypePair type;
        if (method.getParameterCount() == 0 && methodName.startsWith("get") && PersistedList.class.isAssignableFrom(method.getReturnType())) {
            type = TypePair.ofReturnType(method);
        } else if (method.getParameterCount() != 1 || !methodName.startsWith("set")) {
            // Not an accessor, ignore
            continue;
        } else {
            type = TypePair.ofParameter(method, 0);
        }
        final String s = methodName.substring(3);
        final String name = StringUtils.uncapitalize(s);
        if (exclusions.contains(name))
            continue;
        if (!hasGetter(target, s)) {
            // Looks like a property but no actual getter method we can use to read value
            continue;
        }
        LOGGER.log(Level.FINER, "Processing {0} property", name);
        if (Map.class.isAssignableFrom(type.rawType)) {
            // yaml has support for Maps, but as nobody seem to like them we agreed not to support them
            LOGGER.log(Level.FINER, "{0} is a Map<?,?>. We decided not to support Maps.", name);
            continue;
        }
        Attribute attribute = createAttribute(name, type);
        if (attribute == null)
            continue;
        attribute.deprecated(method.getAnnotation(Deprecated.class) != null);
        final Restricted r = method.getAnnotation(Restricted.class);
        if (r != null)
            attribute.restrictions(r.value());
        Attribute prevAttribute = attributes.get(name);
        // Replace the method if it have more concretized type
        if (prevAttribute == null || prevAttribute.type.isAssignableFrom(attribute.type)) {
            attributes.put(name, attribute);
        }
    }
    return new HashSet<>(attributes.values());
}
Also used : DescribableAttribute(io.jenkins.plugins.casc.impl.attributes.DescribableAttribute) PersistedListAttribute(io.jenkins.plugins.casc.impl.attributes.PersistedListAttribute) DescribableListAttribute(io.jenkins.plugins.casc.impl.attributes.DescribableListAttribute) HashMap(java.util.HashMap) Restricted(org.kohsuke.accmod.Restricted) Method(java.lang.reflect.Method) Field(java.lang.reflect.Field) PersistedList(hudson.util.PersistedList) HashSet(java.util.HashSet) NonNull(edu.umd.cs.findbugs.annotations.NonNull)

Example 7 with Restricted

use of org.kohsuke.accmod.Restricted in project configuration-as-code-plugin by jenkinsci.

the class ConfigurationAsCode method toYaml.

@CheckForNull
// for testing only
@Restricted(NoExternalUse.class)
public Node toYaml(CNode config) throws ConfiguratorException {
    if (config == null)
        return null;
    switch(config.getType()) {
        case MAPPING:
            final Mapping mapping = config.asMapping();
            final List<NodeTuple> tuples = new ArrayList<>();
            final List<Map.Entry<String, CNode>> entries = new ArrayList<>(mapping.entrySet());
            entries.sort(Map.Entry.comparingByKey());
            for (Map.Entry<String, CNode> entry : entries) {
                final Node valueNode = toYaml(entry.getValue());
                if (valueNode == null)
                    continue;
                tuples.add(new NodeTuple(new ScalarNode(Tag.STR, entry.getKey(), null, null, PLAIN), valueNode));
            }
            if (tuples.isEmpty())
                return null;
            return new MappingNode(Tag.MAP, tuples, BLOCK);
        case SEQUENCE:
            final Sequence sequence = config.asSequence();
            List<Node> nodes = new ArrayList<>();
            for (CNode cNode : sequence) {
                final Node valueNode = toYaml(cNode);
                if (valueNode == null)
                    continue;
                nodes.add(valueNode);
            }
            if (nodes.isEmpty())
                return null;
            return new SequenceNode(Tag.SEQ, nodes, BLOCK);
        case SCALAR:
        default:
            final Scalar scalar = config.asScalar();
            final String value = scalar.getValue();
            if (value == null || value.length() == 0)
                return null;
            final DumperOptions.ScalarStyle style;
            if (scalar.getFormat().equals(Format.MULTILINESTRING) && !scalar.isRaw()) {
                style = LITERAL;
            } else if (scalar.isRaw()) {
                style = PLAIN;
            } else {
                style = DOUBLE_QUOTED;
            }
            return new ScalarNode(getTag(scalar.getFormat()), value, null, null, style);
    }
}
Also used : ScalarNode(org.yaml.snakeyaml.nodes.ScalarNode) SequenceNode(org.yaml.snakeyaml.nodes.SequenceNode) CNode(io.jenkins.plugins.casc.model.CNode) Node(org.yaml.snakeyaml.nodes.Node) MappingNode(org.yaml.snakeyaml.nodes.MappingNode) ScalarNode(org.yaml.snakeyaml.nodes.ScalarNode) ArrayList(java.util.ArrayList) Mapping(io.jenkins.plugins.casc.model.Mapping) Sequence(io.jenkins.plugins.casc.model.Sequence) SequenceNode(org.yaml.snakeyaml.nodes.SequenceNode) Scalar(io.jenkins.plugins.casc.model.Scalar) CNode(io.jenkins.plugins.casc.model.CNode) MappingNode(org.yaml.snakeyaml.nodes.MappingNode) DumperOptions(org.yaml.snakeyaml.DumperOptions) NodeTuple(org.yaml.snakeyaml.nodes.NodeTuple) Map(java.util.Map) HashMap(java.util.HashMap) Restricted(org.kohsuke.accmod.Restricted) CheckForNull(edu.umd.cs.findbugs.annotations.CheckForNull)

Example 8 with Restricted

use of org.kohsuke.accmod.Restricted in project configuration-as-code-plugin by jenkinsci.

the class ConfigurationAsCode method export.

@Restricted(NoExternalUse.class)
public void export(OutputStream out) throws Exception {
    final List<NodeTuple> tuples = new ArrayList<>();
    final ConfigurationContext context = new ConfigurationContext(registry);
    for (RootElementConfigurator root : RootElementConfigurator.all()) {
        final CNode config = root.describe(root.getTargetComponent(context), context);
        final Node valueNode = toYaml(config);
        if (valueNode == null)
            continue;
        tuples.add(new NodeTuple(new ScalarNode(Tag.STR, root.getName(), null, null, PLAIN), valueNode));
    }
    MappingNode root = new MappingNode(Tag.MAP, tuples, BLOCK);
    try (Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8)) {
        serializeYamlNode(root, writer);
    } catch (IOException e) {
        throw new YAMLException(e);
    }
}
Also used : ScalarNode(org.yaml.snakeyaml.nodes.ScalarNode) SequenceNode(org.yaml.snakeyaml.nodes.SequenceNode) CNode(io.jenkins.plugins.casc.model.CNode) Node(org.yaml.snakeyaml.nodes.Node) MappingNode(org.yaml.snakeyaml.nodes.MappingNode) ScalarNode(org.yaml.snakeyaml.nodes.ScalarNode) ArrayList(java.util.ArrayList) YAMLException(org.yaml.snakeyaml.error.YAMLException) IOException(java.io.IOException) CNode(io.jenkins.plugins.casc.model.CNode) MappingNode(org.yaml.snakeyaml.nodes.MappingNode) OutputStreamWriter(java.io.OutputStreamWriter) NodeTuple(org.yaml.snakeyaml.nodes.NodeTuple) Writer(java.io.Writer) OutputStreamWriter(java.io.OutputStreamWriter) Restricted(org.kohsuke.accmod.Restricted)

Example 9 with Restricted

use of org.kohsuke.accmod.Restricted in project configuration-as-code-plugin by jenkinsci.

the class ConfigurationAsCode method doReplace.

@RequirePOST
@Restricted(NoExternalUse.class)
public void doReplace(StaplerRequest request, StaplerResponse response) throws Exception {
    if (!Jenkins.get().hasPermission(Jenkins.ADMINISTER)) {
        response.sendError(HttpServletResponse.SC_FORBIDDEN);
        return;
    }
    String newSource = request.getParameter("_.newSource");
    String normalizedSource = Util.fixEmptyAndTrim(newSource);
    List<String> candidateSources = new ArrayList<>();
    for (String candidateSource : inputToCandidateSources(normalizedSource)) {
        File file = new File(candidateSource);
        if (file.exists() || ConfigurationAsCode.isSupportedURI(candidateSource)) {
            candidateSources.add(candidateSource);
        } else {
            LOGGER.log(Level.WARNING, "Source {0} could not be applied", candidateSource);
        // todo: show message in UI
        }
    }
    if (!candidateSources.isEmpty()) {
        List<YamlSource> candidates = getConfigFromSources(candidateSources);
        if (canApplyFrom(candidates)) {
            sources = candidateSources;
            configureWith(getConfigFromSources(getSources()));
            CasCGlobalConfig config = GlobalConfiguration.all().get(CasCGlobalConfig.class);
            if (config != null) {
                config.setConfigurationPath(normalizedSource);
                config.save();
            }
            LOGGER.log(Level.FINE, "Replace configuration with: " + normalizedSource);
        } else {
            LOGGER.log(Level.WARNING, "Provided sources could not be applied");
        // todo: show message in UI
        }
    } else {
        LOGGER.log(Level.FINE, "No such source exists, applying default");
        // May be do nothing instead?
        configure();
    }
    response.sendRedirect("");
}
Also used : ArrayList(java.util.ArrayList) File(java.io.File) YamlSource(io.jenkins.plugins.casc.yaml.YamlSource) RequirePOST(org.kohsuke.stapler.interceptor.RequirePOST) Restricted(org.kohsuke.accmod.Restricted)

Example 10 with Restricted

use of org.kohsuke.accmod.Restricted in project configuration-as-code-plugin by jenkinsci.

the class ConfigurationAsCode method serializeYamlNode.

// for testing only
@Restricted(NoExternalUse.class)
public static void serializeYamlNode(Node root, Writer writer) throws IOException {
    DumperOptions options = new DumperOptions();
    options.setDefaultFlowStyle(BLOCK);
    options.setDefaultScalarStyle(PLAIN);
    options.setSplitLines(true);
    options.setPrettyFlow(true);
    Serializer serializer = new Serializer(new Emitter(writer, options), new Resolver(), options, null);
    serializer.open();
    serializer.serialize(root);
    serializer.close();
}
Also used : Emitter(org.yaml.snakeyaml.emitter.Emitter) Resolver(org.yaml.snakeyaml.resolver.Resolver) DumperOptions(org.yaml.snakeyaml.DumperOptions) Serializer(org.yaml.snakeyaml.serializer.Serializer) Restricted(org.kohsuke.accmod.Restricted)

Aggregations

Restricted (org.kohsuke.accmod.Restricted)22 IOException (java.io.IOException)7 ArrayList (java.util.ArrayList)7 File (java.io.File)5 HashMap (java.util.HashMap)4 RequirePOST (org.kohsuke.stapler.interceptor.RequirePOST)4 YamlSource (io.jenkins.plugins.casc.yaml.YamlSource)3 Method (java.lang.reflect.Method)3 URL (java.net.URL)3 PathMatcher (java.nio.file.PathMatcher)3 Map (java.util.Map)3 Jenkins (jenkins.model.Jenkins)3 JSONArray (net.sf.json.JSONArray)3 JSONObject (net.sf.json.JSONObject)3 CheckForNull (edu.umd.cs.findbugs.annotations.CheckForNull)2 NonNull (edu.umd.cs.findbugs.annotations.NonNull)2 Describable (hudson.model.Describable)2 BuildStepDescriptor (hudson.tasks.BuildStepDescriptor)2 CNode (io.jenkins.plugins.casc.model.CNode)2 Source (io.jenkins.plugins.casc.model.Source)2