github.com/mackerelio/mackerel-agent-plugins@v0.89.3/tool/gen_mackerel_plugin.pl (about)

     1  #!/usr/bin/env perl
     2  use 5.014;
     3  use warnings;
     4  use utf8;
     5  use autodie;
     6  use IO::File;
     7  use JSON::PP;
     8  
     9  my $PLUGIN_PREFIX = 'mackerel-plugin-';
    10  my $PACKAGE_NAME = 'mackerel-agent-plugins';
    11  
    12  # refer Mackerel::ReleaseUtils
    13  sub replace {
    14      my ($glob, $code) = @_;
    15      for my $file (glob $glob) {
    16          my $content = $code->(slurp_utf8($file), $file);
    17          $content .= "\n" if $content !~ /\n\z/ms;
    18  
    19          # for keeping permission
    20          append_file($file, $content);
    21      }
    22  }
    23  
    24  sub retrieve_plugins {
    25      # exclude plugins which has been moved to other repositories
    26      sort map {s/^$PLUGIN_PREFIX//; $_} grep { -e "$_/lib" } <$PLUGIN_PREFIX*>;
    27  }
    28  
    29  sub update_readme {
    30      my $plugins = shift;
    31      my $external_plugins = shift;
    32  
    33      my $doc_links = '';
    34      my %doc_links_lines;
    35      for my $plug (@$plugins) {
    36          $doc_links_lines{$plug} = "* [$PLUGIN_PREFIX$plug](./$PLUGIN_PREFIX$plug/README.md)\n"
    37      }
    38      for my $plug (@$external_plugins) {
    39          my $link = sprintf "https://%s/blob/main/README.md", $plug->{'repository'};
    40          $doc_links_lines{$plug->{name}} = "* [$PLUGIN_PREFIX$plug->{name}]($link)\n"
    41      }
    42  
    43      for my $key (sort keys %doc_links_lines) {
    44          $doc_links .= $doc_links_lines{$key};
    45      }
    46  
    47      replace 'README.md' => sub {
    48          my $readme = shift;
    49          my $plu_reg = qr/$PLUGIN_PREFIX[-0-9a-zA-Z_]+/;
    50          my $plu_reg_readme = qr/\.\/$PLUGIN_PREFIX[-0-9a-zA-Z_]+|https:\/\/github\.com\/mackerelio\/[-0-0a-zA-Z_]+\/blob\/main/;
    51          $readme =~ s!(?:\* \[$plu_reg\]\($plu_reg_readme/README\.md\)\n)+!$doc_links!ms;
    52          $readme;
    53      };
    54  }
    55  
    56  sub update_packaging_specs {
    57      my @plugins = @_;
    58      my $for_in = 'for i in ' . join(' ', @plugins) . '; do';
    59  
    60      my $replace_sub = sub {
    61          my $content = shift;
    62          $content =~ s/for i in.*?;\s*do/$for_in/ms;
    63          $content;
    64      };
    65      replace $_, $replace_sub for ("packaging/rpm/$PACKAGE_NAME*.spec", "packaging/deb*/debian/rules", "packaging/tar/build.sh");
    66  }
    67  
    68  ####
    69  # file utility
    70  ####
    71  
    72  sub slurp_utf8 {
    73      my $filename = shift;
    74      my $fh = IO::File->new($filename, "<:utf8");
    75      local $/;
    76      <$fh>;
    77  }
    78  sub write_file {
    79      my $filename = shift;
    80      my $content = shift;
    81      my $fh = IO::File->new($filename, ">:utf8");
    82      print $fh $content;
    83      $fh->close;
    84  }
    85  sub append_file {
    86      my $filename = shift;
    87      my $content = shift;
    88      my $fh = IO::File->new($filename, "+>:utf8");
    89      print $fh $content;
    90      $fh->close;
    91  }
    92  
    93  sub load_packaging_confg {
    94      decode_json(slurp_utf8('packaging/config.json'));
    95  }
    96  
    97  ####
    98  # some file generate task
    99  ####
   100  
   101  sub subtask {
   102      my $config = load_packaging_confg;
   103      my @plugins = retrieve_plugins;
   104      update_readme(\@plugins, $config->{'external-plugins'});
   105  
   106      my @all_plugins = (
   107          @{ $config->{plugins} },
   108          map { $_->{name} } @{ $config->{'external-plugins'} },
   109      );
   110      update_packaging_specs(sort @all_plugins);
   111  }
   112  
   113  subtask();
   114  
   115  ####
   116  # go:generate task
   117  ####
   118  
   119  my @plugins = sort @{ load_packaging_confg()->{plugins}};
   120  my @external_plugins = sort { $a->{name} cmp $b->{name} } @{ load_packaging_confg()->{'external-plugins'}};
   121  
   122  sub resolve_package {
   123      my $plug = shift;
   124      $plug =~ s/-//g;
   125      "mp$plug";
   126  }
   127  
   128  my $imports = "";
   129  my $case = "";
   130  my $plugs = "";
   131  for my $plug (@plugins) {
   132      my $pkg = "mp$plug";
   133         $pkg =~ s/-//g;
   134      $imports .= sprintf qq[\t"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-%s/lib"\n], $plug;
   135      $case .= sprintf qq[\tcase "%s":\n\t\t%s.Do()\n], $plug, $pkg;
   136      $plugs .= sprintf qq[\t"%s",\n], $plug;
   137  }
   138  for my $pluginfo (@external_plugins) {
   139      my $plug = $pluginfo->{name};
   140      my $pkg = "mp$plug";
   141         $pkg =~ s/-//g;
   142      $imports .= sprintf qq[\t"%s/lib"\n], $pluginfo->{repository};
   143      $case .= sprintf qq[\tcase "%s":\n\t\t%s.Do()\n], $plug, $pkg;
   144      $plugs .= sprintf qq[\t"%s",\n], $plug;
   145  }
   146  
   147  my $mackerel_plugin_gen = qq!// Code generated by "tool/gen_mackerel_plugin.pl"; DO NOT EDIT
   148  package main
   149  
   150  import (
   151  	"fmt"
   152  
   153  $imports)
   154  
   155  func runPlugin(plug string) error {
   156  	switch plug {
   157  ${case}\tdefault:
   158  		return fmt.Errorf("unknown plugin: %q", plug)
   159  	}
   160  	return nil
   161  }
   162  
   163  var plugins = []string{
   164  $plugs}!;
   165  
   166  say $mackerel_plugin_gen;