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 Tencent Cloud provider for add_cloud_metadata proccessor #4023

Merged
merged 2 commits into from
Apr 21, 2017

Conversation

athom
Copy link
Contributor

@athom athom commented Apr 16, 2017

Hey there,
Currently the add_cloud_metadata processor supports 3 main providers by default, it's awesome!

However, a lot of companies in China prefer to use Tencent Cloud and AliCloud. AFAIK, the two providers did hold a large marke share. It will be nice to support these two providers by default too.

This PR amis to support Tencent Cloud. Unlike the other 3 providers, Tencent Cloud Metadata behaves a bit different.
You can not get the full JSON format metadata in one single round trip, only one field of the metadata can by queried every request.
For example, you wanna to get the the metadata contains instance-id and region, you have to send two requests separately.

curl http://metadata.tencentyun.com/meta-data/instance-id
curl http://metadata.tencentyun.com/meta-data/placement/region

Here is the document

Summary of the changes:

  • refactor and abstract a data struct named fetcher who did the network/text processing job for specified provider.
  • generalize origin fetchJSON to fetcher.fetchRaw.
  • allow multiple requests to fetch the full metadata in the provider's fetcher level.
  • replace hard code of the goroutinue number in waiting loop with dynamic length cauculation.

Ps, I tested it on my qcloud instance with os ubuntu-16.04 , I can offer a instance for testing, feel free to ping me if you need one.

@elasticmachine
Copy link
Collaborator

Jenkins standing by to test this. If you aren't a maintainer, you can ignore this comment. Someone with commit access, please review this and clear it for Jenkins to run.

1 similar comment
@elasticmachine
Copy link
Collaborator

Jenkins standing by to test this. If you aren't a maintainer, you can ignore this comment. Someone with commit access, please review this and clear it for Jenkins to run.

@tsg tsg added the review label Apr 17, 2017
@@ -31,10 +31,17 @@ const (

// Google GCE Metadata Service
gceMetadataURI = "/computeMetadata/v1/?recursive=true&alt=json"

// Tencent Clound Metadata Service
qcloudMetadataHost = "metadata.tencentyun.com"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we are starting to add more cloud providers it would be nice to have each provider in its own file. This makes it easier to spot which parts are specific to a provider and which is the shared code. Just a general note, could also be done in a follow up PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, I will apply it when implement AliCloud metadata in next PR ;)

@monicasarbu monicasarbu requested a review from andrewkroh April 19, 2017 10:44
Copy link
Contributor

@ruflin ruflin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I left some minor comments. Could you add an entry to CHANGELOG.asciidoc?

In case you do the refactoring with a future PR, I would appreciate if you open 2 PR's. One with the refactoring and one with the additional cloud provider so we can review it separately.

I would also like to get @andrewkroh review on this one.

@andrewkroh In case we add more and more providers, we should probably check again if all of them should be enabled by default.

@@ -266,11 +266,12 @@ The `add_cloud_metadata` processor enriches each event with instance metadata
from the machine's hosting provider. At startup it will detect the hosting
provider and cache the instance metadata.

Three cloud providers are supported.
Four cloud providers are supported.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably drop the number here. More like The following cloud providers are supported:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion

}

func newCloudMetadata(c common.Config) (processors.Processor, error) {
timeout := 3 * time.Second
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we introduce a constant for that so it is easy to find? Something like defaultTimeout?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This timeout value should be unpacked from the configuration data. Otherwise it is hardcoded here.

Copy link
Contributor Author

@athom athom Apr 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, it's hardcoded here, already move timeout configuration out of the getMetadataURLs and put it directly in newCloudMetadata.
The pool config is unpacked 5 times here 🤒, but I think it is acceptable here since it only run once in the startup phase.

@andrewkroh
Copy link
Member

jenkins, test it

Copy link
Member

@andrewkroh andrewkroh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@athom Thanks for the contribution! The refactoring looks good. It does need a change to read the timeout value from the config. My other comments are just minor doc issues and naming suggestions.


- Amazon Elastic Compute Cloud (EC2)
- Digital Ocean
- Google Compute Engine (GCE)
- [Tencent Cloud](https://www.qcloud.com/?lang=en) (QCloud)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe this is the proper format for a hyperlink in asciidoc. I think the format is http://google.com[Google Search].

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤦‍♂️ a clumsy product placement 😢
sorry for really green hand in asciidoc.

qcloudMetadataHost = "metadata.tencentyun.com"
qcloudMetadataInstanceIdURI = "/meta-data/instance-id"
qcloudMetadataRegionURI = "/meta-data/placement/region"
qcloudMetadataZoneURI = "/meta-data/placement/zone"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know if they have versioned endpoints that we can point to (like /v1/meta-data/...) ? It would be preferable to use those if available so that there is less risk of the API changing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK, there is no plan for Tentcent Qcloud endpoints to support /v1/xxx, the metadata service is maintained in my team :)
And the other provider AliCloud also has no versioned endpoints neither, at least no indications from the Chinese documents.

func (r result) String() string {
return fmt.Sprintf("result=[provider:%v, error=%v, metadata=%v]",
r.provider, r.err, r.metadata)
type pick func([]byte, *result) error
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a godoc comment describing pick and its params and return value. And maybe change the name if you can think of something more descriptive (some ideas responseUnmarshaller, responseHandler).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, change applied.

return
}

// fetchMetadata query metadata from a hosting provider's metadata service.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/query/queries/

}

// fetchMetadata query metadata from a hosting provider's metadata service.
// some providers require multiple HTTP request to gather the whole metadata
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/some/Some/, s/request/requests/, and a period at the end of the line.

MetadataHostAndPort: metadataHost,
Timeout: 3 * time.Second,
MetadataHostAndPort: defaultHost,
Timeout: timeout,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Timeout value is not used here so it needs to be relocated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

relocated.

}

func newCloudMetadata(c common.Config) (processors.Processor, error) {
timeout := 3 * time.Second
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This timeout value should be unpacked from the configuration data. Otherwise it is hardcoded here.

)

var debugf = logp.MakeDebug("filters")

// metadata schemas for all prividers
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/prividers/providers./

"region": c.Str("region"),
"availability_zone": c.Str("zone"),
}.Apply(m)
return out
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like this doesn't even need to use the Schema as you have already built up the map[string]interface{} with the proper key names and data types. So I think this could just become return common.MapStr(m).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}

// fetchJSON query metadata from a hosting provider's metadata service.
func fetchJSON(
// fetchRaw query raw metadata from a hosting provider's metadata service.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/query/queries/


// Tencent Clound Metadata Service
qcloudMetadataHost = "metadata.tencentyun.com"
qcloudMetadataInstanceIdURI = "/meta-data/instance-id"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[golint] reported by reviewdog 🐶
const qcloudMetadataInstanceIdURI should be qcloudMetadataInstanceIDURI

@andrewkroh
Copy link
Member

jenkins, test it

@ruflin ruflin merged commit be99062 into elastic:master Apr 21, 2017
@ruflin
Copy link
Contributor

ruflin commented Apr 21, 2017

@athom Thanks a lot for the contribution.

@athom
Copy link
Contributor Author

athom commented Apr 22, 2017

Thanks for the merge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants