如何解决vcsrepo“重复声明”评估错误?

时间:2017-05-22 17:02:59

标签: puppet

我使用puppet-vcsrepo从github安装。代码看起来像这样:

class demo_class(
     $my_repo = undef,
     $my_tag  = undef,
){
    vcsrepo { "$my_repo",
        path     => "/home/user/$my_repo",
        source   => 'git@github.com:7yl4r/$my_repo.git',
        ensure   => latest,
        provider => git,
    }

    # then declare resources specific to my_tag
}

只调用一次就可以正常工作,但我在列表上进行迭代并安装依赖项,因此有时会将此资源声明两次。我认为这大致相当于下面的代码。

class {"demo_class":
    my_repo => test_repo,
    my_tag  => test_tag1,
}
class {"demo_class":
    my_repo => test_repo,
    my_tag  => test_tag2,
}

执行此操作会产生服务器端“重复声明”错误,因为vcsrepo正在尝试两次映射相同的路径。但是,这正是我想要的行为:对于demo_class声明的两个资源,要求在同一位置使用相同的repo。这样我就可以使用demo_class声明一个或多个资源,并确保my_repo给出的回购(可能是多个my_tag共有的)。

如何修改此类以便我可以调用它两次而不会出现错误?

1 个答案:

答案 0 :(得分:2)

我看到了问题。

我使用此代码重现了该问题:

  define my_vcs_repo ($myRepo, $myTag) {
    vcsrepo { "$myRepo-$myTag":
      path     => "/home/user/$myRepo",
      source   => "git@github.com:7yl4r/$myRepo.git",
      revision => $myTag,
      ensure   => latest,
      provider => git,
    }
  }

  $data = [
    {
      myRepo => testRepo,
      myTag  => testTag1,
    },
    {
      myRepo => testRepo,
      myTag  => testTag2,
    },
  ]

  $data.each |$i, $ref| {
    $myRepo = $ref['myRepo']
    $myTag  = $ref['myTag']
    my_vcs_repo { "$myRepo-$i":
      myRepo => $myRepo,
      myTag => $myTag,
    }
  }

然后导致:

     Puppet::PreformattedError:
       Evaluation Error: Error while evaluating a Resource Statement, Evaluation Error: Error while evaluating a Resource Statement, Cannot alias Vcsrepo[testRepo-testTag2] to ["/home/user/testRepo"] at /
Users/alexharvey/git/modules/foo/spec/fixtures/modules/foo/manifests/init.pp:3; resource ["Vcsrepo", "/home/user/testRepo"] already declared at /Users/alexharvey/git/modules/foo/spec/fixtures/modules/foo/
manifests/init.pp:3 at /Users/alexharvey/git/modules/foo/spec/fixtures/modules/foo/manifests/init.pp:3:5 at /Users/alexharvey/git/modules/foo/spec/fixtures/modules/foo/manifests/init.pp:26 on node alexs-macbook-pro.local

问题是你要求Puppet将相同的Git模块克隆到一个目录,但是检出了两个不同的标签。这没有意义。

修复是您需要在vcsrepo路径属性中指定唯一路径,例如:

vcsrepo { "$myRepo-$myTag":
  path     => "/home/user/$myRepo-$myTag",
  source   => "git@github.com:7yl4r/$myRepo.git",
  revision => 'production',
  ensure   => latest,
  provider => git,
}

顺便说一下,我注意到你正在使用camelCase作为你的变量。不要这样做。除了Puppet不是惯用的事实之外,有些事情会在我见过的Puppet / Rspec木偶的某些版本中破裂。

使用snake_case作为变量名和类参数名。

更新

该问题已经过编辑,现在问题是如何在多个班级中声明相同的vcsrepo

通常,尝试重构,这样您就不需要首先执行此操作。换句话说,只需将它移出这个类并将它放在一个只能被声明一次的地方。

如果由于某种原因无法执行此操作,那么您还可以使用virtual resources,这将允许您在将在同一节点上声明的多个类中声明它。

要做到这一点,你只需要重写你所拥有的:

  @vcsrepo { $my_repo:
    path     => "/home/user/$my_repo",
    source   => "git@github.com:7yl4r/$my_repo.git",
    ensure   => latest,
    provider => git,
  }
  realize Vcsrepo[$my_repo]

请记住,您无法在同一节点上两次声明类demo_class。您需要将其转换为已定义的类型,如上所述。

以下评论中提到您还可以使用ensure_resourceensure_resources;请参阅stdlib中的文档。