[RUBY] Comment créer un plugin Vagrant que vous avez appris lorsque vous avez forké et publié vagrant-mutagen

Comment créer un plugin Vagrant que vous avez appris lorsque vous avez forké et publié vagrant-mutagen

introduction

Vagrant Plugin est une extension qui vous permet d'ajouter des fonctionnalités à Vagrant.

Récemment, mutagen est utilisé pour la synchronisation de fichiers lors du démarrage d'une VM, et le projet mutagen est lié au démarrage / arrêt de la VM [vagrant-mutagen plugin](https://github.com/dasginganinja/ Je pensais utiliser vagrant-mutagène).

Cependant, cela ne fonctionnait pas correctement sous Windows et j'utilisais la version modifiée avec PR, mais cela démarre toujours la VM. J'avais des problèmes car je devais augmenter mes privilèges d'administrateur deux fois à chaque fois.

J'ai décidé de créer et de créer un plug-in Vagrant à volonté, et j'ai décidé de résumer ce que j'avais étudié à l'époque.

Le code source du plugin forké peut être trouvé à ici, veuillez donc vous y référer comme exemple.

Présentation du plug-in Vagrant

Pour savoir comment le fabriquer, je me suis référé à celui décrit ci-dessous.

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

Comment écrire un Gemfile

my-vagrant-plugin est le nom du plugin que vous créez.

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 est nécessaire pour le développement, et en mode développement, la commande vagrant plugin ne fonctionne pas et à la place, le gem spécifié dans le groupe plugins est chargé.

Je n'avais généralement pas de développement Ruby dans l'environnement Windows, donc lors du développement du plugin Vagrant, j'ai utilisé celui qui était déjà installé sur Windows, et chaque fois que je `gem construis 'le plugin et le désinstalle / installe avec vagrant. ..

1.Faites de Plugin un bijou

  1. Installez le plugin

(Je pensais que je ne ferais pas de gros correctif, mais avec le recul, je pense qu'il était plus facile d'exécuter Vagrant en mode développement.)

Conception de base du plugin

Définissez la classe qui est le corps principal du plug-in et spécifiez les noms de classe de composant tels que Config et Provisioner dans la classe.

Vous devez exiger la classe Plugin du fichier qui correspond au nom répertorié dans gemspec.

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

Dans l'utilitaire vagrant-mutagen-utilizer que j'ai créé, cela ressemble à ceci:

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

Le vagrant-mutagène fourchu était à l'origine comme ça, mais au lieu de décrire divers processus dans le corps du plugin, la classe est décrite séparément pour chaque processus, lue à l'aide de require_relative et enregistrée en tant que composant. ..

Comment définir Config

Spécifiez le nom de la classe sur le côté du corps du plugin. Le "foo" spécifié ici correspond à config.foo. ~ Dans le Vagrantfile.

config "foo" do
  require_relative "config"
  Config
end

Le composant Config est défini comme une sous-classe de Vagrant.plugin (2 ,: config).

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 est une valeur qui pointe vers undefined dans Vagrant. Certains plugins fournissent des valeurs non définies afin que vous puissiez définir nil comme valeur initiale ou correcte.

initialize est le constructeur lorsque la classe Config est initialisée et finalize! est appelé lorsque toutes les configurations ont été lues.

Dans l'exemple, «0» est attribué si «@ widgets» n'est pas défini dans le fichier de configuration.

La valeur définie dans Config est accessible en tant que machine.config.mutagen_utilizer.orchestrate.

Action Hooks

Réglez ceci lorsque vous souhaitez effectuer un traitement spécifique lorsque «vagrant up», «vagrant halt», etc. sont exécutés.

Les types de hook peuvent être trouvés à https://www.vagrantup.com/docs/plugins/action-hooks#public-action-hooks.

Dans ce qui suit, les classes UpdateConfig et StartOrchestration sont définies pour être appelées lorsque vagrant up est exécuté.

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

Les classes UpdateConfig et StartOrchestration sont définies comme suit:

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

Dans UpdateConfig et StartOrchestration, le constructeur enregistre uniquement la valeur reçue de l'argument dans la variable d'instance.

-- @ app: Utilisé lorsque la méthode d'appel est exécutée. Les détails sont inconnus. -- @ machine: Vous pouvez vous référer à l'ID et à la configuration liés à la VM. -- @ config: Vous pouvez voir les paramètres -- @ console: l'entrée / sortie de la console est possible

La fonctionnalité principale est décrite dans la méthode d'appel. Ici, nous vérifions si le plugin est activé dans Config, et si c'est le cas, nous appelons la méthode start_orchestration de la classe Orchestrattor.

La classe Orchestrattor est:

# 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

Les détails sont omis, mais update_ssh_config_entry appelé depuis Action Hooks décrit le processus d'ajout d'une entrée au fichier de configuration SSH, et start_orchestration décrit le processus de démarrage d'un projet mutagen.

De cette façon, vous pouvez écrire un plugin qui fait une chose spécifique lorsque vagrant up est exécuté.

Si vous voulez connaître les filtres autres que «vagrant up», vous pouvez vous référer à https://www.vagrantup.com/docs/plugins/action-hooks#public-action-hooks.

Entrée / sortie console

Il est déjà apparu plusieurs fois, mais il entre et sort du texte via Vagrant :: UI pour les E / S de Vagrant. Vous ne pouvez pas utiliser le put / get standard de Ruby.

L'environnement de chaque middleware, ʻenv, vous permet d'obtenir Vagrant :: UI avec ʻenv [: ui] .

Il existe des niveaux de sortie de journal d'informations, d'avertissement, d'erreur, de réussite et vous pouvez générer des journaux à chaque niveau.

Plugin de publication

La procédure est la même que pour exposer la gemme aux rubygèmes.

Lors de l'utilisation de la commande rake (Vagrant officiellement présenté comme un moyen facile)

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

Lors de l'utilisation de la commande gem

  1. gem build
  2. gem push

Recommended Posts

Comment créer un plugin Vagrant que vous avez appris lorsque vous avez forké et publié vagrant-mutagen
Comment créer un plug-in Jenkins
Comment créer une application avec un mécanisme de plug-in [C # et Java]
Comment créer un conteneur Java
Comment créer un pilote JDBC
Comment créer un écran de démarrage
Comment faire un projet Maven
Comment identifier le chemin sur lequel il est facile de se tromper
Comment créer un tableau Java
Lorsque vous recevez un appel, envoyez un SMS à ce numéro
Comment tester une méthode privée et la simuler partiellement en Java
Comment afficher les messages d'erreur et les messages de réussite lors de l'inscription en tant qu'utilisateur
Réglage des performances JVM: qu'est-ce que le réglage et comment élaborer un bon plan
Comment créer une méthode pratique qui utilise des génériques et une interface fonctionnelle
Comment créer un résumé de calendrier Java
Comment créer un robot Discord (Java)
[Java] Raccourcis Eclipse qui peuvent être améliorés en sachant lors des allers-retours entre le code source d'un projet
Comment faire fonctionner @Transactional qui ne fonctionne pas si vous ne l'utilisez pas correctement
Une histoire où j'ai essayé de faire une vidéo en liant Traitement et Resolume
Trouvez une valeur pratique pour avoir une méthode et en faire un ValueObject
Comment obtenir uniquement les articles et les transactions que vous avez commentés ou envoyés par message [comprend]
[Rails] Comment écrire lors de la création d'une sous-requête
Comment créer une classe qui hérite des informations de classe
Comment créer un JRE léger pour la distribution
J'ai essayé de créer une application qui vous permet de publier et de discuter par genre ~ Là où j'ai eu du mal ~
Comment créer un plug-in natif Unity (version Android)
Vous n'avez pas besoin d'écrire deux fois lorsque vous créez un triangle rectangle en Java
[Ruby] 5 erreurs courantes qui ont tendance à se produire lors du scraping avec Selenium et comment les gérer
Comment quitter Docker pour Mac et créer un environnement de développement Docker avec Ubuntu + Vagrant
Comment faire fonctionner JavaScript sur une page spécifique
Comment penser quand on comprend soudainement les génériques
Comment convertir A en A et A en A en utilisant le produit logique et la somme en Java
Comment faire un cache sans trop réfléchir
Comment faire un MOD pour Slay the Spire
Remarques à vérifier lorsque vous essayez d'utiliser Lombok
Comment initialiser par lots des tableaux avec Java que je ne savais pas quand j'étais débutant
[Tutoriel Rails Chapitre 2] Que faire lorsque vous faites une erreur dans le nom de la colonne
J'ai essayé de créer une application qui vous permet de publier et de discuter par genre ~ Vue d'ensemble de l'application ~