[RUBY] Wie erstelle ich ein Vagrant Plugin, das Sie gelernt haben, als Sie Vagrant-Mutagen gegabelt und veröffentlicht haben?

Wie erstelle ich ein Vagrant Plugin, das Sie gelernt haben, als Sie Vagrant-Mutagen gegabelt und veröffentlicht haben?

Einführung

Das Vagrant Plugin ist eine Erweiterung, mit der Sie Vagrant Funktionen hinzufügen können.

In letzter Zeit wird Mutagen für die Dateisynchronisierung beim Starten einer VM verwendet, und das Mutagen-Projekt ist mit dem Starten / Stoppen der VM [Vagrant-Mutagen-Plugin] verknüpft (https://github.com/dasginganinja/). Ich dachte daran, Vagrant-Mutagen zu verwenden.

Unter Windows funktionierte es jedoch nicht richtig, und ich habe die geänderte Version mit PR verwendet, aber die VM wird trotzdem gestartet. Ich hatte Probleme, weil ich meine Administratorrechte jedes Mal zweimal erhöhen musste.

Ich beschloss, nach Belieben ein Vagrant-Plugin zu erstellen und zusammenzufassen, was ich damals untersucht hatte.

Der Quellcode des gegabelten Plugins finden Sie unter hier. Bitte beziehen Sie sich als Beispiel darauf.

Vagrant Plugin Übersicht

Für die Gliederung, wie es gemacht wird, habe ich auf die unten beschriebene verwiesen.

https://www.vagrantup.com/docs/plugins/development-basics

Wie schreibe ich eine Gemfile

my-vagrant-plugin ist der Name des Plugins, das Sie erstellen.

source "https://rubygems.org"

group :development do
  gem "vagrant", git: "https://github.com/hashicorp/vagrant.git"
end

group :plugins do
  gem "my-vagrant-plugin", path: "."
end

Vagrant wird für die Entwicklung benötigt, und im Entwicklungsmodus funktioniert der Befehl "vagrant plugin" nicht. Stattdessen wird der in der Plugins-Gruppe angegebene Edelstein geladen.

Normalerweise hatte ich keine Ruby-Entwicklung in der Windows-Umgebung. Bei der Entwicklung des Vagrant-Plugins habe ich das verwendet, das bereits unter Windows installiert war, und jedes Mal, wenn ich das Plugin "gem" baue und es mit vagrant deinstalliere / installiere. ..

  1. Machen Sie Plugin zu einem Juwel
  1. Installieren Sie das Plugin

(Ich dachte, ich würde keine große Lösung finden, aber rückblickend denke ich, dass es einfacher war, Vagrant im Entwicklungsmodus auszuführen.)

Grundlegendes Design des Plugins

Definieren Sie die Klasse, die den Hauptteil des Plugins darstellt, und geben Sie die Komponentenklassennamen wie Config und Provisioner in der Klasse an.

Sie müssen die Plugin-Klasse aus der Datei benötigen, die dem in gemspec aufgeführten Namen entspricht.

lib/<SOME_PLUGIN_NAME>/plugin.rb


class MyPlugin < Vagrant.plugin("2")
  name "My Plugin"

  command "run-my-plugin" do
    require_relative "command"
    Command
  end

  provisioner "my-provisioner" do
    require_relative "provisioner"
    Provisioner
  end
end

In dem von mir erstellten Vagrant-Mutagen-Utilizer sieht es so aus:

lib/vagrant_mutagen_utilizer/plugin.rb


# frozen_string_literal: true

require_relative 'action/update_config'
require_relative 'action/remove_config'
require_relative 'action/start_orchestration'
require_relative 'action/terminate_orchestration'
require_relative 'action/save_machine_identifier'

module VagrantPlugins
  module MutagenUtilizer
    # Plugin to utilize mutagen
    class MutagenUtilizerPlugin < Vagrant.plugin('2')
      name 'Mutagen Utilizer'
      description <<-DESC
        This plugin manages the ~/.ssh/config file for the host machine. An entry is
        created for the hostname attribute in the vm.config.
      DESC

      config(:mutagen_utilizer) do
        require_relative 'config'
        Config
      end

      action_hook(:mutagen_utilizer, :machine_action_up) do |hook|
        hook.append(Action::UpdateConfig)
        hook.append(Action::StartOrchestration)
      end
        : <snip>
    end
  end
end

vagrant-mutagen-utilizer.gemspec


lib = File.expand_path('lib', __dir__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'vagrant_mutagen_utilizer/version'

Gem::Specification.new do |spec|
  spec.name          = 'vagrant-mutagen-utilizer'
    : <snip>
end

lib/vagrant-mutagen-utilizer.rb


# frozen_string_literal: true

require 'vagrant_mutagen_utilizer/version'
require 'vagrant_mutagen_utilizer/plugin'

module VagrantPlugins
  # MutagenUtilizer
  module MutagenUtilizer
    def self.source_root
      @source_root ||= Pathname.new(File.expand_path('..', __dir__))
    end
  end
end

Das gegabelte Vagrant-Mutagen war ursprünglich so, aber anstatt verschiedene Prozesse im Plugin-Body zu beschreiben, wird die Klasse für jeden Prozess separat beschrieben, mit require_relative gelesen und als Komponente registriert. ..

So stellen Sie Config ein

Geben Sie den Klassennamen auf der Plugin-Körperseite an. Das hier angegebene "foo" entspricht config.foo. ~ In der Vagrant-Datei.

config "foo" do
  require_relative "config"
  Config
end

Die Config-Komponente ist als Unterklasse von "Vagrant.plugin (2,: config)" definiert.

class Config < Vagrant.plugin(2, :config)
  attr_accessor :widgets

  def initialize
    @widgets = UNSET_VALUE
  end

  def finalize!
    @widgets = 0 if @widgets == UNSET_VALUE
  end
end

UNSET_VALUE ist ein Wert, der in Vagrant auf undefiniert verweist. Einige Plugins bieten undefinierte Werte, sodass nil als anfänglicher oder korrekter Wert definiert werden kann.

initialize ist der Konstruktor, wenn die Config-Klasse initialisiert wird, und finalize! Wird aufgerufen, wenn alle Configs gelesen wurden.

Im Beispiel wird "0" zugewiesen, wenn "@ widgets" nicht in der Konfigurationsdatei definiert ist.

Auf den in Config festgelegten Wert kann als "machine.config.mutagen_utilizer.orchestrate" zugegriffen werden.

Action Hooks

Stellen Sie dies ein, wenn Sie einen bestimmten Prozess ausführen möchten, wenn "Vagrant Up", "Vagrant Stop" usw. ausgeführt werden.

Hook-Typen finden Sie unter https://www.vagrantup.com/docs/plugins/action-hooks#public-action-hooks.

Im Folgenden werden die Klassen UpdateConfig und StartOrchestration so eingestellt, dass sie aufgerufen werden, wenn "vagrant up" ausgeführt wird.

lib/vagrant_mutagen_utilizer/plugin.rb


# frozen_string_literal: true

require_relative 'action/update_config'
require_relative 'action/start_orchestration'
        : <snip>

module VagrantPlugins
  module MutagenUtilizer
    # Plugin to utilize mutagen
    class MutagenUtilizerPlugin < Vagrant.plugin('2')
        : <snip>
      action_hook(:mutagen_utilizer, :machine_action_up) do |hook|
        hook.append(Action::UpdateConfig)
        hook.append(Action::StartOrchestration)
      end
        : <snip>
    end
  end
end

Die Klassen UpdateConfig und StartOrchestration sind wie folgt definiert:

lib/vagrant_mutagen_utilizer/action/update_config.rb


# frozen_string_literal: true

require_relative '../orchestrator'

module VagrantPlugins
  module MutagenUtilizer
    module Action
      # Update ssh config entry
      # If ssh config entry already exists, just entry appended
      class UpdateConfig
        def initialize(app, env)
          @app = app
          @machine = env[:machine]
          @config = env[:machine].config
          @console = env[:ui]
        end

        def call(env)
          return unless @config.orchestrate?

          o = Orchestrator.new(@machine, @console)
          o.update_ssh_config_entry
          @app.call(env)
        end
      end
    end
  end
end

lib/vagrant_mutagen_utilizer/action/start_orchestration.rb


# frozen_string_literal: true

require_relative '../orchestrator'

module VagrantPlugins
  module MutagenUtilizer
    module Action
      # Start mutagen project
      class StartOrchestration
        def initialize(app, env)
          @app = app
          @machine = env[:machine]
          @config = env[:machine].config
          @console = env[:ui]
        end

        def call(env)
          return unless @config.orchestrate?

          o = Orchestrator.new(@machine, @console)
          o.start_orchestration
          @app.call(env)
        end
      end
    end
  end
end

Sowohl in UpdateConfig als auch in StartOrchestration registriert der Konstruktor nur den vom Argument empfangenen Wert in der Instanzvariablen.

-- @ app: Wird verwendet, wenn die Aufrufmethode ausgeführt wird. Details sind unbekannt. -- @ machine: Sie können sich auf die ID und Konfiguration beziehen, die sich auf die VM beziehen. -- @ config: Sie können die Einstellungen sehen -- @ console: Konsoleneingabe / -ausgabe ist möglich

Die Hauptfunktionalität wird in der Aufrufmethode beschrieben. Hier prüfen wir, ob das Plugin in Config aktiviert ist, und rufen in diesem Fall die Methode start_orchestration der Orchestrattor-Klasse auf.

Die Orchestrattor-Klasse lautet:

# frozen_string_literal: true

module VagrantPlugins
  module MutagenUtilizer
    # Class for orchestrate with mutagen
    class Orchestrator
      def initialize(machine, console)
        @machine = machine
        @console = console
      end

      # Update ssh config entry
      # If ssh config entry already exists, just entry appended
      def update_ssh_config_entry
        hostname = @machine.config.vm.hostname

        logging(:info, 'Checking for SSH config entries')
        if ssh_config_entry_exist?
          logging(:info, "  updating SSH Config entry for: #{hostname}")
          remove_from_ssh_config
        else
          logging(:info, "  adding entry to SSH config for: #{hostname}")
        end
        append_to_ssh_config(ssh_config_entry)
      end

      def start_orchestration
        return if mutagen_project_started?

        logging(:info, 'Starting mutagen project orchestration (config: /mutagen.yml)')
        start_mutagen_project || logging(:error, 'Failed to start mutagen project (see error above)')
        # show project status to indicate if there are conflicts
        list_mutagen_project
      end

        : <snip>

      private

        : <snip>
    end
  end
end

Obwohl Details weggelassen werden, beschreibt update_ssh_config_entry, das von Action Hooks aufgerufen wird, den Vorgang des Hinzufügens eines Eintrags zur SSH-Konfigurationsdatei, und start_orchestration beschreibt den Vorgang des Startens eines mutagenen Projekts.

Auf diese Weise können Sie ein Plugin schreiben, das eine bestimmte Funktion ausführt, wenn "vagrant up" ausgeführt wird.

Wenn Sie andere Filter als "Vagrant Up" kennen möchten, können Sie auf https://www.vagrantup.com/docs/plugins/action-hooks#public-action-hooks verweisen.

Konsoleneingabe / -ausgabe

Es ist bereits mehrmals aufgetaucht, aber es gibt Text über "Vagrant :: UI" für Vagrants I / O ein und gibt ihn aus. Sie können das Standard-Ruby put / get nicht verwenden.

Die Umgebung für jede Middleware, "env", ermöglicht es Ihnen, die Vagrant :: UI mit "env [: ui]" abzurufen.

Es gibt Protokollausgabeebenen mit Informationen, Warnungen, Fehlern und Erfolgen, und Sie können Protokolle auf jeder Ebene ausgeben.

Plugin veröffentlichen

Das Verfahren ist das gleiche wie das Aussetzen des Edelsteins an Rubgemüs.

Bei Verwendung des Rechenbefehls (Vagrants offizieller und einfacher Weg)

  1. bundle install
  2. rake build
  3. rake release

Bei Verwendung des Befehls gem

  1. gem build
  2. gem push

Recommended Posts

Wie erstelle ich ein Vagrant Plugin, das Sie gelernt haben, als Sie Vagrant-Mutagen gegabelt und veröffentlicht haben?
So erstellen Sie ein Jenkins-Plug-In
So erstellen Sie eine App mit einem Plug-In-Mechanismus [C # und Java]
So erstellen Sie einen Java-Container
So erstellen Sie einen JDBC-Treiber
So erstellen Sie einen Begrüßungsbildschirm
Wie erstelle ich ein Maven-Projekt?
So identifizieren Sie den Pfad, auf dem leicht Fehler gemacht werden können
So erstellen Sie ein Java-Array
Wenn Sie einen Anruf erhalten, senden Sie eine SMS an diese Nummer
So testen Sie eine private Methode und verspotten sie teilweise in Java
Anzeigen von Fehlermeldungen und Erfolgsmeldungen bei der Registrierung als Benutzer
JVM-Leistungsoptimierung: Was ist Optimierung und wie erstellt man einen guten Plan?
So erstellen Sie eine bequeme Methode, die Generika und eine funktionale Schnittstelle verwendet
So erstellen Sie eine Java-Kalenderzusammenfassung
Wie erstelle ich einen Discord Bot (Java)
[Java] Eclipse-Verknüpfungen, die verbessert werden können, indem Sie wissen, wann Sie zwischen Quellcode in einem Projekt hin und her wechseln
So funktioniert @Transactional, das nicht funktioniert, wenn Sie es falsch verwenden
Eine Geschichte, als ich versuchte, ein Video zu erstellen, indem ich Processing und Resolume verknüpfte
Suchen Sie einen geeigneten Wert für eine Methode und machen Sie sie zu einem ValueObject
So erhalten Sie nur Artikel und Transaktionen, die Sie kommentiert oder mit Nachrichten versehen haben [enthält]
[Rails] Wie schreibe ich, wenn ich eine Unterabfrage mache?
So erstellen Sie eine Klasse, die Klasseninformationen erbt
So erstellen Sie eine leichte JRE für den Vertrieb
Ich habe versucht, eine App zu erstellen, mit der Sie nach Genre posten und chatten können ~ Wo ich es schwer hatte ~
Wie erstelle ich Unity Native Plugin (Android-Version)
Sie müssen nicht zweimal schreiben, wenn Sie in Java ein rechtwinkliges Dreieck erstellen
[Ruby] 5 häufige Fehler, die beim Schaben mit Selen auftreten und wie man damit umgeht
So beenden Sie Docker für Mac und erstellen eine Docker-Entwicklungsumgebung mit Ubuntu + Vagrant
So funktioniert JavaScript auf einer bestimmten Seite
Wie man denkt, wenn man plötzlich etwas über Generika versteht
So konvertieren Sie A in a und a in A mit logischem Produkt und Summe in Java
Wie man einen Cache erstellt, ohne zu viel nachzudenken
Wie erstelle ich einen MOD für Slay the Spire?
Hinweise zur Überprüfung bei der Verwendung von Lombok
Wie man Arrays mit Java stapelweise initialisiert, wusste ich als Anfänger nicht
[Rails Tutorial Kapitel 2] Was tun, wenn Sie einen Fehlern im Spaltennamen machen?
Ich habe versucht, eine App zu erstellen, mit der Sie nach Genre posten und chatten können ~ Übersicht über die App ~