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

Puppet 如何解决vcsrepo问题”;重复声明“;评估错误?,puppet,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

我正在使用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\u class
声明的两个资源,都需要在同一位置进行相同的回购。这样,我就可以使用
demo\u class
声明一个或多个资源,并确保
my\u repo
给出的repo(可能是多个
my\u标签
s共用的)存在

如何修改这个类,以便在不出错的情况下调用它两次

我明白问题所在

我使用以下代码复制了该问题:

  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/Rspec Puppet也会出现一些突破

变量名和类参数名使用
snake\u case

更新

该问题已被编辑,现在是关于如何在多个类中声明相同的
vcsrepo
的问题

一般来说,试着重构,这样你就不必一开始就这么做了。换句话说,只需将它移出这个类,并将它放在只需要声明一次的地方

如果由于某种原因不能这样做,那么也可以使用,这将允许您在同一节点上声明的多个类中声明它

要做到这一点,您只需将现有内容改写为:

  @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\u class
。您需要将其转换为已定义的类型,正如我在上面所做的那样

下面的评论中提到,您也可以使用
确保_资源
确保_资源
;请参阅中的文档。

我看到了问题所在

我使用以下代码复制了该问题:

  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/Rspec Puppet也会出现一些突破

变量名和类参数名使用
snake\u case

更新

该问题已被编辑,现在是关于如何在多个类中声明相同的
vcsrepo
的问题

一般来说,试着重构,这样你就不必一开始就这么做了。换句话说,只需将它移出这个类,并将它放在只需要声明一次的地方

如果由于某种原因不能这样做,那么也可以使用,这将允许您在同一节点上声明的多个类中声明它

要做到这一点,您只需将现有内容改写为:

  @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\u class
。您需要将其转换为已定义的类型,正如我在上面所做的那样


下面的评论中提到,您也可以使用
确保_资源
确保_资源
;请参阅中的文档。

因为您没有在
vcsrepo
资源中使用
$myTag
,所以您尝试做两次相同的事情,Puppet的重复声明错误正确地防止了您可能造成的损坏。我的使用案例是:我有两个资源要求将相同的repo安装到相同的位置。如果vcsrepo说“确保回购A位于位置B”,那么两次声明会造成什么损失?那么您只有一个
vcsrepo
资源,这两个资源都需要。我认为您可能不知道Puppet是一种声明性语言:并且您的示例对myTag的定义不明确。您想要testTag1还是testTag2?这种歧义会导致重复声明错误。阅读“类似资源的行为”,了解为什么用不同的参数重新定义一个类是不明确的,感谢@bigtoni链接。我认为我的困惑可能是因为不理解类似资源和类似包含行为之间的区别。我想当我打算做include时,我可能正在使用资源。我会详细了解一下。由于您没有在
vcsrepo
资源中使用
$myTag
,因此您尝试做两次相同的事情,Puppet的重复声明错误正确地防止了您可能造成的损坏。我的使用案例是:我有两个资源需要将相同的repo安装到相同的位置。如果vcsrepo说“确保回购A位于位置B”,那么两次声明会造成什么损失?那么您只有一个
vcsrepo
资源,这两个资源都需要。我认为您可能不知道Puppet是一种声明性语言:并且您的示例对myTag的定义不明确。您想要testTag1还是testTag2?这种歧义会导致重复声明错误。阅读“类似资源的行为”,了解为什么要重新定义类