Azure / azure-sdk-for-ruby

Ruby SDK for Azure Resource Manager: build and manage your Azure cloud infrastructure (Compute, Virtual Networks, Storage, etc...) using Ruby.
MIT License
275 stars 245 forks source link

ARM Notification Hubs server error: NotificationHubProperties / pnsCredentials #344

Closed RocketPop closed 8 years ago

RocketPop commented 8 years ago

I need to iterate over the notification hubs in a given namespace. Then for each one I need to upload APNS certs and GCM certs based if some condition is met. I can iterate the hubs and what I do see seems correct. But none of the NotificationHubProperties are ever filled out in the results. I tried list() and get() - neither fill in the properties. I don't see any documentation for it (the inline doc for get() is incorrect in that it says it lists all the hubs - it does not. Also lots of misspellings as "NotificatioHub" :) ) I find the new ARM stuff obtuse with zero examples. But I think from reading the code here on Github the following should work, but it gets a server error.

require 'azure_mgmt_resources'
require 'azure_mgmt_notification_hubs'
require 'pry'

subscription_id = "the-subscription-id"
my_namespace = "validnamespace"
my_resgroup = "validresourcegroup"

# Create authentication objects
token_provider = MsRestAzure::ApplicationTokenProvider.new("xxx-xxx-xxx", "yyy-yyy-yyy", "zzzzz=")
credentials = MsRest::TokenCredentials.new(token_provider)

# Create a client - a point of access to the API and set the subscription id
client = Azure::ARM::NotificationHubs::NotificationHubsManagementClient.new(credentials)
client.subscription_id = subscription_id

promise = client.notification_hubs.list(my_resgroup, my_namespace)
result = promise.value!

result.body.value.each do |val|
  if (val.name == "hub-with-known-valid-certs") then
    puts "Getting the hub"
    hpromise = client.notification_hubs.get(my_resgroup, my_namespace, val.name)
    hresult = hpromise.value!

    # A hub is returned, but all the *_credential members and properties are blank
    binding.pry

    puts "Getting #{val.name} PNS credentials"
    gpromise = client.notification_hubs.get_pns_credentials(my_resgroup, my_namespace, val.name)
    gresult = gpromise.value!

    #never gets here - crashes above gresult.
    binding.pry
  end
end

The error it returns is (slightly edited):

/Library/Ruby/Gems/2.0.0/gems/azure_mgmt_notification_hubs-0.2.1/lib/azure_mgmt_notification_hubs/notification_hubs.rb:751:in `block in get_pns_credentials': { (MsRestAzure::AzureOperationError)
  "message": "MsRestAzure::AzureOperationError",
  "request": {
    "base_uri": "https://management.azure.com",
    "path_template": "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.NotificationHubs/namespaces/{namespaceName}/notificationHubs/{notificationHubName}/pnsCredentials",
    "method": "post",
    "path_params": {
      "resourceGroupName": "validresourcegroup",
      "namespaceName": "my_namespace",
      "notificationHubName": "hub-with-known-valid-certs",
      "subscriptionId": "the-subscription-id"
    },
    "skip_encoding_path_params": null,
    "query_params": {
      "api-version": "2014-09-01"
    },
    "skip_encoding_query_params": null,
    "headers": {
      "x-ms-client-request-id": "c125260b-8e86-495b-bc49-2b08b61cb6cb",
      "accept-language": "en-US"
    },
    "body": null,
    "middlewares": [
      [
        "MsRest::RetryPolicyMiddleware",
        {
          "times": 3,
          "retry": 0.02
        }
      ],
      [
        "cookie_jar"
      ]
    ],
    "log": null
  },
  "response": {
    "body": "{\"error\":{\"message\":\"The format of value 'Azure-SDK-For-Ruby/0.2.1/' is invalid.\",\"code\":\"InternalServerError\"}}",
    "headers": {
      "cache-control": "no-cache",
      "pragma": "no-cache",
      "content-length": "112",
      "content-type": "application/json; charset=utf-8",
      "expires": "-1",
      "x-ms-request-id": "e9000fb2-5e53-463e-b55b-89c6524d0e3a_M2_M2",
      "server-sb": "Service-Bus-Resource-Provider/SN1",
      "server": "Service-Bus-Resource-Provider/SN1, Microsoft-HTTPAPI/2.0",
      "x-ms-failure-cause": "service",
      "x-ms-ratelimit-remaining-subscription-writes": "1199",
      "x-ms-correlation-request-id": "a9d0cf76-692b-4edc-a7dd-532aaf6dc1f4",
      "x-ms-routing-request-id": "SOUTHCENTRALUS:20160406T175344Z:a9d0cf76-692b-4edc-a7dd-532aaf6dc1f4",
      "strict-transport-security": "max-age=31536000; includeSubDomains",
      "date": "Wed, 06 Apr 2016 17:53:43 GMT",
      "connection": "close"
    },
    "status": 500
  }
}
    from /Library/Ruby/Gems/2.0.0/gems/concurrent-ruby-1.0.1/lib/concurrent/promise.rb:496:in `call'
    from /Library/Ruby/Gems/2.0.0/gems/concurrent-ruby-1.0.1/lib/concurrent/promise.rb:496:in `block in on_fulfill'
    from /Library/Ruby/Gems/2.0.0/gems/concurrent-ruby-1.0.1/lib/concurrent/executor/safe_task_executor.rb:24:in `call'
    from /Library/Ruby/Gems/2.0.0/gems/concurrent-ruby-1.0.1/lib/concurrent/executor/safe_task_executor.rb:24:in `block in execute'
    from /Library/Ruby/Gems/2.0.0/gems/concurrent-ruby-1.0.1/lib/concurrent/synchronization/mri_lockable_object.rb:38:in `block in synchronize'
    from /Library/Ruby/Gems/2.0.0/gems/concurrent-ruby-1.0.1/lib/concurrent/synchronization/mri_lockable_object.rb:38:in `synchronize'
    from /Library/Ruby/Gems/2.0.0/gems/concurrent-ruby-1.0.1/lib/concurrent/synchronization/mri_lockable_object.rb:38:in `synchronize'
    from /Library/Ruby/Gems/2.0.0/gems/concurrent-ruby-1.0.1/lib/concurrent/executor/safe_task_executor.rb:19:in `execute'
    from /Library/Ruby/Gems/2.0.0/gems/concurrent-ruby-1.0.1/lib/concurrent/promise.rb:526:in `block in realize'
    from /Library/Ruby/Gems/2.0.0/gems/concurrent-ruby-1.0.1/lib/concurrent/executor/ruby_thread_pool_executor.rb:348:in `call'
    from /Library/Ruby/Gems/2.0.0/gems/concurrent-ruby-1.0.1/lib/concurrent/executor/ruby_thread_pool_executor.rb:348:in `run_task'
    from /Library/Ruby/Gems/2.0.0/gems/concurrent-ruby-1.0.1/lib/concurrent/executor/ruby_thread_pool_executor.rb:337:in `block (3 levels) in create_worker'
    from /Library/Ruby/Gems/2.0.0/gems/concurrent-ruby-1.0.1/lib/concurrent/executor/ruby_thread_pool_executor.rb:320:in `loop'
    from /Library/Ruby/Gems/2.0.0/gems/concurrent-ruby-1.0.1/lib/concurrent/executor/ruby_thread_pool_executor.rb:320:in `block (2 levels) in create_worker'
    from /Library/Ruby/Gems/2.0.0/gems/concurrent-ruby-1.0.1/lib/concurrent/executor/ruby_thread_pool_executor.rb:319:in `catch'
    from /Library/Ruby/Gems/2.0.0/gems/concurrent-ruby-1.0.1/lib/concurrent/executor/ruby_thread_pool_executor.rb:319:in `block in create_worker'
devigned commented 8 years ago

Sorry... We'll take a look at the spelling errors. This code is generated from the spec here: https://github.com/Azure/azure-rest-api-specs/blob/master/arm-notificationhubs/2014-09-01/swagger/notificationhubs.json.

The error message is really weird... It looks like the service is failing on parsing the UserAgent... Huh, that's a new one.

@vishrutshah can you take a look at this?

RocketPop commented 8 years ago

Thanks for the quick update @devigned ! Hopefully that error can be addressed and my hub updater can finally work this year :) BTW - Is there any information on the "why and how" of that API spec you linked? Like are the list() and get() methods supposed to fill out parameters, usage scenarios for different calls? It shows the mechanics of what to do but is missing context and intention/exposition IMO :)

devigned commented 8 years ago

@smithab please provide some insight when you have a bit.

devigned commented 8 years ago

@RocketPop, what do you mean about the "why and how"?

I'll take a swing at what I think you are asking about. Basically, the spec I pointed you to is used via https://github.com/azure/autorest to generate out the code you used to call notification hubs. It's an OpenAPI specification (Swagger) for the service and if updated will update the code in this repo upon regeneration.

RocketPop commented 8 years ago

Hi @devigned - I get that this is auto-generated from that API spec. The stuff that is marked as "ARM" doesn't match the samples and docs of the old azure sdk/api. But I don't see new documentation other than the mechanics of using these generated API's. For example - there is a get for pnsCredentials but no set. How do I set them? Can I set them? The portal can so I must be able to somehow :) The get() that fetches an individual NotificationHub (NotificationHubs_Get - disregarding the description that says list) appears not to fetch the NotificationHubProperties. Is it supposed to? A low-level api spec is silent on questions like this. I am left to assume I'm using something incorrectly. I don't see the get for namespace credentials here: (https://msdn.microsoft.com/library/azure/dn495827.aspx) but I also can't find what the swagger shows as a per hub getter here: ( "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.NotificationHubs/namespaces/{namespaceName}/notificationHubs/{notificationHubName}/pnsCredentials" ). That getter has the weird User Agent error - so I had to stop investigating that for now. There is certificate data in ApnsCredentialProperties - The API spec is silent on what format that cert is - pfx, p12, cer? There's also an endpoint member - what is that about? :) I can find it in a comment on the Create NotificationHub docs on the Rest API page above, but that's not where I would think to look. I'm looking at pages like ( https://msdn.microsoft.com/en-us/library/dn495628.aspx ) that explain what you can do - the steps required in the API to do that (i.e. exposition) - then they show the mechanics of calling it with some code. Hope this makes sense - thanks for the discussion - I intend it to be constructive, not whining!

smithaborkar commented 8 years ago

@RocketPop. When you want to create/update a notificationHub you would use the PUT operation on the following :

"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.NotificationHubs/namespaces/{namespaceName}/notificationHubs/{notificationHubName}/

We do not return any of the PNS credentials when you do a GET on that hub cos its supposed to be a credential. If you need to view the PNSCredentials you need to do a POST on the following

/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.NotificationHubs/namespaces/{namespaceName}/notificationHubs/{notificationHubName}/pnsCredentials

Will look into the exception you are getting and update this thread

devigned commented 8 years ago

@RocketPop this is awesome feedback! Thank you!

@thedanfernandez do you have any insight into why the ARM documentation for NotificationHubs service is not available?

smithaborkar commented 8 years ago

@RocketPop I am able to repro this exception. Will make a fix on our end.

RocketPop commented 8 years ago

@smithab, @devigned thanks for the updates and the help. I'll watch this space for a fix to the user agent problem. As for the certs - I see what you mean, but it's a little odd. If I don't need elevated privileges or extra authentication to call this: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.NotificationHubs/namespaces/{namespaceName}/notificationHubs/{notificationHubName}/pnsCredentials then it's just one more hoop to jump through with extra documentation for that call. Personal opinion - it's not more secure, it's just harder to use :) To support the spirit of your explanation - certs should be broken out of the NotificationHubProperties object and put in their own GET that can only be called with a specific security role.

devigned commented 8 years ago

@smithab it's been about a month. Do you have any update on this issue?

smithaborkar commented 8 years ago

Hi, yes the fix got deployed last week. @RocketPop : You should not see this error anymore.