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

Prevent reparenting a block with itself #36075

Merged
merged 2 commits into from Feb 13, 2018
Merged

Conversation

sivel
Copy link
Member

@sivel sivel commented Feb 12, 2018

SUMMARY

We have been noticing that the parent tree for blocks is mutated and grows to large sizes. We have partially mitigated the problem in previous changes, but as a result the number of dynamic includes was limited in number due to recursion errors.

This change ensures that we never reparent a block with itself, causing a block explosion and recursion errors.

This also drastically speeds up dynamic task includes over time.

ISSUE TYPE
  • Bugfix Pull Request
COMPONENT NAME

lib/ansible/playbook/base.py
lib/ansible/playbook/block.py

ANSIBLE VERSION
2.4
2.5
2.6
ADDITIONAL INFORMATION

Output of parent lineage from Strategy._load_included_file during a successive 100 include_taskss in a flat playbook (reproducer from #36053):

Before this change (failing on the 42nd):

BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781459104)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781459160)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781459216)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781459272)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781459328)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781459384)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781459440)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781459496)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781459552)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781459608)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781459664)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781459720)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781459776)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781459832)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781459888)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781459944)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781460000)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781460056)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781460112)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781460168)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781460224)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781460280)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781460336)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781460392)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781460448)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781460504)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781460560)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781460616)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781460672)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781460728)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781460784)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781460840)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781460896)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781460952)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781461008)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781461064)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781461120)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781461176)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781461232)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781461288)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781461344)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4781461400)
(parent=BLOCK(uuid=784f43a0-97cc-6ecb-df87-000000000009)(id=4645217000)
(parent=None)))))))))))))))))))))))))))))))))))))))))))

After this change (executes all 100 include_tasks):

 BLOCK(uuid=784f43a0-97cc-6542-167b-000000000009)(id=4481635104)(parent=None))

@ansibot ansibot added WIP This issue/PR is a work in progress. Nevertheless it was shared for getting input from peers. bugfix_pull_request needs_triage Needs a first human triage before being processed. support:core This issue/PR relates to code supported by the Ansible Engineering Team. labels Feb 12, 2018
@bcoca bcoca removed the needs_triage Needs a first human triage before being processed. label Feb 12, 2018
@sivel
Copy link
Member Author

sivel commented Feb 12, 2018

This PR does not address recursion errors when using nested includes (eg a->b->c->d...) as opposed to a flat playbook/task file with many includes.

They have the same traceback, but different causes. In the nested include scenario, we should have that many parents, we just cannot copy all of the objects. Eventually we hit a recursion error.

@sivel sivel changed the title [WIP] Prevent reparenting a block with itself Prevent reparenting a block with itself Feb 13, 2018
@jimi-c
Copy link
Member

jimi-c commented Feb 13, 2018

FWIW, I tested a recursive include that made it over 250 levels deep before hitting a python recursion error, so hopefully no-one goes to that extreme with nested includes...

@sivel sivel merged commit 76ff3e9 into ansible:devel Feb 13, 2018
sivel added a commit that referenced this pull request Feb 13, 2018
* Prevent reparenting a block with itself

* Move __eq__ to Block, to avoid some unexpected problems

(cherry picked from commit 76ff3e9)
sivel added a commit that referenced this pull request Feb 13, 2018
* Prevent reparenting a block with itself

* Move __eq__ to Block, to avoid some unexpected problems

(cherry picked from commit 76ff3e9)
sivel added a commit that referenced this pull request Feb 13, 2018
@alikins
Copy link
Contributor

alikins commented Feb 13, 2018

Since this is changing how some of the playbook objects compares work, I updated a branch with some playbook object compare tests at #36132 if it would be helpful for testing.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug This issue/PR relates to a bug. support:core This issue/PR relates to code supported by the Ansible Engineering Team. WIP This issue/PR is a work in progress. Nevertheless it was shared for getting input from peers.
Projects
Development

Successfully merging this pull request may close these issues.

None yet

5 participants