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

org.elasticsearch.protocol.xpack.XPackInfoResponse Maven / Gradle / Ivy

There is a newer version: 8.13.2
Show newest version
/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0; you may not use this file except in compliance with the Elastic License
 * 2.0.
 */
package org.elasticsearch.protocol.xpack;

import org.elasticsearch.Version;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.protocol.xpack.license.LicenseStatus;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;

public class XPackInfoResponse extends ActionResponse implements ToXContentObject {
    /**
     * Value of the license's expiration time if it should never expire.
     */
    public static final long BASIC_SELF_GENERATED_LICENSE_EXPIRATION_MILLIS = Long.MAX_VALUE - TimeUnit.HOURS.toMillis(24 * 365);
    // TODO move this constant to License.java once we move License.java to the protocol jar

    @Nullable private BuildInfo buildInfo;
    @Nullable private LicenseInfo licenseInfo;
    @Nullable private FeatureSetsInfo featureSetsInfo;

    public XPackInfoResponse(StreamInput in) throws IOException {
        super(in);
        this.buildInfo = in.readOptionalWriteable(BuildInfo::new);
        this.licenseInfo = in.readOptionalWriteable(LicenseInfo::new);
        this.featureSetsInfo = in.readOptionalWriteable(FeatureSetsInfo::new);
    }

    public XPackInfoResponse(@Nullable BuildInfo buildInfo, @Nullable LicenseInfo licenseInfo, @Nullable FeatureSetsInfo featureSetsInfo) {
        this.buildInfo = buildInfo;
        this.licenseInfo = licenseInfo;
        this.featureSetsInfo = featureSetsInfo;
    }

    /**
     * @return  The build info (incl. build hash and timestamp)
     */
    public BuildInfo getBuildInfo() {
        return buildInfo;
    }

    /**
     * @return  The current license info (incl. UID, type/mode. status and expiry date). May return {@code null} when no
     *          license is currently installed.
     */
    public LicenseInfo getLicenseInfo() {
        return licenseInfo;
    }

    /**
     * @return  The current status of the feature sets in X-Pack. Feature sets describe the features available/enabled in X-Pack.
     */
    public FeatureSetsInfo getFeatureSetsInfo() {
        return featureSetsInfo;
    }

    @Override
    public void writeTo(StreamOutput out) throws IOException {
        out.writeOptionalWriteable(buildInfo);
        out.writeOptionalWriteable(licenseInfo);
        out.writeOptionalWriteable(featureSetsInfo);
    }

    @Override
    public boolean equals(Object other) {
        if (other == null || other.getClass() != getClass()) return false;
        if (this == other) return true;
        XPackInfoResponse rhs = (XPackInfoResponse) other;
        return Objects.equals(buildInfo, rhs.buildInfo)
                && Objects.equals(licenseInfo, rhs.licenseInfo)
                && Objects.equals(featureSetsInfo, rhs.featureSetsInfo);
    }

    @Override
    public int hashCode() {
        return Objects.hash(buildInfo, licenseInfo, featureSetsInfo);
    }

    @Override
    public String toString() {
        return Strings.toString(this, true, false);
    }

    @Override
    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
        builder.startObject();

        if (buildInfo != null) {
            builder.field("build", buildInfo, params);
        }

        EnumSet categories = XPackInfoRequest.Category
                .toSet(Strings.splitStringByCommaToArray(params.param("categories", "_all")));
        if (licenseInfo != null) {
            builder.field("license", licenseInfo, params);
        } else if (categories.contains(XPackInfoRequest.Category.LICENSE)) {
            // if the user requested the license info, and there is no license, we should send
            // back an explicit null value (indicating there is no license). This is different
            // than not adding the license info at all
            builder.nullField("license");
        }

        if (featureSetsInfo != null) {
            builder.field("features", featureSetsInfo, params);
        }

        if (params.paramAsBoolean("human", true)) {
            builder.field("tagline", "You know, for X");
        }

        return builder.endObject();
    }

    public static class LicenseInfo implements ToXContentObject, Writeable {
        private final String uid;
        private final String type;
        private final String mode;
        private final LicenseStatus status;
        private final long expiryDate;

        public LicenseInfo(String uid, String type, String mode, LicenseStatus status, long expiryDate) {
            this.uid = uid;
            this.type = type;
            this.mode = mode;
            this.status = status;
            this.expiryDate = expiryDate;
        }

        public LicenseInfo(StreamInput in) throws IOException {
            this(in.readString(), in.readString(), in.readString(), LicenseStatus.readFrom(in), in.readLong());
        }

        @Override
        public void writeTo(StreamOutput out) throws IOException {
            out.writeString(uid);
            out.writeString(type);
            out.writeString(mode);
            status.writeTo(out);
            out.writeLong(expiryDate);
        }

        public String getUid() {
            return uid;
        }

        public String getType() {
            return type;
        }

        public String getMode() {
            return mode;
        }

        public long getExpiryDate() {
            return expiryDate;
        }

        public LicenseStatus getStatus() {
            return status;
        }

        @Override
        public boolean equals(Object other) {
            if (other == null || other.getClass() != getClass()) return false;
            if (this == other) return true;
            LicenseInfo rhs = (LicenseInfo) other;
            return Objects.equals(uid, rhs.uid)
                    && Objects.equals(type, rhs.type)
                    && Objects.equals(mode, rhs.mode)
                    && Objects.equals(status, rhs.status)
                    && expiryDate == rhs.expiryDate;
        }

        @Override
        public int hashCode() {
            return Objects.hash(uid, type, mode, status, expiryDate);
        }

        @Override
        public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
            builder.startObject()
                .field("uid", uid)
                .field("type", type)
                .field("mode", mode)
                .field("status", status.label());
            if (expiryDate != BASIC_SELF_GENERATED_LICENSE_EXPIRATION_MILLIS) {
                builder.timeField("expiry_date_in_millis", "expiry_date", expiryDate);
            }
            return builder.endObject();
        }
    }

    public static class BuildInfo implements ToXContentObject, Writeable {
        private final String hash;
        private final String timestamp;

        public BuildInfo(String hash, String timestamp) {
            this.hash = hash;
            this.timestamp = timestamp;
        }

        public BuildInfo(StreamInput input) throws IOException {
            this(input.readString(), input.readString());
        }

        @Override
        public void writeTo(StreamOutput output) throws IOException {
            output.writeString(hash);
            output.writeString(timestamp);
        }

        public String getHash() {
            return hash;
        }

        public String getTimestamp() {
            return timestamp;
        }

        @Override
        public boolean equals(Object other) {
            if (other == null || other.getClass() != getClass()) return false;
            if (this == other) return true;
            BuildInfo rhs = (BuildInfo) other;
            return Objects.equals(hash, rhs.hash)
                    && Objects.equals(timestamp, rhs.timestamp);
        }

        @Override
        public int hashCode() {
            return Objects.hash(hash, timestamp);
        }

        private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
                "build_info", true, (a, v) -> new BuildInfo((String) a[0], (String) a[1]));
        static {
            PARSER.declareString(constructorArg(), new ParseField("hash"));
            PARSER.declareString(constructorArg(), new ParseField("date"));
        }

        @Override
        public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
            return builder.startObject()
                    .field("hash", hash)
                    .field("date", timestamp)
                    .endObject();
        }
    }

    public static class FeatureSetsInfo implements ToXContentObject, Writeable {
        private final Map featureSets;

        public FeatureSetsInfo(Set featureSets) {
            Map map = new HashMap<>(featureSets.size());
            for (FeatureSet featureSet : featureSets) {
                map.put(featureSet.name, featureSet);
            }
            this.featureSets = Collections.unmodifiableMap(map);
        }

        public FeatureSetsInfo(StreamInput in) throws IOException {
            int size = in.readVInt();
            Map featureSets = new HashMap<>(size);
            for (int i = 0; i < size; i++) {
                FeatureSet featureSet = new FeatureSet(in);
                featureSets.put(featureSet.name, featureSet);
            }
            this.featureSets = Collections.unmodifiableMap(featureSets);
        }

        @Override
        public void writeTo(StreamOutput out) throws IOException {
            out.writeVInt(featureSets.size());
            for (FeatureSet featureSet : featureSets.values()) {
                featureSet.writeTo(out);
            }
        }

        public Map getFeatureSets() {
            return featureSets;
        }

        @Override
        public boolean equals(Object other) {
            if (other == null || other.getClass() != getClass()) return false;
            if (this == other) return true;
            FeatureSetsInfo rhs = (FeatureSetsInfo) other;
            return Objects.equals(featureSets, rhs.featureSets);
        }

        @Override
        public int hashCode() {
            return Objects.hash(featureSets);
        }

        @Override
        public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
            builder.startObject();
            List names = new ArrayList<>(this.featureSets.keySet()).stream().sorted().collect(Collectors.toList());
            for (String name : names) {
                builder.field(name, featureSets.get(name), params);
            }
            return builder.endObject();
        }

        public static class FeatureSet implements ToXContentObject, Writeable {
            private final String name;
            private final boolean available;
            private final boolean enabled;
            @Nullable private final Map nativeCodeInfo;

            public FeatureSet(String name, boolean available, boolean enabled,
                              @Nullable Map nativeCodeInfo) {
                this.name = name;
                this.available = available;
                this.enabled = enabled;
                this.nativeCodeInfo = nativeCodeInfo;
            }

            public FeatureSet(StreamInput in) throws IOException {
                this(in.readString(), readAvailable(in), in.readBoolean(), in.readMap());
            }

            // this is separated out so that the removed description can be read from the stream on construction
            // TODO: remove this for 8.0
            private static boolean readAvailable(StreamInput in) throws IOException {
                if (in.getVersion().before(Version.V_7_3_0)) {
                    in.readOptionalString();
                }
                return in.readBoolean();
            }

            @Override
            public void writeTo(StreamOutput out) throws IOException {
                out.writeString(name);
                if (out.getVersion().before(Version.V_7_3_0)) {
                    out.writeOptionalString(null);
                }
                out.writeBoolean(available);
                out.writeBoolean(enabled);
                out.writeMap(nativeCodeInfo);
            }

            public String name() {
                return name;
            }

            public boolean available() {
                return available;
            }

            public boolean enabled() {
                return enabled;
            }

            @Nullable
            public Map nativeCodeInfo() {
                return nativeCodeInfo;
            }

            @Override
            public boolean equals(Object other) {
                if (other == null || other.getClass() != getClass()) return false;
                if (this == other) return true;
                FeatureSet rhs = (FeatureSet) other;
                return Objects.equals(name, rhs.name)
                        && available == rhs.available
                        && enabled == rhs.enabled
                        && Objects.equals(nativeCodeInfo, rhs.nativeCodeInfo);
            }

            @Override
            public int hashCode() {
                return Objects.hash(name, available, enabled, nativeCodeInfo);
            }

            @Override
            public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
                builder.startObject();
                builder.field("available", available);
                builder.field("enabled", enabled);
                if (nativeCodeInfo != null) {
                    builder.field("native_code_info", nativeCodeInfo);
                }
                return builder.endObject();
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy