If your Chef environment has grown and its time for a cleanup, here is an easy way to find unused and obsolete Roles.
This works as long as the roles/*.rb files are named exactly like the roles.
# in roles/ directory do
for f in *.rb; do echo $f; done | cut -d'.' -f1 | tr '\n' '\0'|xargs -0 -L1 -I '$' sh -c "echo '$:';knife search node 'role:$'|grep Node" > result.txt
# then
for f in *.rb; do echo $f; done | cut -d'.' -f1 | tr '\n' '\0'|xargs -0 -L1 -I '$' sh -c "echo '$:';knife search node 'roles:$'|grep Node" > result2.txt
This will output role name and the hosts using it. Roles not having nodes in both result files are unused and can be removed.
Sample output
auth-app:
Node Name: auth-app2.prod1.example.lan
Node Name: auth-app3.prod1.example.lan
Node Name: auth-app1.prod2.example.lan
unused-role:
ch-elasticsearch:
Node Name: ch-esearch3.prod1.example.lan
Node Name: ch-esearch2.prod2.example.lan
Reason why you need to run it twice is first command searches for nodes having exactly that role and second one searching in expanded run lists.