Skip to content
3 changes: 2 additions & 1 deletion lib/logstash-docket.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ module LogstashDocket

require_relative 'logstash-docket/repository'
require_relative 'logstash-docket/util/threadsafe_index'
require_relative 'logstash-docket/util/threadsafe_wrapper'
require_relative 'logstash-docket/util/threadsafe_wrapper'
require_relative 'logstash-docket/util/alias_definitions_loader'
74 changes: 74 additions & 0 deletions lib/logstash-docket/aliased_plugin.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# encoding: utf-8

require_relative 'plugin'

module LogstashDocket

class AliasPlugin

SUPPORTED_TYPES = Set.new(%w(input output filter codec).map(&:freeze)).freeze

include Plugin

attr_reader :canonical_plugin, :doc_headers

def initialize(canonical_plugin:, alias_name:, doc_headers:)
fail(ArgumentError) unless canonical_plugin.kind_of?(ArtifactPlugin)

super(type: canonical_plugin.type, name: alias_name)

fail("#{canonical_plugin.desc} plugin type #{type} not supported as an alias plugin") unless SUPPORTED_TYPES.include?(type)

@canonical_plugin = canonical_plugin
@doc_headers = doc_headers
end

##
# @see Plugin#version
def version
@canonical_plugin.version
end

def documentation
content = @canonical_plugin.documentation
@doc_headers.reduce(content) do |memo, header|
memo.gsub(header.fetch("replace"), header.fetch("with"))
end
end

##
# @see Plugin#release_date
def release_date
@canonical_plugin.release_date
end

##
# @see Plugin#changelog_url
def changelog_url
@canonical_plugin.changelog_url
end

##
# @see Plugin#tag
def tag
@canonical_plugin.tag
end

##
# @see Plugin#desc
def desc
@desc ||= "[plugin:#{canonical_name}@#{tag}]"
end

##
# @see Plugin#==
def ==(other)
return false unless super

return false unless other.kind_of?(AliasPlugin)
return false unless self.name == other.name

return true
end
end
end
21 changes: 18 additions & 3 deletions lib/logstash-docket/artifact_plugin.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# encoding: utf-8

require_relative 'embedded_plugin'
require_relative 'aliased_plugin'
require_relative 'plugin'
require_relative 'repository'
require 'set'
Expand Down Expand Up @@ -71,7 +72,7 @@ def initialize(repository:,version:)
@repository = repository
@version = version && Gem::Version.new(version)

@embedded_plugins = Util::ThreadsafeDeferral.for(&method(:generate_embeded_plugins))
@embedded_plugins = Util::ThreadsafeDeferral.for(&method(:generate_embedded_plugins))
end

##
Expand Down Expand Up @@ -105,7 +106,7 @@ def desc
end

##
# Returns an {@link Enumerable[Plugin]} containing itself and any wrapped plugins
# Returns an {@link Enumerable[Plugin]} containing itself and any integrated plugins
#
# @return [Enumerable[Plugin]]
def with_embedded_plugins
Expand All @@ -118,6 +119,20 @@ def with_embedded_plugins
end
end

##
# Returns an {@link Enumerable[Plugin]} containing itself and any wrapped plugins,
# including integration-wrapped plugins and aliases from the provided mappings
#
def with_wrapped_plugins(alias_definitions)
return enum_for(:with_wrapped_plugins, alias_definitions) unless block_given?

with_embedded_plugins do |plugin|
plugin.with_alias(alias_definitions) do |plugin_or_alias|
yield plugin_or_alias
end
end
end

##
# Returns zero or more {@link Plugin::Wrapped} provided by
# an "integration" plugin.
Expand All @@ -144,7 +159,7 @@ def ==(other)
# @api private
#
# @return [Array[EmbeddedPlugin]]: a frozen array of {@link EmbeddedPlugin}
def generate_embeded_plugins
def generate_embedded_plugins
gem_data_version = version || repository.rubygem_info.latest
gem_data_version || fail("No releases on rubygems")

Expand Down
13 changes: 13 additions & 0 deletions lib/logstash-docket/plugin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,19 @@ def desc
fail NotImplementedError
end

def with_alias(alias_definitions)
yield self

return unless alias_definitions.key?(type)
alias_definitions[type]&.each do |alias_definition|
if alias_definition.fetch("from") == name
yield AliasPlugin.new(canonical_plugin: self,
alias_name: alias_definition.fetch("alias"),
doc_headers: alias_definition.fetch("docs", []))
end
end
end

##
# @return [Boolean]
def ==(other)
Expand Down
33 changes: 33 additions & 0 deletions lib/logstash-docket/util/alias_definitions_loader.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# encoding: utf-8

require "yaml"
require "net/http"

module LogstashDocket
module Util
##
# A util module defines repetitive logics for aliased plugins.
#
module AliasDefinitionsLoader

ALIAS_DEFINITIONS_URL = 'https://raw.githubusercontent.com/elastic/logstash/main/logstash-core/src/main/resources/org/logstash/plugins/AliasRegistry.yml'

# Returns alias definitions for each plugin type ([type]=[alias_definitions])
# ex: {
# "input" => [
# [{
# "alias" => "elastic_agent",
# "from" => "beats",
# "docs" => [{
# "replace" => ":plugin: beats",
# "with" => ":plugin: elastic_agent"
# }]
# }]
# ]
# }
def self.get_alias_definitions
YAML::safe_load(Net::HTTP.get(URI(ALIAS_DEFINITIONS_URL))) || fail('empty alias definition')
end
end
end
end
5 changes: 3 additions & 2 deletions plugindocs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
require "fileutils"
require "time"
require "yaml"
require "net/http"
require "stud/try"
require "pmap" # Enumerable#peach

Expand All @@ -26,6 +25,8 @@ def execute
report = JSON.parse(File.read(plugins_json))
repositories = report["successful"]

alias_definitions = Util::AliasDefinitionsLoader.get_alias_definitions

repositories.peach(parallelism) do |repository_name, details|
if settings['skip'].include?(repository_name)
$stderr.puts("Skipping #{repository_name}\n")
Expand All @@ -50,7 +51,7 @@ def execute
next
end

released_plugin.with_embedded_plugins.each do |plugin|
released_plugin.with_wrapped_plugins(alias_definitions).each do |plugin|
$stderr.puts("#{plugin.desc}: fetching documentation\n")
content = plugin.documentation

Expand Down
47 changes: 15 additions & 32 deletions versioned_plugins.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@
require "json"
require "fileutils"
require "time"
require "yaml"
require "net/http"
require "stud/try"
require "octokit"
require "erb"
require "pmap"
require "yaml"

require_relative 'lib/logstash-docket'

require_relative 'lib/core_ext/erb_result_with_hash'
require_relative 'lib/logstash-docket'

class VersionedPluginDocs < Clamp::Command
option "--output-path", "OUTPUT", "Path to a directory where logstash-docs repository will be cloned and written to", required: true
Expand Down Expand Up @@ -175,17 +171,23 @@ def generate_docs
end
end

$stderr.puts("REINDEXING PLUGINS..load plugin aliases")
aliases = load_alias_definitions_for_target_plugins(plugin_names_by_type)
$stderr.puts("REINDEXING PLUGINS, loading plugin aliases...")
alias_definitions_by_type = Util::AliasDefinitionsLoader.get_alias_definitions

# add aliases named to the partitioned plugin names collection
aliases.each { |type, alias_name, _| plugin_names_by_type.fetch(type).add(alias_name) }
alias_definitions_by_type.each do |type, alias_definitions|
alias_definitions.each do |alias_definition|
plugin_names_by_type.fetch(type).add(alias_definition.fetch("alias"))
end
end

# rewrite alias indices if target plugin was changed
$stderr.puts("REINDEXING PLUGINS ALIASES... #{aliases.size}\n")
aliases.each do |type, alias_name, target|
$stderr.puts("[plugin:#{alias_name}] reindexing\n")
write_alias_index(type, alias_name, target)
$stderr.puts("REINDEXING PLUGINS ALIASES... #{alias_definitions_by_type.size}\n")
alias_definitions_by_type.each do |type, alias_definitions|
alias_definitions.each do |alias_definition|
$stderr.puts("[plugin:#{alias_definition.fetch("alias")}] reindexing\n")
write_alias_index(type, alias_definition.fetch("alias"), alias_definition.fetch("from"))
end
end

# rewrite incomplete plugin indices
Expand Down Expand Up @@ -413,26 +415,6 @@ def lazy_create_output_folder(file_name)
FileUtils.mkdir_p(directory) if !File.directory?(directory)
end

# param plugin_names_by_type: map of lists {:input => [beats, tcp, ...]}
# return list of triples (type, alias, target) es: ("input", "agent", "beats")
def load_alias_definitions_for_target_plugins(plugin_names_by_type)
alias_url = URI('https://raw.githubusercontent.com/elastic/logstash/master/logstash-core/src/main/resources/org/logstash/plugins/AliasRegistry.yml')
alias_yml = Net::HTTP.get(alias_url)
yaml = YAML::safe_load(alias_yml) || {}

aliases = []

yaml.each do |type, alias_defs|
alias_defs.each do |alias_name, target|
if plugin_names_by_type.fetch(type).include?(target)
aliases << [type, alias_name, target]
end
end
end

aliases
end

def fetch_stack_versions
stack_versions = Net::HTTP.get(URI.parse(VERSIONS_URL))
@logstash_version = get_logstash_version(stack_versions)
Expand Down Expand Up @@ -467,6 +449,7 @@ def write_stack_versions(content, type)
.gsub("%BRANCH%", @logstash_version) \
.gsub("%ECS_VERSION%", @ecs_version)
end

end

if __FILE__ == $0
Expand Down