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

Adding etc_hosts module #19283

Closed
wants to merge 11 commits into from
Closed

Conversation

jtyr
Copy link
Contributor

@jtyr jtyr commented Dec 13, 2016

ISSUE TYPE

New Module Pull Request.

COMPONENT NAME

hosts

ANSIBLE VERSION

For Ansible 2.3.

SUMMARY

This module adds the ability to add, remove and modify records in the /etc/hosts file.

@jtyr
Copy link
Contributor Author

jtyr commented Dec 13, 2016

Migrated from ansible/ansible-modules-extras#3457

@jtyr
Copy link
Contributor Author

jtyr commented Dec 13, 2016

@drybjed I have moved this PR from the obsolete ansible-modules-extras project to here and would like to ask you to review it. You can still use this playbook for the tests.

@ansibot ansibot added affects_2.3 This issue/PR affects Ansible v2.3 module This issue/PR relates to a module. new_plugin This PR includes a new plugin. plugin needs_rebase https://docs.ansible.com/ansible/devel/dev_guide/developing_rebasing.html needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. and removed needs_rebase https://docs.ansible.com/ansible/devel/dev_guide/developing_rebasing.html needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. labels Dec 13, 2016
@ansibot ansibot added needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. and removed needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. labels Dec 20, 2016
@ansibot ansibot added needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. and removed needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. labels Jan 2, 2017
@jimi-c jimi-c removed the plugin label Jan 4, 2017
@ansibot ansibot added needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. new_module This PR includes a new module. community_review In order to be merged, this PR must follow the community review workflow. and removed needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. labels Jan 5, 2017

DOCUMENTATION = '''
---
module: hosts
Copy link
Contributor

Choose a reason for hiding this comment

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

Name seems a little too generic. Maybe etc_hosts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

argument_spec=dict(
ip=dict(required=True),
hostname=dict(),
alias=dict(type='raw'),
Copy link
Contributor

Choose a reason for hiding this comment

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

list might be a better type and then just leave off the space separated feature (comma separated should work IIRC)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

from ansible.module_utils._text import to_bytes
import os
import re
import tempfile
Copy link
Member

Choose a reason for hiding this comment

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

These imports are incorrectly placed above the DOCUMENTATION/EXAMPLES/etc strings. The ansible standard is that these imports go below the documentation, and not at the top of the file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

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 as of yet see the requested change. Did you push it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

About to push it ;o)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just pushed it.

from ansible.module_utils._text import to_bytes
import os
import re
import tempfile
Copy link
Contributor

Choose a reason for hiding this comment

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

imports should go below the "ansible data variables" (DOCUMENTATION, RETURNS, etc). That keeps code that is used in the module together instead of separating it with many lines that aren't used in the module at all. Imports are usually broken into three parts, first stdlib, then 3rd party (none here), and finally from the project itself.

Other note, need to add metadata.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think you mentioned yesterday that PEP8 is allowing variables above imports. The reality is different:

E402 module level import not at top of file

That makes me very sad to produce a module which is not PEP8 compliant ;o(((((((((((((((((

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ehm, it's PEP8 compliant now ;o)

@abadger
Copy link
Contributor

abadger commented Jan 19, 2017

One thing that always comes up with modules like this are "Why is it better to have a module than to use template (or even lineinfile)?" So be prepared for that question :-)

@jtyr jtyr force-pushed the ansible-modules-extras/pull/3457 branch from f07ba1c to 8222d68 Compare January 20, 2017 00:00
YAML list or a string containing comma separated list.
path:
required: false
default: /etc/hosts
Copy link
Contributor

@jasperla jasperla Jan 20, 2017

Choose a reason for hiding this comment

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

Wouldn't it be better to adjust the name of the module to hosts ? It seems odd to effectively hardcode the filepath in the module name, while at the same time allowing to adjust the file path. This module might also be extended to add support for managing the Windows hosts file,

Furthermore both Puppet and Salt call their analogue type/modules also hosts.

Edit: I see this module used to be named hosts and was renamed after @abadger his feedback. However I wonder if Windows support and the more common naming in the larger ecosystem was considered at the time.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have changed the name of the module from hosts to etc_hosts as suggested by @abadger because the name hosts seems to be too generic. I'm open to suggestions if you can think of a better name than hosts or etc_hosts.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think hosts is a name that does not violate the principle of least surprise. I merely wanted to point the rest of the cfg mgmt ecosystem and possible Windows support. Let's see what @abadger thinks about it given the above.

Copy link
Contributor

Choose a reason for hiding this comment

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

I like 'etc_hosts' > 'hosts'. Especially if the intention is to support just unix style /etc/hosts.

If other formats/types is in the future, maybe 'hosts_file' ?

Copy link
Contributor

Choose a reason for hiding this comment

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

@jtyr is it the intention to only support non-windows?

@ansibot ansibot added needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. and removed community_review In order to be merged, this PR must follow the community review workflow. labels Jan 25, 2017
# Change file attributes if needed
if os.path.isfile(module.params['path']):
file_args = module.load_file_common_arguments(module.params)
changed = module.set_fs_attributes_if_different(file_args, changed)
Copy link
Contributor

Choose a reason for hiding this comment

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

Will this handle a 'chattr +i /etc/hosts' or otherwise immutable /etc/hosts (docker does some variant of that I think?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it will allow to specify the attributes option as in the file module.

changed = module.set_fs_attributes_if_different(file_args, changed)

# Print status of the change
module.exit_json(changed=changed, state=state, diff=diff)
Copy link
Contributor

@alikins alikins Jan 26, 2017

Choose a reason for hiding this comment

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

I'd like to see the return include a data structure of /etc/hosts content. Maybe a serializeable version of the EtcHosts object? (not a requirement, just a nice to have)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For what purpose?

Copy link
Contributor

Choose a reason for hiding this comment

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

register it in a playbook and use it later. The module has already parsed the file into a object (self.lines and its records). That avoids the need to refetch and do string parsing to inspect the results.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think so that full hosts file should be returned by the module. I would say that only the added, removed, modified result should be returned.

Copy link
Member

Choose a reason for hiding this comment

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

that is why we have a 'diff' facility for modules

@alikins
Copy link
Contributor

alikins commented Jan 26, 2017

Code/docs looks good to me. Have a couple of minor suggestions, but LGTM.

line['valid'] and
line['ip'] == self.params['ip'] and (
self.params['hostname'] is None or
line['hostname'] == self.params['hostname'])):
Copy link
Contributor

Choose a reason for hiding this comment

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

I would be tempted to extract this check into a method or two. (To simplify reading the logic, and also to make it easier to easier to unit test).

@jtyr jtyr force-pushed the ansible-modules-extras/pull/3457 branch from 184a23c to 949acc5 Compare January 27, 2017 15:42
@jtyr jtyr force-pushed the ansible-modules-extras/pull/3457 branch 2 times, most recently from cfb02fd to 07324ee Compare January 27, 2017 15:48
'''


class EtcHosts:
Copy link
Contributor

Choose a reason for hiding this comment

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

SHould inherit from object because of python2

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Isn't that the default?

Copy link
Contributor Author

@jtyr jtyr Feb 2, 2017

Choose a reason for hiding this comment

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

@abadger I can fix that if that's really so important. But there is another 39 modules using exactly the same syntax and they don't seem to break anything:

$ egrep -R '^\s*class .[^(]*:' *
cloud/docker/_docker.py:class ContainerSet:
cloud/centurylink/clc_modify_server.py:class ClcModifyServer:
cloud/centurylink/clc_blueprint_package.py:class ClcBlueprintPackage:
cloud/centurylink/clc_firewall_policy.py:class ClcFirewallPolicy:
cloud/centurylink/clc_alert_policy.py:class ClcAlertPolicy:
cloud/centurylink/clc_aa_policy.py:class ClcAntiAffinityPolicy:
cloud/centurylink/clc_server.py:class ClcServer:
cloud/centurylink/clc_loadbalancer.py:class ClcLoadBalancer:
cloud/centurylink/clc_server_snapshot.py:class ClcSnapshot:
cloud/amazon/ec2_elb.py:class ElbManager:
cloud/amazon/ecs_ecr.py:class EcsEcr:
cloud/amazon/ecs_cluster.py:class EcsClusterManager:
cloud/amazon/rds.py:class RDSConnection:
cloud/amazon/rds.py:class RDS2Connection:
cloud/amazon/rds.py:class RDSDBInstance:
cloud/amazon/rds.py:class RDS2DBInstance:
cloud/amazon/rds.py:class RDSSnapshot:
cloud/amazon/rds.py:class RDS2Snapshot:
cloud/amazon/cloudtrail.py:class CloudTrailManager:
cloud/amazon/cloudfront_facts.py:class CloudFrontServiceManager:
cloud/amazon/cloudformation_facts.py:class CloudFormationServiceManager:
cloud/amazon/ecs_service_facts.py:class EcsServiceManager:
cloud/amazon/lambda_event.py:class AWSConnection:
cloud/amazon/ecs_taskdefinition.py:class EcsTaskManager:
cloud/amazon/lambda_alias.py:class AWSConnection:
cloud/amazon/ecs_task.py:class EcsExecManager:
cloud/amazon/ec2_customer_gateway.py:class Ec2CustomerGatewayManager:
cloud/amazon/ecs_service.py:class EcsServiceManager:
cloud/google/gce.py:class LazyDiskImage:
cloud/misc/xenserver_facts.py:class XenServerFacts:
clustering/consul_acl.py:class Rules:
clustering/consul_acl.py:class Rule:
monitoring/icinga2_feature.py:class Icinga2FeatureHelper:
network/dnsmadeeasy.py:class DME2:
network/omapi_host.py:class OmapiHostManager:
packaging/os/rpm_key.py:class RpmKey:
packaging/language/maven_artifact.py:class MavenDownloader:
remote_management/stacki/stacki_host.py:class StackiHost:
web_infrastructure/jenkins_job.py:class JenkinsJob:

Copy link
Member

Choose a reason for hiding this comment

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

I would recommend updating to inherit from object. Just because others did it or are doing it, doesn't necessarily make it a thing we wish to have.

We are trying to improve and standardize on implementations, and the preference here is that we standardize on inheriting from object.

A future task can be to improve modules where this was not followed.

Copy link
Contributor

Choose a reason for hiding this comment

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

No, it doesn't become the default until Python3.0

@abadger
Copy link
Contributor

abadger commented Feb 2, 2017

Discussed at the meeting today. The module is as good as it can be but we're unable to come to an agreement between the author and the project on the remaining point of where the imports belong. Since the module's actions can be performed via other modules, we're choosing to decline this submission. It can be pushed to galaxy in a role if you wish, though, and others can install and use it from there.

@abadger abadger closed this Feb 2, 2017
@abadger
Copy link
Contributor

abadger commented Feb 21, 2017

At the Feb 9th meeting this cam up for a vote. Unfortunately, the vote came out against merging: -1:5, 0:3, +1:1. The rationale was due to redundancy with template and concerns about cross-platform maintainability. can still be hosted on galaxy in a role. We're discussing a proposal for an "ansible-installer" program which can make things hosted on galaxy more discoverable but that's something for the future.

@abadger abadger closed this Feb 21, 2017
@jtyr jtyr mentioned this pull request Sep 21, 2017
@ansible ansible locked and limited conversation to collaborators Apr 26, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
affects_2.3 This issue/PR affects Ansible v2.3 module This issue/PR relates to a module. needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. new_module This PR includes a new module. new_plugin This PR includes a new plugin.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants