Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support import private repository #236

Closed
ak58588 opened this issue Nov 25, 2020 · 15 comments · Fixed by #402
Closed

Support import private repository #236

ak58588 opened this issue Nov 25, 2020 · 15 comments · Fixed by #402

Comments

@ak58588
Copy link

ak58588 commented Nov 25, 2020

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or "me too" comments, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

Terraform (and Azure DevOps Provider) Version

Terraform v0.13.5
azurerm v2.36.0
random v3.0.0
azuredevops v0.1.0

Affected Resource(s)

  • azuredevops_git_repository

Terraform Configuration Files

provider "azurerm" {
  version = "~> 2.36.0"
  features {}
}

provider "azuredevops" {
  version = "= 0.1.0"
  org_service_url       = var.org_service_url 
  personal_access_token = var.personal_access_token
}

resource "azuredevops_project" "appproj" {
  name               = local.project_name
  description        = local.project_description
  visibility         = "private"
  version_control    = "Git"
  work_item_template = local.project_process
  features = {
      "testplans"    = "disabled"
      "artifacts"    = "disabled"
      "boards"       = "enabled" 
      "pipelines"    = "enabled"
      "repositories" = "enabled"
  }
}

## Add Project Owners to Project Administrator role
resource "azuredevops_user_entitlement" "owners" {
  principal_name = each.key
  for_each       = var.project_owners
}

resource "azuredevops_group" "project_owners_group" {
  scope        = azuredevops_project.appproj.id
  display_name = "Project Administrators"
}

resource "azuredevops_group_membership" "project_owners_membership" {
  for_each = var.project_owners
  group    = azuredevops_group.project_owners_group.descriptor
  members = [
    azuredevops_user_entitlement.owners[each.key].descriptor
  ]
}

resource "azuredevops_user_entitlement" "admins" {
  principal_name = each.key
  for_each       = var.project_admins
}

resource "azuredevops_group" "project_team_group" {
  scope        = azuredevops_project.appproj.id
  display_name = "${local.project_name} Team"
}

resource "azuredevops_group_membership" "project_admins_membership" {
  for_each = var.project_admins
  group    = azuredevops_group.project_team_group.descriptor
  members = [
    azuredevops_user_entitlement.admins[each.key].descriptor
  ]
}

data "azurerm_key_vault" "key_vault" {
  name                = module.subscription.kv_name
  resource_group_name = module.subscription.rgname
}

data "azurerm_key_vault_secret" "secret_key_vault" {
  name         = "secretname"  
  key_vault_id = data.azurerm_key_vault.key_vault.id
}

resource "azuredevops_serviceendpoint_azurerm" "endpointazure" {
  project_id            = azuredevops_project.appproj.id
  service_endpoint_name = local.project_spn_name

  credentials {
    serviceprincipalid  = var.spn_objectid
    serviceprincipalkey = data.azurerm_key_vault_secret.secret_key_vault.value
  }
  
  azurerm_spn_tenantid      = local.tenant_id
  azurerm_subscription_id   = module.subscription.subscription_guid
  azurerm_subscription_name = module.subscription.current_subscription_display_name
}

resource "azuredevops_git_repository" "repo" {
  project_id = azuredevops_project.appproj.id
  name       = "abcde"
  initialization {
    init_type = "Import"
    source_type = "Git"
    source_url = "<here comes a url of  a github repo in the same azure devops organisation, but in another project>"
  }
}

Debug Output

2020/11/25 15:00:36 [DEBUG] azuredevops_git_repository.repo: applying the planned Create change
2020-11-25T15:00:36.195Z [DEBUG] plugin.terraform-provider-azuredevops_v0.1.0: 2020/11/25 15:00:36 [DEBUG] expandGitRepository: ID is empty (not set) 
2020/11/25 15:00:36 [DEBUG] azuredevops_git_repository.repo: apply errored, but we're indicating that via the Error pointer rather than returning it: Error import repository in Azure DevOps: <nil> 

Panic Output

Error: Error import repository in Azure DevOps: <nil> 

  on main.tf line 138, in resource "azuredevops_git_repository" "repo":
 138: resource "azuredevops_git_repository" "repo" {

Expected Behavior

The apply proceeds successfully, the repository is created and there is no error.

Actual Behavior

What actually happens:

  1. terraform apply exits with the above mentioned error
  2. the needed resource actually gets created and the repo is imported - can be seen in the Azure DevOps porta;
  3. what is not expected - another empty repo is created with the same name as the project name.

Steps to Reproduce

  1. terraform apply
@xuzhang3
Copy link
Collaborator

@ak58588 Azure DevOps will create a repo with the same as the project name by default. You can reuse the default repository with data source azuredevops_git_repository or azuredevops_git_repositories

@ak58588
Copy link
Author

ak58588 commented Nov 30, 2020

@xuzhang3 thanks for your reply. What still I need is to create a new repo by importing some other existing one...and I wonder what makes terraform apply to fail every time

@xuzhang3
Copy link
Collaborator

@ak58588 I tested your script and it worked for me, I cannot reproduce your error(both of github repo and azure git repo works). Can you share more error logs or reproduce steps? Is the repo you want to import is an existed one or created along with this repo.

@ak58588
Copy link
Author

ak58588 commented Dec 6, 2020

@xuzhang3 thanks for your response. I have tried to deploy a project with a repo only (the one with import). I have examined the debug logs and found there

2020/12/06 17:27:16 [DEBUG] azuredevops_git_repository.repo: applying the planned Create change
2020-12-06T17:27:16.871Z [DEBUG] plugin.terraform-provider-azuredevops_v0.1.0: 2020/12/06 17:27:16 [DEBUG] expandGitRepository: ID is empty (not set)
2020/12/06 17:27:17 [DEBUG] azuredevops_git_repository.repo: apply errored, but we're indicating that via the Error pointer rather than returning it: Error import repository in Azure DevOps: <nil> 
2020/12/06 17:27:17 [ERROR] eval: *terraform.EvalApplyPost, err: Error import repository in Azure DevOps: <nil> 
2020/12/06 17:27:17 [ERROR] eval: *terraform.EvalSequence, err: Error import repository in Azure DevOps: <nil> 

So it complains about the id expandGitRepository: ID is empty (not set)

@ak58588
Copy link
Author

ak58588 commented Dec 6, 2020

@ak58588
Copy link
Author

ak58588 commented Dec 6, 2020

@xuzhang3 I think I got what my problem in my case is - I am referring another Azure DevOps git repo from the same organisation. I have just tried importing some github.com/.git and it worked.

@ChrisF987
Copy link

@ak58588 I'm experiencing this issue also, with the same Error: Error import repository in Azure DevOps: <nil> error message.

I'm trying to import an existing repo from the same project and organisation. When I do this via the UI, I have to provide authentication. @xuzhang3 is this supported by the updated provider?

Our use case is that when we create these new repos (there will be many), we want to use the another repo as the template which we will then add code to.

@xuzhang3
Copy link
Collaborator

xuzhang3 commented Dec 7, 2020

Hi @ChrisF987 @ak58588 The root issue here is current import function only support public repo link, if you want import a private repo, you need the pass the credentials.
If the source repository is empty. This error will also happen, the source repo should have at least one file.

Potential Terraform Configuration

resource "azuredevops_git_repository" "repo" {
  project_id = id
  name = "Project name"
  initialization {
    init_type = "Import"
    source_type = "Git"
    source_url = "repo_link"
    username =""
    password=""
   personal_access_token=""
  }
}

@xuzhang3 xuzhang3 changed the title Importing an existing repo when creating azuredevops_git_repository fails, though the resource is created and is seen in the portal Support import private repository Dec 7, 2020
@ak58588
Copy link
Author

ak58588 commented Dec 7, 2020

Thanks, @xuzhang3 ! I have just tried adding the credentials and I am getting the error "unsupported argument" on these three parameters like this:

An argument named "personal_access_token" is not expected here.

@xuzhang3
Copy link
Collaborator

xuzhang3 commented Dec 7, 2020

Hi @ak58588 This is not supported yet, this is new feature we need to implement.

@ak58588
Copy link
Author

ak58588 commented Dec 7, 2020

@xuzhang3 thanks for the information

@wernerfred
Copy link
Contributor

wernerfred commented Dec 21, 2020

Any information about a roadmap for this feature?

Digged a bit deeper in the source code and traced the function calls. Seems like the repository is created and afterwards the import is requested (which we can verify as the repo gets created in azure devops but in state uninitialized).
The function which should trigger the import seems to be this one:

func (client *ClientImpl) CreateImportRequest(ctx context.Context, args CreateImportRequestArgs) (*GitImportRequest, error) {

(Note the [Preview]in the comment line above)

When running terraform we get the same error as @ak58588 :
Error: Error import repository in Azure DevOps: <nil>

On line 599 onwards it says:

resp, err := client.Client.Send(ctx, http.MethodPost, locationId, "5.1-preview.1", routeValues, nil, bytes.NewReader(body), "application/json", "application/json", nil)
if err != nil {
	return nil, err
}

So as we are not getting any additional error message besides to nil there might be a problem with the actual API call? Might this be related to microsoft/azure-devops-go-api#93 ?

EDIT 1:

Can someone explain what location does and why it is hardcoded?:

locationId, _ := uuid.Parse("01828ddc-3600-4a41-8633-99b3a73a0eb3")

Here we have "5.1-preview.1" as part of the request

resp, err := client.Client.Send(ctx, http.MethodPost, locationId, "5.1-preview.1", routeValues, nil, bytes.NewReader(body), "application/json", "application/json", nil)

which is no longer available at the official API documentation

EDIT 2:

Another finding: The CreateRpository function which runs sucessfully before the CreateImportRequest function uses API version 5.1:

resp, err := client.Client.Send(ctx, http.MethodPost, locationId, "5.1", routeValues, queryParams, bytes.NewReader(body), "application/json", "application/json", nil)

whereas the latter one uses 5.1-preview.1

So for me there are 2 different things that could be the root cause:

  1. This terraform provider does not support the authentication to clone private repos
  2. The API which is triggered by this provider does not support cloning private repos at all (which would be worst case)

@wernerfred
Copy link
Contributor

@xuzhang3 any roadmap update on this? Is there any point where we can assist?

@xuzhang3
Copy link
Collaborator

Hi @wernerfred In portal, when you try to import a repository with authorization, you will find 4 HTTP requests before the repository created.
image
Analysis the requests, you will found that the authorization is based on service connection(the third request endpoints), since import API support send the service connection ID along with the request, you can do the authorization with service connection.

@xuzhang3
Copy link
Collaborator

xuzhang3 commented Apr 14, 2021

@wernerfred This issue is in our backlog, but not the highest priority. If you interest in this issue, you can create a PR for it.

dmccaffery added a commit to dmccaffery/terraform-provider-azuredevops that referenced this issue Jun 11, 2021
…sitories

* add support for username and password authentication with import
  initialization of the `resource_git_repository` resource
* create `UsernamePassword` service connection when credentials are
  specified, which is used by the import request
* fix an issue where errors in the import / initialization process could
  leave behind the uninitialized repository without being recorded in
  state

Closes: microsoft#236
dmccaffery added a commit to dmccaffery/terraform-provider-azuredevops that referenced this issue Jun 11, 2021
…sitories

* add support for username and password authentication with import
  initialization of the `resource_git_repository` resource
* create `UsernamePassword` service connection when credentials are
  specified, which is used by the import request
* fix an issue where errors in the import / initialization process could
  leave behind the uninitialized repository without being recorded in
  state

Closes: microsoft#236
dmccaffery added a commit to dmccaffery/terraform-provider-azuredevops that referenced this issue Jun 15, 2021
…sitories

* add support for specifying a `service_connection_id` for importing
  private repositories using the `serviceendpoint_generic_git` resource
* add acceptance test that imports a repository from azure devops via
  the `serviceendpoint_generic_git` resource
* fix an issue where errors in the import / initialization process could
  leave behind the uninitialized repository without being recorded in
  state

Closes: microsoft#236
Supersedes: microsoft#181
dmccaffery added a commit to dmccaffery/terraform-provider-azuredevops that referenced this issue Jun 22, 2021
…sitories

* add support for specifying a `service_connection_id` for importing
  private repositories using the `serviceendpoint_generic_git` resource
* add acceptance test that imports a repository from azure devops via
  the `serviceendpoint_generic_git` resource
* fix an issue where errors in the import / initialization process could
  leave behind the uninitialized repository without being recorded in
  state

Closes: microsoft#236
Supersedes: microsoft#181
dmccaffery added a commit to dmccaffery/terraform-provider-azuredevops that referenced this issue Jun 23, 2021
…sitories

* add support for specifying a `service_connection_id` for importing
  private repositories using the `serviceendpoint_generic_git` resource
* add acceptance test that imports a repository from azure devops via
  the `serviceendpoint_generic_git` resource
* fix an issue where errors in the import / initialization process could
  leave behind the uninitialized repository without being recorded in
  state

Closes: microsoft#236
Supersedes: microsoft#181
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants