VMC源码的简单分析

简单看了下VMC的源码,写一个类似提纲的东西。文章里面主要包括VMC各个代码块和他们实现的功能,通过一个命令的实现流程来分析。

VMC执行一条命令的流程:

1. bin/vmc

vmc是一个gem包,所以我们可以在自己的gem文件夹下面找到他们,执行vmc命令其实就是运行bin目录下的vmc文件。这个文件很简单,首先require lib/cli.rb,然后调用VMC::Cli::Runner.run。

2. Cli.rb

前面说到vmc require了Cli.rb文件,而Cli.rb包含了几乎所有需要用到的模块,包括micro的以及普通的Cli。由于我没用过micro的命令,所以本文不对micro作出分析。我们看下Cli.rb文件中有关Cli的model(代码中的autoload相当于lazy的require,只有在需要时才require):

  module Cli
    autoload :Config,         "#{ROOT}/cli/config"
    autoload :Framework,      "#{ROOT}/cli/frameworks"
    autoload :Runner,         "#{ROOT}/cli/runner"
    autoload :ZipUtil,        "#{ROOT}/cli/zip_util"
    autoload :ServicesHelper, "#{ROOT}/cli/services_helper"
    autoload :TunnelHelper,   "#{ROOT}/cli/tunnel_helper"
    autoload :ManifestHelper, "#{ROOT}/cli/manifest_helper"
    autoload :ConsoleHelper,  "#{ROOT}/cli/console_helper"
 
    module Command
      autoload :Base,         "#{ROOT}/cli/commands/base"
      autoload :Admin,        "#{ROOT}/cli/commands/admin"
      autoload :Apps,         "#{ROOT}/cli/commands/apps"
      autoload :Micro,        "#{ROOT}/cli/commands/micro"
      autoload :Misc,         "#{ROOT}/cli/commands/misc"
      autoload :Services,     "#{ROOT}/cli/commands/services"
      autoload :User,         "#{ROOT}/cli/commands/user"
      autoload :Manifest,     "#{ROOT}/cli/commands/manifest"
    end

这里主要分成两块:一是cli目录下的一些工具类,提供了Cli需要的一些通用功能,而另外一部分是在commands目录下,代表了各种不同类型的命令,比如有关于app的(apps),或者有关于service的(services)。

3. Runner.run

前面提到bin/vmc执行命令就是调用Runner.run。那么这个函数在vmc/lib/cli/runner.rb文件中。这个文件主要解析命令以及命令的参数,然后生成一个command,就是前面Cli.rb中提到的各种commands。解析命令其实比较简单,就是分析是哪种类型的(app?service?misc?。。。),然后命令是什么(list?target?。。。),最后参数是什么。
在获得这些数据之后就会尝试生成一个command:

      cmd = VMC::Cli::Command.const_get(@namespace.to_s.capitalize)
      cmd.new(@options).send(@action, *@args.collect(&:dup))

这两行代码的意思是:首先在Command空间下找到namespace对应的常量string(namespace就是对应的类名,比如app的就是Apps,admin就是Admin)。获得这个常量string是为了new一个实例出来,cmd.new(@options)意思就是new一个这个cmd string命名的类。然后.send()是调用这个类的一个函数,函数名就是第一个参数@action,第二个参数就是这个函数的参数。可以看到ruby的反射真是非常的简单。

举个例子:比如我执行命令vmc stop appname。那么这个命令会在runner.rb中解析为:namespace:apps,action:stop,args:appname。然后new一个Apps实例,调用它的stop函数,把appname传进去。

4. 实际执行

从上面的分析我们的流程已经到了command里面了,那么每个command会对命令作出相应的操作。那么我们看Apps类好了,我们看一个list函数,这个函数对应了vmc apps命令(这里list是apps的别名,所以我们可以不使用vmc apps list命令)。那么看这个函数的代码:

def list
      apps = client.apps
      apps.sort! {|a, b| a[:name] <=> b[:name] }
      return display JSON.pretty_generate(apps || []) if @options[:json]
 
      display "\n"
      return display "No Applications" if apps.nil? || apps.empty?
 
      apps_table = table do |t|
        t.headings = 'Application', '# ', 'Health', 'URLS', 'Services'
        apps.each do |app|
          t << [app[:name], app[:instances], health(app), app[:uris].join(', '), app[:services].join(', ')]
        end
      end
      display apps_table
    end

有一行代码:apps = client.apps,我们暂时不管它,只需要知道它是获得了当前cf中的所有app,赋值给apps。那么后面就是在display了,可以返回json格式的,或者table格式的。在table中我们可以看到熟悉的apps table header。

那么回到略过的那一行,我们需要知道client在哪里:这个client其实就是vmc/lib/vmc/client.rb中Client类的实例,那么我们开始看Client类:

5. Client.rb

Client负责一个任务:和CF的cloud controller交互。比如vmc apps,需要给cc发送一个获得所有apps的请求。所以前面提到的client.apps就是调用它的apps函数,这个函数最终会通过request函数发出请求。

 
至此我们的流程已经全部走通了,VMC还是比较简单的,希望大家能够学到点东西

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值